Poker hand analyser: Difference between revisions
Content added Content deleted
No edit summary |
No edit summary |
||
Line 1: | Line 1: | ||
⚫ | |||
{{task}}Parse and rank 5-card poker hands |
|||
⚫ | |||
Each input card should be specified as a two characters indicating face and suit. For example 2d (two of diamonds). |
Each input card should be specified as a two characters indicating face and suit. For example 2d (two of diamonds). |
Revision as of 21:49, 9 December 2013
Poker hand analyser
You are encouraged to solve this task according to the task description, using any language you may know.
You are encouraged to solve this task according to the task description, using any language you may know.
Create a program to parse a single 5 card poker hand and rank it according to the List of poker hands [1].
Each input card should be specified as a two characters indicating face and suit. For example 2d (two of diamonds).
Faces are: a, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, j, q, k
Suits are: h (hearts), d (diamonds), c (clubs), and s (spades). Or you can use the unicode suit characters: ♥ ♦ ♣ ♠
Duplicate cards are illegal.
The program should analyse a single hand and produce one of the following outputs:
straight-flush four-of-a-kind full-house flush straight three-of-a-kind two-pair one-pair high-card invalid
Examples
2♥ 2♦ 2♣ k♣ q♦: three-of-a-kind 2♥ 5♥ 7♦ 8♣ 9♠: high-card a♥ 2♦ 3♣ 4♣ 5♦: straight 2♥ 3♥ 2♦ 3♣ 3♦: full-house 2♥ 7♥ 2♦ 3♣ 3♦: two-pair 2♥ 7♥ 7♦ 7♣ 7♠: four-of-a-kind 10♥ j♥ q♥ k♥ a♥: straight-flush
Perl 6
This solution is written entirely as a Perl 6 grammar. <lang perl6> use v6;
grammar PokerHand {
# Perl6 Grammar to parse and rank 5-card poker hands # E.g. PokerHand.parse("2♥ 3♥ 2♦ 3♣ 3♦");
rule TOP { <hand>
:my ($n, $flush, $straight); { $n = n-of-a-kind($<hand>); $flush = flush($<hand>); $straight = straight($<hand>); } <rank($n, $flush, $straight)> }
proto token suit {*} token suit:sym<♥> {<sym>} token suit:sym<♦> {<sym>} token suit:sym<♠> {<sym>} token suit:sym<♣> {<sym>}
token face { <[2..9]> | 10 | j | q | k | a }
token card {<face><suit> <?{ my $card = ~$/; note "Hey, were'd that extra $card come from?" if %*PLAYED{$card};
! %*PLAYED{$card}++; }> }
rule hand { :my %*PLAYED; { %*PLAYED = () }
[ <card> ]**5 }
sub played($card) { note "Hey, were'd that extra $card come from?" if %*PLAYED{$card}; return %*PLAYED{$card}++; }
token rank($n, $flush, $straight) { $<straight-flush> = <?{$straight && $flush}> || $<four-of-a-kind> = <?{$n[0] == 4}> || $<full-house> = <?{$n[0] == 3 && $n[1] == 2}> || $<flush> = <?{$flush}> || $<straight> = <?{$straight}> || $<three-of-a-kind> = <?{$n[0] == 3}> || $<two-pair> = <?{$n[0] == 2 && $n[1] == 2}> || $<one-pair> = <?{$n[0] == 2}> || $<high-card> = <?> }
sub n-of-a-kind($/) { my %n;
for @<card> -> $/ { %n{ ~$<face> }++ } return %n.values.sort: {$^b <=> $^a}; }
sub flush($/) { my %m;
for @<card> -> $/ { %m{ ~$<suit> }++ } return +%m.keys == 1; }
sub straight($/) { # allow both ace-low and ace-high straights my @seq = 'a', 2 .. 10, < j q k a >; my %got;
for @<card> -> $/ { %got{ ~$<face> }++ }
my $run = 0; for @seq { if %got{ $_ } { return True if ++$run >= 5; } else { $run = 0; } } return False; }
}
for ("2♥ 2♦ 2♣ k♣ q♦",
"2♥ 5♥ 7♦ 8♣ 9♠", "a♥ 2♦ 3♣ 4♣ 5♦", "2♥ 3♥ 2♦ 3♣ 3♦", "2♥ 7♥ 2♦ 3♣ 3♦", "2♥ 7♥ 7♦ 7♣ 7♠", "10♥ j♥ q♥ k♥ a♥", ) { PokerHand.parse($_); my $rank = $<rank> ?? $<rank>.caps !! 'invalid'; say "$_: $rank";
}