Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save masak/364800 to your computer and use it in GitHub Desktop.
Save masak/364800 to your computer and use it in GitHub Desktop.
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