| 1 | use v6-alpha; |
|---|
| 2 | |
|---|
| 3 | # Brute force proof that every cribbage hand with a 5 is >= 2 points |
|---|
| 4 | # See http://perlmonks.org/index.pl?node_id=458728 for details |
|---|
| 5 | |
|---|
| 6 | # The following code will not work yet as of revision 4167 |
|---|
| 7 | # There are two bugs and two unimplemented features |
|---|
| 8 | # Bug 1 - t/pugsbugs/return_with_trailing_stuff.t |
|---|
| 9 | # Bug 2 - t/pugsbugs/postincrement_in_subscripts.t |
|---|
| 10 | # Feature 1 - t/operators/hyper.t (hyper dereferencing) |
|---|
| 11 | # Feature 2 - t/statements/last.t (last <label>) |
|---|
| 12 | |
|---|
| 13 | my $next = combo(5, new_deck()); |
|---|
| 14 | while $combo == 1 { |
|---|
| 15 | # Skip all hands that do not contain a 5 |
|---|
| 16 | # next if none( @combo.>>.<val> ) == 5; |
|---|
| 17 | |
|---|
| 18 | # Skip all hands that have a score of at least 2 |
|---|
| 19 | # next if score( @combo ) > 1; |
|---|
| 20 | |
|---|
| 21 | # Print out the rest |
|---|
| 22 | # say ~@combo.>>.<suit>; |
|---|
| 23 | } |
|---|
| 24 | |
|---|
| 25 | sub score ( @hand ) returns Int { |
|---|
| 26 | my $score = 0; |
|---|
| 27 | |
|---|
| 28 | # [234] of a kind |
|---|
| 29 | my %ordval; |
|---|
| 30 | for @hand.>>.<num> { %ordval{$_}++ }; |
|---|
| 31 | for %ordval.values { $score += $_ * $_ - 1 } |
|---|
| 32 | |
|---|
| 33 | # Flush |
|---|
| 34 | $score += ([eq] @hand[0..3].>>.<suit>) |
|---|
| 35 | ?? ([eq] @hand[3,4].>>.<suit>) ?? 5 !! 4 |
|---|
| 36 | !! 0; |
|---|
| 37 | |
|---|
| 38 | # Check for right-jack, @hand[-1] is community card |
|---|
| 39 | $score++ if grep { $_<num> == 11 && $_<suit> eq @hand[-1]<suit> }, @hand[0..3]; |
|---|
| 40 | |
|---|
| 41 | # Count 15's |
|---|
| 42 | my @vals = @hand>>.<val>; |
|---|
| 43 | for 2 .. 5 { |
|---|
| 44 | my $next = combo($_, @vals); |
|---|
| 45 | while my @combo = $next() { $score += 2 if ([+] @combo) == 15 } |
|---|
| 46 | } |
|---|
| 47 | |
|---|
| 48 | # Runs |
|---|
| 49 | SPAN: |
|---|
| 50 | for 5, 4, 3 -> $span { |
|---|
| 51 | for (sort { $^a <=> $^b }, %ordval.keys) -> $start { |
|---|
| 52 | if all( %ordval{$start .. $start + $span} ) > 1 { |
|---|
| 53 | $score += [*] %ordval{$start .. $start + $span}, $span; |
|---|
| 54 | last SPAN; |
|---|
| 55 | } |
|---|
| 56 | } |
|---|
| 57 | } |
|---|
| 58 | return $score; |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | sub combo (Int $by is copy, @list is copy) returns Ref { |
|---|
| 62 | my @position = 0 .. $by - 2, $by - 2; |
|---|
| 63 | my @stop = @list.elems - $by .. @list.end; |
|---|
| 64 | my $done = undef; |
|---|
| 65 | return sub { |
|---|
| 66 | return () if $done; |
|---|
| 67 | my $cur = @position.end; |
|---|
| 68 | while ++@position[ $cur ] > @stop[ $cur ] { |
|---|
| 69 | @position[ --$cur ]++; |
|---|
| 70 | next if @position[ $cur ] > @stop[ $cur ]; |
|---|
| 71 | my $new_pos = @position[ $cur ]; |
|---|
| 72 | @position[ $cur .. @position.end ] = $new_pos .. $new_pos + $by; |
|---|
| 73 | last; |
|---|
| 74 | } |
|---|
| 75 | $done = 1 if @position[ 0 ] == @stop[ 0 ]; |
|---|
| 76 | return @list[ @position ]; |
|---|
| 77 | }; |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | sub new_deck () returns Array { |
|---|
| 81 | return (1..13).map: -> $num { |
|---|
| 82 | <H D C S>.map: -> $suit { |
|---|
| 83 | { num => $num, val => $num > 10 ?? 10 !! $num, suit => $suit }; |
|---|
| 84 | } |
|---|
| 85 | }; |
|---|
| 86 | } |
|---|