in reply to How to write this in Perl 6?

Here's a version that works under pugs:
#!/usr/bin/pugs my @DATA = q:to/END/.split(/\n/); 08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48 END my @dir = map -> $i { [map {$i*$_}, 0..3] }, 1, 22, 21, 20; my @data = map { .comb, 0 }, @DATA; say max map -> $base { map -> $offs { [*] map { @data[ $base + $_ ] }, @$offs; }, @dir; }, 0..@data.end;
I would generally prefer to write max as [max], but that's not implemented yet. Also it prints the result in E notation, albeit with sufficient precision. I think there are probably ways to use hyperops to replace some of the maps, but I need to think about it some more. There are also some unimplemented cross operators that might replace nested maps.

Replies are listed 'Best First'.
Re^2: How to write this in Perl 6?
by blazar (Canon) on Dec 02, 2006 at 21:03 UTC
    Here's a version that works under pugs:

    (Needless to say,) whoa! That's great. Generally I avoid replying for TY-only posts and prefer to /msg instead. But I feel like doing so publicly for this time since it's so nice to actually test the thing myself. I tried a first time and pugs seemed not to like the method call on the HERE doc string. In fact I had 6.2.12 installed; I upgraded to 6.2.13 and it still complains about something:

    *** Cannot parse regex: \n *** Error: Error: Can't call method "__RUN__" on an undefined value.

    But it does spit out a value.

    I would generally prefer to write max as [max], but that's not implemented yet. Also it prints the result in E notation, albeit with sufficient precision.

    Indeed, especially since the original problem expected an exact answer in terms of an integer. (The value spitted out doesn't seem to match the Perl 5 version one, but that's definitely a side note in this context. I don't know whether that could be related to the messages above.)

    I think there are probably ways to use hyperops to replace some of the maps, but I need to think about it some more. There are also some unimplemented cross operators that might replace nested maps.

    That's great as well. The maps look very natural to me, but I'd be delighted to see what hyperops could do instead of them. And I'm particularly excited about the potential cross operators which I also find quite natural, in fact it's one of the first things I asked in p6l: I can do without them, but I miss them more than, say, the somewhat "dual" zip operator. Of course the advantage becomes more evident with more nesting levels than just two...

      Okay, if we install a workaround version of XX that only does two arrays (compliments of Gothmog++):
      multi infix:<XX> (@a, @b) is equiv(&infix:<¥>) { @a.map: -> $a { @b.map: -> $b { ($a, $b) } } }
      then the following seems to work in the devel version of pugs:
      my @dir = map -> $i { [map {$i*$_}, 0..3] }, 1, 22, 21, 20; my @data = map { .comb, 0 }, @DATA; say max gather { for ^@data XX @dir { take int [*] @data[ $^base »+« $^offs ]; } }
      The first two lines are unchanged. I used gather/take to let me use a for loop and get the inputs in front. The int suppresses the floating notation. The two parameters are passed using placeholder variables, which work as long as they're not nested inside internal braces. (They rely on "base" coming before "offs" in alphabetical order.) And I just used a slice to pull out the four values instead of another map. (Note also that the hyperoperator is still behaving under the old specs of dwimming both sides, but that actually won't work under the latest specs, which requires the quote to be reversed to get dwimmery on that side.) Oh, I also used the unary ^ to get a range from 0 up to the size of the array, which also helped because the XX doesn't quite parse with the correct precedence yet for some reason, so saying 0..^@data would have required extra parens in the current pugs.