Created
April 13, 2010 16:33
-
-
Save masak/364800 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use v6; | |
# enum Suit <spades hearts diamonds clubs>; | |
# enum Rank (2, 3, 4, 5, 6, 7, 8, 9, 10, | |
# 'jack', 'queen', 'king', 'ace'); | |
class DIY::Enum { | |
has Str $.key; | |
has Str $.value; | |
method new(Str $key) { | |
self.bless(*, :$key, :value(self.enums{$key} // die "Illegal key $key")) | |
} | |
method pick($amount = 1) { | |
if $amount ~~ Whatever { | |
return map { self.new($_) }, self.enums.keys.pick(*) | |
} | |
elsif $amount == 1 { | |
return self.new(self.enums.keys.pick); | |
} | |
else { | |
die "Can't handle non-1-non-* case"; | |
} | |
} | |
method Num { | |
$.value | |
} | |
} | |
class Suit is DIY::Enum { | |
method enums() { | |
hash | |
spades => 0, | |
hearts => 1, | |
diamonds => 2, | |
clubs => 3, | |
} | |
} | |
class Rank is DIY::Enum { | |
method enums() { | |
hash | |
two => 0, | |
three => 1, | |
four => 2, | |
five => 3, | |
six => 4, | |
seven => 5, | |
eight => 6, | |
nine => 7, | |
ten => 8, | |
jack => 9, | |
queen => 10, | |
king => 11, | |
ace => 12, | |
} | |
} | |
class Card { | |
has Suit $.suit; | |
has Rank $.rank; | |
method Str { "$.rank.key() of $.suit.key()" } | |
} | |
subset PokerHand of Array where { .elems == 5 && !grep { $_ !~~ Card }, @($_) } | |
sub n-of-a-kind($n, @cards) { | |
for @cards>>.rank.uniq -> $rank { | |
return True if $n == grep $rank, @cards>>.rank; | |
} | |
return False; | |
} | |
subset Kwad of PokerHand where { n-of-a-kind(4, $_) } | |
subset ThreeOfAKind of Any where { n-of-a-kind(3, $_) } | |
subset OnePair of Any where { n-of-a-kind(2, $_) } | |
subset FullHouse of Any where OnePair & ThreeOfAKind; | |
subset Flush of PokerHand where -> @cards { [==] @cards>>.suit } | |
subset Straight of PokerHand where sub (@cards) { | |
my @sorted-cards = @cards.sort({ .rank }); | |
# my ($head, @tail) = @sorted-cards; | |
my $head = shift @sorted-cards; | |
my @tail = @sorted-cards; | |
for @tail -> $card { | |
return False if $card.rank != $head.rank + 1; | |
$head = $card; | |
} | |
return True; | |
} | |
subset StraightFlush of Flush where Straight; | |
subset TwoPair of PokerHand where sub (@cards) { | |
my $pairs = 0; | |
for @cards>>.rank.uniq -> $rank { | |
++$pairs if 2 == grep $rank, @cards>>.rank; | |
} | |
return $pairs == 2; | |
} | |
sub classify(PokerHand $_) { | |
when StraightFlush { 'straight flush', 8 } | |
when Kwad { 'four of a kind', 7 } | |
when FullHouse { 'full house', 6 } | |
when Flush { 'flush', 5 } | |
when Straight { 'straight', 4 } | |
when ThreeOfAKind { 'three of a kind', 3 } | |
when TwoPair { 'two pair', 2 } | |
when OnePair { 'one pair', 1 } | |
when * { 'high cards', 0 } | |
} | |
my @deck; | |
for Suit.pick(*).eager X Rank.pick(*) { | |
# RAKUDO: This is wrong, and shouldn't be necessary. | |
my ($suit, $rank) = .[0], .[1]; | |
@deck.push( Card.new(:$suit, :$rank) ); | |
} | |
@deck .= pick(*); | |
my @hand1; | |
@hand1.push(@deck.shift()) for ^5; | |
my @hand2; | |
@hand2.push(@deck.shift()) for ^5; | |
say 'Hand 1: ', map { "\n $_" }, @hand1>>.Str; | |
say 'Hand 2: ', map { "\n $_" }, @hand2>>.Str; | |
my ($hand1-description, $hand1-value) = classify(@hand1); | |
my ($hand2-description, $hand2-value) = classify(@hand2); | |
say sprintf q[The first hand is a '%s' and the second one a '%s', so %s.], | |
$hand1-description, $hand2-description, | |
$hand1-value > $hand2-value | |
?? 'the first hand wins' | |
!! $hand2-value > $hand1-value | |
?? 'the second hand wins' | |
!! "the hands are of equal value"; # XXX: probably wrong |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment