| 1 | use v6-alpha; |
|---|
| 2 | |
|---|
| 3 | # See http://perlmonks.org/?node_id=440531 and 441347 for details |
|---|
| 4 | # Produces an infinite streams of merged primes that is evaluated lazily |
|---|
| 5 | |
|---|
| 6 | # original code (http://www.perlmonks.org/index.pl?node_id=453215) |
|---|
| 7 | sub lazy_merge1 (@list is copy) returns Ref { |
|---|
| 8 | my $last = 0; |
|---|
| 9 | |
|---|
| 10 | my $by_n = sub { my ($n, $k) = (shift(@_), 0); return sub { @_[0] ?? $k += $n !! $k } }; |
|---|
| 11 | for @list { $_ = $by_n( $_ ) } |
|---|
| 12 | |
|---|
| 13 | return sub { |
|---|
| 14 | my $low; |
|---|
| 15 | for ( @list ) { |
|---|
| 16 | my $val = $_(); |
|---|
| 17 | $val = $_( 'next' ) if $val <= $last; |
|---|
| 18 | $low = $val if (! defined $low) || ($val < $low); |
|---|
| 19 | } |
|---|
| 20 | return $last = $low; |
|---|
| 21 | }; |
|---|
| 22 | } |
|---|
| 23 | |
|---|
| 24 | # further perl6-ification (http://www.perlmonks.org/index.pl?node_id=453402) |
|---|
| 25 | sub lazy_merge2 (@list is copy) returns Sub { |
|---|
| 26 | my $last = 0; |
|---|
| 27 | |
|---|
| 28 | my $by_n = sub ($n) { my $k = 0; return -> $x { $x ?? $k += $n !! $k } }; |
|---|
| 29 | @list = @list.map:{ $by_n( $_ ) }; |
|---|
| 30 | |
|---|
| 31 | return sub { |
|---|
| 32 | my $low; |
|---|
| 33 | for ( @list ) -> $sub { |
|---|
| 34 | my $val = $sub(); |
|---|
| 35 | $val = $sub(<next>) if $val <= $last; |
|---|
| 36 | $low = $val if !$low.defined || $val < $low; |
|---|
| 37 | } |
|---|
| 38 | return $last = $low; |
|---|
| 39 | }; |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | # And again, golfing a bit as well (http://perlmonks.org/?node_id=463610) |
|---|
| 43 | sub lazy_merge3 (@list is copy) returns Sub { |
|---|
| 44 | my $last = 0; |
|---|
| 45 | |
|---|
| 46 | my &by_n = -> $n { my $k = 0; -> $x { $x ?? $k += $n !! $k } }; |
|---|
| 47 | @list .= map:{ by_n $_ }; |
|---|
| 48 | |
|---|
| 49 | sub { |
|---|
| 50 | my $low; |
|---|
| 51 | for @list -> $sub { |
|---|
| 52 | my $val = $sub(); |
|---|
| 53 | $val = $sub(<next>) if $val <= $last; |
|---|
| 54 | $low = $val unless $low && $low < $val; |
|---|
| 55 | } |
|---|
| 56 | $last = $low; |
|---|
| 57 | } |
|---|
| 58 | } |
|---|
| 59 | |
|---|
| 60 | my $end = @*ARGS[0] // 22; |
|---|
| 61 | my @prime = (2, 3, 5); |
|---|
| 62 | my &next1 = lazy_merge1( @prime ); |
|---|
| 63 | my &next2 = lazy_merge2( @prime ); |
|---|
| 64 | my &next3 = lazy_merge3( @prime ); |
|---|
| 65 | for 1..$end { say "v1: {next1} v2: {next2} v3: {next3}" }; |
|---|