Poker hand analyser: Difference between revisions

Added XPL0 example.
m (→‎{{header|REXX}}: added more descriptive error messages, added/changed whitespace and comments, used templates for the input and output sections.)
(Added XPL0 example.)
 
(62 intermediate revisions by 23 users not shown)
Line 9:
A poker hand is specified as a space separated list of five playing cards.
 
Each input card has two characters indicating face and suit.   For example:   '''2d'''   (two of diamonds).
 
Faces are: '''a''', '''2''', '''3''', '''4''', '''5''', '''6''', '''7''', '''8''', '''9''', '''10''', '''j''', '''q''', '''k'''
 
;Example:
Suits are: '''h''' (hearts), '''d''' (diamonds), '''c''' (clubs), and '''s''' (spades), or alternatively the unicode card-suit characters: ♥ ♦ ♣ ♠
::::'''2d'''       (two of diamonds).
 
 
 
Faces are:    '''a''', '''2''', '''3''', '''4''', '''5''', '''6''', '''7''', '''8''', '''9''', '''10''', '''j''', '''q''', '''k'''
 
Suits are:    '''h''' (hearts),   '''d''' (diamonds),   '''c''' (clubs),   and   '''s''' (spades),   or
<br>alternatively, &nbsp; the unicode card-suit characters: &nbsp;&nbsp; <big> ♥ ♦ ♣ ♠ </big>
 
 
Duplicate cards are illegal.
Line 29 ⟶ 37:
invalid
 
 
Examples:
;Examples:
2♥ 2♦ 2♣ k♣ q♦: three-of-a-kind
2♥ 5♥2♦ 7♦2♣ 8♣k♣ 9♠q♦: high three-of-a-cardkind
a♥2♥ 2♦5♥ 3♣7♦ 4♣8♣ 5♦9♠: straight high-card
2♥ 3♥a♥ 2♦ 3♣ 3♦4♣ 5♦: full-house straight
2♥ 7♥3♥ 2♦ 3♣ 3♦: two full-pairhouse
2♥ 7♥ 7♦2♦ 7♣3♣ 7♠3♦: four two-of-a-kind pair
10♥2♥ j♥7♥ q♥7♦ k♥7♣ a♥7♠: straight four-flushof-a-kind
4♥10♥ 4♠j♥ k♠q♥ 5♦k♥ 10♠a♥: one straight-pairflush
q♣4♥ 10♣4♠ 7♣k♠ 6♣5♦ 4♣10♠: flush one-pair
q♣ 10♣ 7♣ 6♣ q♣: invalid
 
The programs output for the above examples should be displayed here on this page.
Line 46 ⟶ 55:
# use the playing card characters introduced with Unicode 6.0 (U+1F0A1 - U+1F0DE).
# allow two jokers
::* use the symbol &nbsp; '''joker'''
::* duplicates would be allowed (for jokers only)
::* five-of-a-kind would then be the highest hand
Line 52 ⟶ 61:
 
;More extra credit examples:
joker 2♦ 2♠ k♠ q♦: three-of-a-kind
joker 5♥ 7♦ 8♠ 9♦: straight
joker 2♦ 3♠ 4♠ 5♠: straight
joker 3♥ 2♦ 3♠ 3♦: four-of-a-kind
joker 7♥ 2♦ 3♠ 3♦: three-of-a-kind
joker 7♥ 7♦ 7♠ 7♣: five-of-a-kind
joker j♥ q♥ k♥ A♥: straight-flush
joker 4♣ k♣ 5♦ 10♠: one-pair
joker k♣ 7♣ 6♣ 4♣: flush
joker 2♦ joker 4♠ 5♠: straight
joker Q♦ joker A♠ 10♠: straight
joker Q♦ joker A♦ 10♦: straight-flush
joker 2♦ 2♠ joker q♦: four-of-a-kind
 
 
;Related tasks:
* [[Playing cards]]
* [[Card shuffles]]
* [[Deal cards_for_FreeCell]]
* [[War Card_Game]]
* [[Go Fish]]
<br><br>
 
=={{header|11l}}==
{{trans|D}}
 
<syntaxhighlight lang="11l">F analyzeHandHelper(faceCount, suitCount)
V
p1 = 0B
p2 = 0B
t = 0B
f = 0B
fl = 0B
st = 0B
 
L(fc) faceCount
S fc
2 {I p1 {p2 = 1B} E p1 = 1B}
3 {t = 1B}
4 {f = 1B}
 
L(sc) suitCount
I sc == 5
fl = 1B
 
I !p1 & !p2 & !t & !f
V s = 0
L(fc) faceCount
I fc != 0
s++
E
s = 0
I s == 5
L.break
 
st = (s == 5) | (s == 4 & faceCount[0] != 0 & faceCount[1] == 0)
 
I st & fl {R ‘straight-flush’}
E I f {R ‘four-of-a-kind’}
E I p1 & t {R ‘full-house’}
E I fl {R ‘flush’}
E I st {R ‘straight’}
E I t {R ‘three-of-a-kind’}
E I p1 & p2 {R ‘two-pair’}
E I p1 {R ‘one-pair’}
E {R ‘high-card’}
 
F analyzeHand(inHand)
V handLen = 5
V face = ‘A23456789TJQK’
V suit = ‘SHCD’
V errorMessage = ‘invalid hand.’
 
V hand = sorted(inHand.split(‘ ’))
I hand.len != handLen
R errorMessage
I Set(hand).len != handLen
R errorMessage‘ Duplicated cards.’
 
V faceCount = [0] * face.len
V suitCount = [0] * suit.len
L(card) hand
I card.len != 2
R errorMessage
V? n = face.find(card[0])
V? l = suit.find(card[1])
I n == N | l == N
R errorMessage
faceCount[n]++
suitCount[l]++
 
R analyzeHandHelper(faceCount, suitCount)
 
L(hand) [‘2H 2D 2S KS QD’,
‘2H 5H 7D 8S 9D’,
‘AH 2D 3S 4S 5S’,
‘2H 3H 2D 3S 3D’,
‘2H 7H 2D 3S 3D’,
‘2H 7H 7D 7S 7C’,
‘TH JH QH KH AH’,
‘4H 4C KC 5D TC’,
‘QC TC 7C 6C 4C’]
print(hand‘: ’analyzeHand(hand))</syntaxhighlight>
 
{{out}}
<pre>
2H 2D 2S KS QD: three-of-a-kind
2H 5H 7D 8S 9D: high-card
AH 2D 3S 4S 5S: straight
2H 3H 2D 3S 3D: full-house
2H 7H 2D 3S 3D: two-pair
2H 7H 7D 7S 7C: four-of-a-kind
TH JH QH KH AH: straight-flush
4H 4C KC 5D TC: one-pair
QC TC 7C 6C 4C: flush
</pre>
 
=={{header|Ada}}==
 
{{works with|GNAT Ada 2022}}
 
<syntaxhighlight lang="ada">
pragma Ada_2022;
with Ada.Characters.Handling; use Ada.Characters.Handling;
with Ada.Containers.Generic_Constrained_Array_Sort;
with Ada.Text_IO; use Ada.Text_IO;
 
procedure Poker is
 
type Face_T is (two, three, four, five, six, seven, eight, nine, t, j, q, k, a);
for Face_T use (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
type Suit_T is (C, D, H, S);
type Card_T is record
Face : Face_T;
Suit : Suit_T;
end record;
 
subtype Hand_Index is Natural range 1 .. 5;
type Hand_T is array (Hand_Index) of Card_T;
type Test_Hand_Arr is array (Positive range <>) of Hand_T;
type Pip_Counter_T is array (Face_T range Face_T'Range) of Natural;
 
Pip_Counts : Pip_Counter_T := [others => 0];
 
Test_Hands : Test_Hand_Arr := [
1 => [(two, H), (two, D), (two, C), (k, S), (q, D)],
2 => [(two, H), (five, H), (seven, D), (eight, C), (nine, S)],
3 => [(a, H), (two, D), (three, C), (four, C), (five, D)],
4 => [(two, H), (three, H), (two, D), (three, C), (three, D)],
5 => [(two, H), (seven, H), (two, D), (three, C), (three, D)],
6 => [(two, H), (seven, H), (seven, D), (seven, C), (seven, S)],
7 => [(t, H), (j, H), (q, H), (k, H), (a, H)],
8 => [(four, H), (four, S), (k, S), (five, D), (t, S)],
9 => [(q, C), (t, C), (seven, C), (six, C), (q, C)]
];
 
function "<" (L, R : Card_T) return Boolean is
begin
if L.Face = R.Face then
return L.Suit < R.Suit;
else
return L.Face < R.Face;
end if;
end "<";
 
procedure Sort_Hand is new Ada.Containers.Generic_Constrained_Array_Sort (Hand_Index, Card_T, Hand_T);
 
procedure Print_Hand (Hand : Hand_T) is
begin
for Card of Hand loop
if Card.Face < j then
Put (Face_T'Enum_Rep (Card.Face)'Image);
else
Put (" " & To_Lower (Card.Face'Img));
end if;
Put (To_Lower (Card.Suit'Img));
end loop;
end Print_Hand;
 
function Is_Invalid (Hand : Hand_T) return Boolean is
begin
for Ix in 2 .. 5 loop
if Face_T'Pos (Hand (Ix).Face) = Face_T'Pos (Hand (Ix - 1).Face) and then
Hand (Ix).Suit = Hand (Ix - 1).Suit
then
return True;
end if;
end loop;
return False;
end Is_Invalid;
 
function Is_Flush (Hand : Hand_T) return Boolean is
begin
for Ix in 2 .. 5 loop
if Hand (Ix).Suit /= Hand (1).Suit then
return False;
end if;
end loop;
return True;
end Is_Flush;
 
function Is_Straight (Hand : Hand_T) return Boolean is
begin
-- special case: Ace low
if Hand (5).Face = a and then Hand (1).Face = two and then Hand (2).Face = three and then Hand (3).Face = four then
return True;
end if;
for Ix in 2 .. 5 loop
if Face_T'Pos (Hand (Ix).Face) /= Face_T'Pos (Hand (Ix - 1).Face) + 1 then
return False;
end if;
end loop;
return True;
end Is_Straight;
 
function Of_A_Kind (N : Positive) return Boolean is
begin
for Pip in two .. a loop
if Pip_Counts (Pip) = N then
return True;
end if;
end loop;
return False;
end Of_A_Kind;
 
function Count_Pairs return Natural is
Pairs : Natural := 0;
begin
for Pip in two .. a loop
if Pip_Counts (Pip) = 2 then
Pairs := Pairs + 1;
end if;
end loop;
return Pairs;
end Count_Pairs;
 
Flush, Straight : Boolean;
 
begin
 
for Hand of Test_Hands loop
Print_Hand (Hand);
Put (":");
Set_Col (20);
Sort_Hand (Hand); -- Print_Hand (Hand);
if Is_Invalid (Hand) then
Put ("invalid");
else
Flush := Is_Flush (Hand);
Straight := Is_Straight (Hand);
if Flush and Straight then
Put ("straight-flush");
else
for Pip in two .. a loop
Pip_Counts (Pip) := 0;
for Card of Hand loop
if Card.Face = Pip then
Pip_Counts (Pip) := Pip_Counts (Pip) + 1;
end if;
end loop;
end loop;
if Of_A_Kind (4) then
Put ("four-of-a-kind");
elsif Of_A_Kind (3) and then Of_A_Kind (2) then
Put ("full-house");
elsif Flush then
Put ("flush");
elsif Straight then
Put ("straight");
elsif Of_A_Kind (3) then
Put ("three-of-a-kind");
else
case Count_Pairs is
when 2 => Put ("two-pairs");
when 1 => Put ("one-pair");
when others => Put ("high-card");
end case;
end if;
end if;
end if;
Put_Line ("");
end loop;
 
end Poker;
</syntaxhighlight>
 
Output:
2h 2d 2c ks qd: three-of-a-kind
2h 5h 7d 8c 9s: high-card
ah 2d 3c 4c 5d: straight
2h 3h 2d 3c 3d: full-house
2h 7h 2d 3c 3d: two-pairs
2h 7h 7d 7c 7s: four-of-a-kind
10h jh qh kh ah: straight-flush
4h 4s ks 5d 10s: one-pair
qc 10c 7c 6c qc: invalid
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">PokerHand(hand){
StringUpper, hand, hand
Sort, hand, FCardSort D%A_Space%
Line 91 ⟶ 382:
b := (b = "T") ? 10 : (b = "J") ? 11 : (b = "Q") ? 12 : (b = "K") ? 13 : b
return a > b ? 1 : a < b ? -1 : 0
}</langsyntaxhighlight>
Examples:<langsyntaxhighlight AutoHotkeylang="autohotkey">hands =
(join`r`n
2♥ 2♦ 2♣ k♣ q♦
Line 109 ⟶ 400:
res .= PokerHand(A_LoopField) "`n"
MsgBox, 262144, , % res
return</langsyntaxhighlight>
Outputs:<pre>2♦ 2♣ 2♥ Q♦ K♣ Three of a Kind
2♥ 5♥ 7♦ 8♣ 9♠ High Card
Line 124 ⟶ 415:
=={{header|C}}==
{{trans|Kotlin}}
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <ctype.h>
#include <string.h>
Line 252 ⟶ 543:
}
return 0;
}</langsyntaxhighlight>
 
{{output}}
Line 267 ⟶ 558:
ah ah 7c 6c 4c: invalid
</pre>
 
=={{header|C sharp}}==
{{works with|C sharp|8}}
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using static System.Linq.Enumerable;
 
public static class PokerHandAnalyzer
{
private enum Hand {
Invalid, High_Card, One_Pair, Two_Pair, Three_Of_A_Kind, Straight,
Flush, Full_House, Four_Of_A_Kind, Straight_Flush, Five_Of_A_Kind
}
 
private const bool Y = true;
private const char C = '♣', D = '♦', H = '♥', S = '♠';
private const int rankMask = 0b11_1111_1111_1111;
private const int suitMask = 0b1111 << 14;
private static readonly string[] ranks = { "a", "2", "3", "4", "5", "6", "7", "8", "9", "10", "j", "q", "k" };
private static readonly string[] suits = { C + "", D + "", H + "", S + "" };
private static readonly Card[] deck = (from suit in Range(1, 4) from rank in Range(1, 13) select new Card(rank, suit)).ToArray();
 
public static void Main() {
string[] hands = {
"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♥",
"4♥ 4♠ k♠ 5♦ 10♠",
"q♣ 10♣ 7♣ 6♣ 4♣",
"4♥ 4♣ 4♥ 4♠ 4♦", //duplicate card
"joker 2♦ 2♠ k♠ q♦",
"joker 5♥ 7♦ 8♠ 9♦",
"joker 2♦ 3♠ 4♠ 5♠",
"joker 3♥ 2♦ 3♠ 3♦",
"joker 7♥ 2♦ 3♠ 3♦",
"joker 7♥ 7♦ 7♠ 7♣",
"joker j♥ q♥ k♥ A♥",
"joker 4♣ k♣ 5♦ 10♠",
"joker k♣ 7♣ 6♣ 4♣",
"joker 2♦ joker 4♠ 5♠",
"joker Q♦ joker A♠ 10♠",
"joker Q♦ joker A♦ 10♦",
"joker 2♦ 2♠ joker q♦"
};
foreach (var h in hands) {
Console.WriteLine($"{h}: {Analyze(h).Name()}");
}
}
 
static string Name(this Hand hand) => string.Join('-', hand.ToString().Split('_')).ToLower();
 
static List<T> With<T>(this List<T> list, int index, T item) {
list[index] = item;
return list;
}
 
struct Card : IEquatable<Card>, IComparable<Card>
{
public static readonly Card Invalid = new Card(-1, -1);
public static readonly Card Joker = new Card(0, 0);
 
public Card(int rank, int suit) {
(Rank, Suit, Code) = (rank, suit) switch {
(_, -1) => (-1, -1, -1),
(-1, _) => (-1, -1, -1),
(0, _) => (0, 0, 0),
(1, _) => (rank, suit, (1 << (13 + suit)) | ((1 << 13) | 1)),
(_, _) => (rank, suit, (1 << (13 + suit)) | (1 << (rank - 1)))
};
}
 
public static implicit operator Card((int rank, int suit) tuple) => new Card(tuple.rank, tuple.suit);
public int Rank { get; }
public int Suit { get; }
public int Code { get; }
 
public override string ToString() => Rank switch {
-1 => "invalid",
0 => "joker",
_ => $"{ranks[Rank-1]}{suits[Suit-1]}"
};
public override int GetHashCode() => Rank << 16 | Suit;
public bool Equals(Card other) => Rank == other.Rank && Suit == other.Suit;
 
public int CompareTo(Card other) {
int c = Rank.CompareTo(other.Rank);
if (c != 0) return c;
return Suit.CompareTo(other.Suit);
}
}
 
static Hand Analyze(string hand) {
var cards = ParseHand(hand);
if (cards.Count != 5) return Hand.Invalid; //hand must consist of 5 cards
cards.Sort();
if (cards[0].Equals(Card.Invalid)) return Hand.Invalid;
int jokers = cards.LastIndexOf(Card.Joker) + 1;
if (jokers > 2) return Hand.Invalid; //more than 2 jokers
if (cards.Skip(jokers).Distinct().Count() + jokers != 5) return Hand.Invalid; //duplicate cards
 
if (jokers == 2) return (from c0 in deck from c1 in deck select Evaluate(cards.With(0, c0).With(1, c1))).Max();
if (jokers == 1) return (from c0 in deck select Evaluate(cards.With(0, c0))).Max();
return Evaluate(cards);
}
 
static List<Card> ParseHand(string hand) =>
hand.Split(default(char[]), StringSplitOptions.RemoveEmptyEntries)
.Select(card => ParseCard(card.ToLower())).ToList();
 
static Card ParseCard(string card) => (card.Length, card) switch {
(5, "joker") => Card.Joker,
(3, _) when card[..2] == "10" => (10, ParseSuit(card[2])),
(2, _) => (ParseRank(card[0]), ParseSuit(card[1])),
(_, _) => Card.Invalid
};
 
static int ParseRank(char rank) => rank switch {
'a' => 1,
'j' => 11,
'q' => 12,
'k' => 13,
_ when rank >= '2' && rank <= '9' => rank - '0',
_ => -1
};
 
static int ParseSuit(char suit) => suit switch {
C => 1, 'c' => 1,
D => 2, 'd' => 2,
H => 3, 'h' => 3,
S => 4, 's' => 4,
_ => -1
};
 
static Hand Evaluate(List<Card> hand) {
var frequencies = hand.GroupBy(c => c.Rank).Select(g => g.Count()).OrderByDescending(c => c).ToArray();
(int f0, int f1) = (frequencies[0], frequencies.Length > 1 ? frequencies[1] : 0);
 
return (IsFlush(), IsStraight(), f0, f1) switch {
(_, _, 5, _) => Hand.Five_Of_A_Kind,
(Y, Y, _, _) => Hand.Straight_Flush,
(_, _, 4, _) => Hand.Four_Of_A_Kind,
(_, _, 3, 2) => Hand.Full_House,
(Y, _, _, _) => Hand.Flush,
(_, Y, _, _) => Hand.Straight,
(_, _, 3, _) => Hand.Three_Of_A_Kind,
(_, _, 2, 2) => Hand.Two_Pair,
(_, _, 2, _) => Hand.One_Pair,
_ => Hand.High_Card
};
 
bool IsFlush() => hand.Aggregate(suitMask, (r, c) => r & c.Code) > 0;
 
bool IsStraight() {
int r = hand.Aggregate(0, (r, c) => r | c.Code) & rankMask;
for (int i = 0; i < 4; i++) r &= r << 1;
return r > 0;
}
}
}</syntaxhighlight>
{{out}}
<pre>
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
4♥ 4♠ k♠ 5♦ 10♠: one-pair
q♣ 10♣ 7♣ 6♣ 4♣: flush
4♥ 4♣ 4♥ 4♠ 4♦: invalid
joker 2♦ 2♠ k♠ q♦: three-of-a-kind
joker 5♥ 7♦ 8♠ 9♦: straight
joker 2♦ 3♠ 4♠ 5♠: straight
joker 3♥ 2♦ 3♠ 3♦: four-of-a-kind
joker 7♥ 2♦ 3♠ 3♦: three-of-a-kind
joker 7♥ 7♦ 7♠ 7♣: five-of-a-kind
joker j♥ q♥ k♥ A♥: straight-flush
joker 4♣ k♣ 5♦ 10♠: one-pair
joker k♣ 7♣ 6♣ 4♣: flush
joker 2♦ joker 4♠ 5♠: straight
joker Q♦ joker A♠ 10♠: straight
joker Q♦ joker A♦ 10♦: straight-flush
joker 2♦ 2♠ joker q♦: four-of-a-kind</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="cpp">
<lang Cpp>
#include <iostream>
#include <sstream>
Line 344 ⟶ 825:
cout << p.analyze( "qc tc 7c 6c 4c" ) << endl << endl; return system( "pause" );
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 359 ⟶ 840:
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(defn rank [card]
(let [[fst _] card]
(if (Character/isDigit fst)
Line 439 ⟶ 920:
["QC" "TC" "7C" "6C" "4C"]])
(run! println (map #(str % " : " (check-hand %)) hands))
</syntaxhighlight>
</lang>
 
{{out}}
Line 458 ⟶ 939:
No bonus for this simple version.
{{trans|C++}}
<langsyntaxhighlight lang="d">import std.stdio, std.string, std.algorithm, std.range;
 
string analyzeHand(in string inHand) pure /*nothrow @safe*/ {
Line 543 ⟶ 1,024:
"QC TC 7C 6C 4C"])
writeln(hand, ": ", hand.analyzeHand);
}</langsyntaxhighlight>
{{out}}
<pre>2H 2D 2S KS QD: three-of-a-kind
Line 558 ⟶ 1,039:
{{trans|Ruby}}
{{works with|Elixir|1.2}}
<langsyntaxhighlight lang="elixir">defmodule Card do
@faces ~w(2 3 4 5 6 7 8 9 10 j q k a)
@suits ~w(♥ ♦ ♣ ♠) # ~w(h d c s)
Line 684 ⟶ 1,165:
best = Enum.map(cards_list, &Hand.new &1) |> Enum.max
IO.puts "#{hand}:\t#{elem(best,3)}"
end)</langsyntaxhighlight>
 
{{out}}
Line 721 ⟶ 1,202:
 
=={{header|F Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">
type Card = int * int
 
Line 821 ⟶ 1,302:
]
|> List.iter showHandRank
</syntaxhighlight>
</lang>
 
{{out}}
Line 849 ⟶ 1,330:
</pre>
 
=={{header|Factor}}==
Factor comes with a poker hand evaluator.
<syntaxhighlight lang="factor">USING: formatting kernel poker sequences ;
{
"2H 2D 2C KC QD"
"2H 5H 7D 8C 9S"
"AH 2D 3C 4C 5D"
"2H 3H 2D 3C 3D"
"2H 7H 2D 3C 3D"
"2H 7H 7D 7C 7S"
"TH JH QH KH AH"
"4H 4S KS 5D TS"
"QC TC 7C 6C 4C"
} [ dup string>hand-name "%s: %s\n" printf ] each</syntaxhighlight>
{{out}}
<pre>
2H 2D 2C KC QD: Three of a Kind
2H 5H 7D 8C 9S: High Card
AH 2D 3C 4C 5D: Straight
2H 3H 2D 3C 3D: Full House
2H 7H 2D 3C 3D: Two Pair
2H 7H 7D 7C 7S: Four of a Kind
TH JH QH KH AH: Straight Flush
4H 4S KS 5D TS: One Pair
QC TC 7C 6C 4C: Flush
</pre>
 
=={{header|FreeBASIC}}==
{{trans|C}}
<syntaxhighlight lang="vbnet">Const As String FACES = "23456789tjqka"
Const As String SUITS = "shdc"
 
Type card
face As Integer ' FACES map to 0..12 respectively
suit As String
End Type
 
Dim Shared As card cards(4)
 
Sub insertionSort(arr() As card, Byval n As Integer)
Dim As Integer i, key, j
For i = 1 To n-1
key = arr(i).face
j = i-1
While j >= 0 And arr(j).face > key
arr(j+1) = arr(j)
j = j-1
Wend
arr(j+1).face = key
Next i
End Sub
 
Function compareCard(Byval a As card, Byval b As card) As Integer
Return a.face - b.face
End Function
 
Function equalsCard(Byval c1 As card, Byval c2 As card) As Integer
If c1.face = c2.face And c1.suit = c2.suit Then Return True
Return False
End Function
 
Function areDistinct() As Integer
Dim As Integer i, j
For i = 0 To 3
For j = i + 1 To 4
If equalsCard(cards(i), cards(j)) = True Then Return False
Next j
Next i
Return True
End Function
 
Function isStraight() As Boolean
insertionSort(cards(), 5)
If cards(0).face + 4 = cards(4).face Then Return True
If cards(4).face = 12 And cards(0).face = 0 And cards(3).face = 3 Then Return True
Return False
End Function
 
Function isFlush() As Boolean
Dim As String suit = cards(0).suit
For i As Integer = 1 To 4
If cards(i).suit <> suit Then Return False
Next i
Return True
End Function
 
Function analyzeHand(Byval hand As String) As String
Dim As Integer i, j, cp, gs = 0
Dim As String suit
Dim As Integer found, flush, straight
Dim As Integer groups(12)
If Len(hand) <> 14 Then Return "invalid"
For i = 0 To 13 Step 3
cp = Instr(FACES, Lcase(Mid(hand, i + 1, 1)))
If cp = 0 Then Return "invalid"
j = i \ 3
cards(j).face = cp - 1
suit = Lcase(Mid(hand, i + 2, 1))
cp = Instr(SUITS, suit)
If cp = 0 Then Return "invalid"
cards(j).suit = suit
Next i
If areDistinct() = False Then Return "invalid"
For i = 0 To 12
groups(i) = 0
Next i
For i = 0 To 4
groups(cards(i).face) += 1
Next i
For i = 0 To 12
If groups(i) > 0 Then gs += 1
Next i
Select Case gs
Case 2
found = False
For i = 0 To 12
If groups(i) = 4 Then
found = True
Exit For
End If
Next i
If found = True Then Return "four-of-a-kind"
Return "full-house"
Case 3
found = False
For i = 0 To 12
If groups(i) = 3 Then
found = True
Exit For
End If
Next i
If found = True Then Return "three-of-a-kind"
Return "two-pairs"
Case 4
Return "one-pair"
Case Else
flush = isFlush()
straight = isStraight()
If flush = True And straight = True Then
Return "straight-flush"
Elseif flush = True Then
Return "flush"
Elseif straight = True Then
Return "straight"
Else
Return "high-card"
End If
End Select
End Function
 
Dim As String tipo
Dim As String hands(9) = { _
"2h 2d 2c kc qd", _
"2h 5h 7d 8c 9s", _
"ah 2d 3c 4c 5d", _
"2h 3h 2d 3c 3d", _
"2h 7h 2d 3c 3d", _
"2h 7h 7d 7c 7s", _
"th jh qh kh ah", _
"4h 4s ks 5d ts", _
"qc tc 7c 6c 4c", _
"ah ah 7c 6c 4c" }
 
For i As Integer = 0 To 9
tipo = analyzeHand(hands(i))
Print hands(i); ": "; tipo
Next i
 
Sleep</syntaxhighlight>
{{out}}
<pre>Same as C entry.</pre>
 
=={{header|Go}}==
{{trans|Kotlin}}
===Basic Version===
<langsyntaxhighlight lang="go">package main
 
import (
Line 979 ⟶ 1,631:
fmt.Printf("%s: %s\n", hand, analyzeHand(hand))
}
}</langsyntaxhighlight>
 
{{out}}
Line 996 ⟶ 1,648:
 
===Extra Credit Version===
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,211 ⟶ 1,863:
fmt.Printf("%s: %s\n", hand, analyzeHand(hand))
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,231 ⟶ 1,883:
🃂 🃞 🃍 🃁 🃊 : high-card
</pre>
 
=={{header|Haskell}}==
===Basic Version===
<syntaxhighlight lang="haskell">{-# LANGUAGE TupleSections #-}
 
import Data.Function (on)
import Data.List (group, nub, any, sort, sortBy)
import Data.Maybe (mapMaybe)
import Text.Read (readMaybe)
 
data Suit = Club | Diamond | Spade | Heart deriving (Show, Eq)
 
data Rank = Ace | Two | Three | Four | Five | Six | Seven
| Eight | Nine | Ten | Jack | Queen | King
deriving (Show, Eq, Enum, Ord, Bounded)
 
data Card = Card { suit :: Suit, rank :: Rank } deriving (Show, Eq)
 
type Hand = [Card]
 
consumed = pure . (, "")
 
instance Read Suit where
readsPrec d s = case s of "♥" -> consumed Heart
"♦" -> consumed Diamond
"♣" -> consumed Spade
"♠" -> consumed Club
"h" -> consumed Heart
_ -> []
 
instance Read Rank where
readsPrec d s = case s of "a" -> consumed Ace
"2" -> consumed Two
"3" -> consumed Three
"4" -> consumed Four
"5" -> consumed Five
"6" -> consumed Six
"7" -> consumed Seven
"8" -> consumed Eight
"9" -> consumed Nine
"10" -> consumed Ten
"j" -> consumed Jack
"q" -> consumed Queen
"k" -> consumed King
_ -> []
 
instance Read Card where
readsPrec d = fmap (, "") . mapMaybe card . lex
where
card (r, s) = Card <$> (readMaybe s :: Maybe Suit)
<*> (readMaybe r :: Maybe Rank)
 
-- Special hand
acesHigh :: [Rank]
acesHigh = [Ace, Ten, Jack, Queen, King]
 
isSucc :: (Enum a, Eq a, Bounded a) => [a] -> Bool
isSucc [] = True
isSucc [x] = True
isSucc (x:y:zs) = (x /= maxBound && y == succ x) && isSucc (y:zs)
 
nameHand :: Hand -> String
nameHand [] = "Invalid Input"
nameHand cards | invalidHand = "Invalid hand"
| straight && flush = "Straight flush"
| ofKind 4 = "Four of a kind"
| ofKind 3 && ofKind 2 = "Full house"
| flush = "Flush"
| straight = "Straight"
| ofKind 3 = "Three of a kind"
| uniqRanks == 3 = "Two pair"
| uniqRanks == 4 = "One pair"
| otherwise = "High card"
where
sortedRank = sort $ rank <$> cards
rankCounts = sortBy (compare `on` snd) $ (,) <$> head <*> length <$> group sortedRank
uniqRanks = length rankCounts
ofKind n = any ((==n) . snd) rankCounts
straight = isSucc sortedRank || sortedRank == acesHigh
flush = length (nub $ suit <$> cards) == 1
invalidHand = length (nub cards) /= 5
 
testHands :: [(String, Hand)]
testHands = (,) <$> id <*> mapMaybe readMaybe . words <$>
[ "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♥"
, "4♥ 4♠ k♠ 5♦ 10♠"
, "q♣ 10♣ 7♣ 6♣ 4♣"
, "q♣ 10♣ 7♣ 6♣ 7♣" -- duplicate cards
, "Bad input" ]
 
main :: IO ()
main = mapM_ (putStrLn . (fst <> const ": " <> nameHand . snd)) testHands</syntaxhighlight>
{{out}}
<pre>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
4♥ 4♠ k♠ 5♦ 10♠: One pair
q♣ 10♣ 7♣ 6♣ 4♣: Flush
q♣ 10♣ 7♣ 6♣ 7♣: Invalid hand
Bad input: Invalid Input</pre>
 
=={{header|J}}==
 
<langsyntaxhighlight Jlang="j">parseHand=: <;._2@,&' '@ cut 7&u:~&7 NB. hand must be well formed
Suits=: <"> 7 u: '♥♦♣♦' NB. or Suits=: 'hdcs'
Faces=: <;._1 ' 2 3 4 5 6 7 8 9 10 j q k a'
Line 1,269 ⟶ 2,031:
('straight-flush' IF (straight * flush)) Or
('five-of-a-kind' IF five)
)
)</lang>
 
Hands=: <@deb;._2 {{)n
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♥
4♥ 4♠ k♠ 5♦ 10♠
q♣ 10♣ 7♣ 6♣ 4♣
}}</syntaxhighlight>
 
Note that * acts as "logical and" on logical values (if you need to deal with boolean values in the original sense - which were not constrained to logical values - you should use *. instead of * to achieve boolean multiplication, but that's not needed here).
 
Output for required<code>rateHand@> examplesHands</code>:
 
<pre>2♥ 2♦ 2♣ k♣ q♦ three-of-a-kind
2♥ 5♥ 7♦ 8♣ 9♠ high-card
a♥ 2♦ 3♣ 4♣ 5♦ high-card
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
4♥ 4♠ k♠ 5♦ 10♠ one-pair
q♣ 10♣ 7♣ 6♣ 4♣ flush
</pre>
 
Output for extra-credit examples
Line 1,304 ⟶ 2,079:
{{works with|Java|7}}
This code does not qualify for extra credit. Although it supports wildcards, it does not allow for duplicates.
<langsyntaxhighlight lang="java">import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
Line 1,483 ⟶ 2,258:
}
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,530 ⟶ 2,305:
[QC, TC, 7H, WW, WW]
[QC, TC, 7H, QH, QD] three-of-a-kind</pre>
 
=={{header|JavaScript}}==
{{works with|JavaScript|ECMAScript 6}}
<syntaxhighlight lang="javascript">const FACES = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'j', 'q', 'k', 'a'];
const SUITS = ['♥', '♦', '♣', '♠'];
 
function analyzeHand(hand){
let cards = hand.split(' ').filter(x => x !== 'joker');
let jokers = hand.split(' ').length - cards.length;
let faces = cards.map( card => FACES.indexOf(card.slice(0,-1)) );
let suits = cards.map( card => SUITS.indexOf(card.slice(-1)) );
if( cards.some( (card, i, self) => i !== self.indexOf(card) ) || faces.some(face => face === -1) || suits.some(suit => suit === -1) )
return 'invalid';
let flush = suits.every(suit => suit === suits[0]);
let groups = FACES.map( (face,i) => faces.filter(j => i === j).length).sort( (x, y) => y - x );
let shifted = faces.map(x => (x + 1) % 13);
let distance = Math.min( Math.max(...faces) - Math.min(...faces), Math.max(...shifted) - Math.min(...shifted));
let straight = groups[0] === 1 && distance < 5;
groups[0] += jokers;
if (groups[0] === 5) return 'five-of-a-kind'
else if (straight && flush) return 'straight-flush'
else if (groups[0] === 4) return 'four-of-a-kind'
else if (groups[0] === 3 && groups[1] === 2) return 'full-house'
else if (flush) return 'flush'
else if (straight) return 'straight'
else if (groups[0] === 3) return 'three-of-a-kind'
else if (groups[0] === 2 && groups[1] === 2) return 'two-pair'
else if (groups[0] === 2) return 'one-pair'
else return 'high-card';
}</syntaxhighlight>
Demonstrating:
<syntaxhighlight lang="javascript">let testHands = [
"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♥",
"4♥ 4♠ k♠ 5♦ 10♠",
"q♣ 10♣ 7♣ 6♣ 4♣",
"joker 4♣ k♣ 5♦ 10♠",
"joker 2♦ 2♠ k♠ q♦",
"joker 3♥ 2♦ 3♠ 3♦",
"joker 7♥ 7♦ 7♠ 7♣",
"joker 2♦ joker 4♠ 5♠",
"joker 2♠ joker a♠ 10♠",
"joker q♦ joker a♦ 10♦"
];
for(hand of testHands) console.log(hand + ": " + analyzeHand(hand));</syntaxhighlight>
{{out}}
<pre>
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
4♥ 4♠ k♠ 5♦ 10♠: one-pair
q♣ 10♣ 7♣ 6♣ 4♣: flush
joker 4♣ k♣ 5♦ 10♠: one-pair
joker 2♦ 2♠ k♠ q♦: three-of-a-kind
joker 3♥ 2♦ 3♠ 3♦: four-of-a-kind
joker 7♥ 7♦ 7♠ 7♣: five-of-a-kind
joker 2♦ joker 4♠ 5♠: straight
joker 2♠ joker a♠ 10♠: flush
joker q♦ joker a♦ 10♦: straight-flush
</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
 
'''Works with jq, the C implementation of jq'''
 
'''Works with gojq, the Go implementation of jq'''
 
With a few small tweaks, the program shown below also works with jaq,
the Rust implementation of jq.
<syntaxhighlight lang="jq">
# A card is represented by a JSON object:
def Card($face; $suit): {$face, $suit};
 
def FACES: "23456789tjqka";
def SUITS: "shdc";
 
# Input: an array of Card
def isStraight:
sort_by(.face)
| (.[0].face + 4 == .[4].face)
or (.[4].face == 14 and .[0].face == 2 and .[3].face == 5) ;
 
def isFlush:
.[0].suit as $suit
| all(.[]; .suit == $suit);
 
# Input: a string such as "2h 2d 2c kc qd"
def analyzeHand:
(FACES | split("")) as $FACES
| (SUITS | split("")) as $SUITS
| ascii_downcase
| split(" ")
| unique
| if length != 5 or
any(length != 2 or
(.[0:1] | IN($FACES[]) | not) or
(.[1: ] | IN($SUITS[]) | not) )
then "invalid"
else [.[] as $s | Card(($FACES|index($s[0:1])) + 2; $s[1:]) ]
| . as $cards
| group_by(.face)
| if length == 2
then if any(length == 4) then "four-of-a-kind"
else "full-house"
end
elif length == 3
then if any(length == 3) then "three-of-a-kind"
else "two-pairs"
end
elif length == 4
then "one-pair"
else ($cards|[isFlush, isStraight]) as [$flush, $straight]
| if $flush and $straight then "straight-flush"
elif $flush then "flush"
elif $straight then "straight"
else "high-card"
end
end
end ;
 
def hands: [
"2h 2d 2c kc qd",
"2h 5h 7d 8c 9s",
"ah 2d 3c 4c 5d",
"2h 3h 2d 3c 3d",
"2h 7h 2d 3c 3d",
"2h 7h 7d 7c 7s",
"th jh qh kh ah",
"4h 4s ks 5d ts",
"qc tc 7c 6c 4c",
"ah ah 7c 6c 4c"
];
 
hands[]
| "\(.): \(analyzeHand)"
</syntaxhighlight>
{{output}}
<pre>
2h 2d 2c kc qd: three-of-a-kind
2h 5h 7d 8c 9s: high-card
ah 2d 3c 4c 5d: straight
2h 3h 2d 3c 3d: full-house
2h 7h 2d 3c 3d: two-pairs
2h 7h 7d 7c 7s: four-of-a-kind
th jh qh kh ah: straight-flush
4h 4s ks 5d ts: one-pair
qc tc 7c 6c 4c: flush
ah ah 7c 6c 4c: invalid
</pre>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">sorteddeck = [string(r) * s for s in "♣♦♥♠", r in "23456789TJQKA"]
 
cardlessthan(card1, card2) = indexin(x, sorteddeck)[1] < indexin(y, sorteddeck)[1]
 
decksort(d) = sort(d, lt=cardlessthan)
 
highestrank(d) = string(highestcard(d)[1])
 
function hasduplicate(d)
s = sort(d)
for i in 1:length(s)-1
if s[i] == s[i+1]
return true
end
end
false
end
 
invalid(d) = !all(x -> x in sorteddeck, d) || hasduplicate(d)
 
function countranks(d)
ranks = Dict()
for c in d
r = string(c[1])
if !haskey(ranks, r)
ranks[r] = 1
else
ranks[r] += 1
end
end
ranks
end
 
function countsuits(d)
suits = Dict()
for c in d
s = string(c[2])
if !haskey(suits, s)
suits[s] = 1
else
suits[s] += 1
end
end
suits
end
 
const rankmodifiers = Dict("A" => 130, "K" => 120, "Q" => 110, "J" => 100, "T" => 90,
"9" => 80, "8" => 70, "7" => 60, "6" => 50, "5" => 40,
"4" => 30, "3" => 20, "2" => 10)
 
rank(card) = rankmodifiers[string(card[1])]
 
const suitmodifiers = Dict("♠" => 4, "♥" => 3, "♦" => 2, "♣" => 1)
 
suitrank(card) = suitmodifiers[string(card[2])]
 
function isstraight(ranksdict)
v = collect(values(ranksdict))
if maximum(v) != 1
return false
else
s = sort(map(x->rankmodifiers[x], collect(keys(ranksdict))))
if s == [10, 20, 30, 40, 130] # aces low straight
return true
else
for i in 1:length(s)-1
if abs(s[i] - s[i+1]) > 10
return false
end
end
end
end
true
end
 
highestsuit(suitsdict) = sort(collect(keys(suitsdict)), lt=(x,y)->suitsdict[x] < suitsdict[y])[end]
 
isflush(suitsdict) = length(collect(values(suitsdict))) == 1
 
isstraightflush(ranks, suits) = isstraight(ranks) && isflush(suits)
 
isfourofakind(ranksdict) = maximum(values(ranksdict)) == 4 ? true : false
 
isfullhouse(ranksdict) = sort(collect(values(ranksdict))) == [2, 3]
 
isthreeofakind(ranksdict) = maximum(values(ranksdict)) == 3 && !isfullhouse(ranksdict) ? true : false
 
istwopair(ranksdict) = sort(collect(values(ranksdict)))[end-1: end] == [2,2]
 
isonepair(ranksdict) = sort(collect(values(ranksdict)))[end-1: end] == [1,2]
 
ishighcard(ranks, suits) = maximum(values(ranks)) == 1 && !isflush(suits) && !isstraight(ranks)
 
function scorehand(d)
suits = countsuits(d)
ranks = countranks(d)
if invalid(d)
return "invalid"
end
if isstraightflush(ranks, suits) return "straight-flush"
elseif isfourofakind(ranks) return "four-of-a-kind"
elseif isfullhouse(ranks) return "full-house"
elseif isflush(suits) return "flush"
elseif isstraight(ranks) return "straight"
elseif isthreeofakind(ranks) return "three-of-a-kind"
elseif istwopair(ranks) return "two-pair"
elseif isonepair(ranks) return "one-pair"
elseif ishighcard(ranks, suits) return "high-card"
end
end
 
const hands = [["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♠"],
["T♥", "J♥", "Q♥", "K♥", "A♥"], ["4♥", "4♠", "K♠", "5♦", "T♠"],
["Q♣", "T♣", "7♣", "6♣", "4♣"]]
 
for hand in hands
println("Hand $hand is a ", scorehand(hand), " hand.")
end
</syntaxhighlight>{{output}}<pre>
Hand ["2♥", "2♦", "2♣", "K♣", "Q♦"] is a three-of-a-kind hand.
Hand ["2♥", "5♥", "7♦", "8♣", "9♠"] is a high-card hand.
Hand ["A♥", "2♦", "3♣", "4♣", "5♦"] is a straight hand.
Hand ["2♥", "3♥", "2♦", "3♣", "3♦"] is a full-house hand.
Hand ["2♥", "7♥", "2♦", "3♣", "3♦"] is a two-pair hand.
Hand ["2♥", "7♥", "7♦", "7♣", "7♠"] is a four-of-a-kind hand.
Hand ["T♥", "J♥", "Q♥", "K♥", "A♥"] is a straight-flush hand.
Hand ["4♥", "4♠", "K♠", "5♦", "T♠"] is a one-pair hand.
Hand ["Q♣", "T♣", "7♣", "6♣", "4♣"] is a flush hand.
</pre>
 
=={{header|Kotlin}}==
===Basic Version===
<langsyntaxhighlight lang="scala">// version 1.1.2
 
class Card(val face: Int, val suit: Char)
Line 1,608 ⟶ 2,680:
println("$hand: ${analyzeHand(hand)}")
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,625 ⟶ 2,697:
 
===Extra Credit Version===
<langsyntaxhighlight lang="scala">// version 1.1.2
 
class Card(val face: Int, val suit: Char)
Line 1,752 ⟶ 2,824:
println("$hand : ${analyzeHand(hand)}")
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,772 ⟶ 2,844:
🃂 🃞 🃍 🃁 🃊 : high-card
</pre>
 
=={{header|Liberty Basic}}==
{{works with|LB Booster}}
<syntaxhighlight lang="Liberty Basic>
 
NoMainWin
WindowWidth=900
WindowHeight=720
BackgroundColor$ = "191 191 255" ' buttonface default
Global Deck, MaxDecks
 
StaticText #1.Debug "", 0, 0, 600, 20
StaticText #1.StaticText "Ten Decks of Poker Hands", 50, 50, 3000, 40
Button #1.Deal "Deal", [Start], UL, 700, 180, 80, 40
Button #1.TenThousand "10,000", [TenThousand], UL, 700, 250, 80, 40
Button #1.Stats "History", ShowStats, UL, 700, 320, 80, 40
Button #1.Quit "Quit", Quit, UL, 700, 390, 80, 40
TextEditor #1.TextEditor 50, 100, 600, 500
 
open "POKER HANDS" for dialog as #1
#1 "TrapClose Quit"
#1 "Font Ariel 12 Bold"
#1.StaticText "!Font Ariel 16 Bold"
#1.TextEditor "!Font Courier_New 14 Bold"
if not(exists("Poker Hands.txt")) then #1.Stats "!Disable"
MaxDecks=10
wait
 
[TenThousand]
TenThousand = 1
[Start]
if TenThousand then
MaxDecks=10000
#1.TextEditor "!Hide"
#1.Deal "!Hide"
#1.TenThousand "!Hide"
#1.Stats "!Hide"
#1.Quit "!Hide"
#1.StaticText "Ten Thousand Decks of Poker Hands"
end if
Deck += 1
if TenThousand then #1.Debug Str$(Deck)
if Deck>MaxDecks then Deck -= 1: call Quit
#1.TextEditor "!cls"
call ShuffleDeck 0
'call TestDeck
NextCard=1
for y=1 to 10
for x=1 to 5
y$ = A$(NextCard)
B$(x) = ConvertHiCard$(y$)
NextCard += 1
next x
sort B$(), 1, 5
for x=NextCard-5 to NextCard-1
#1.TextEditor A$(x)+" ";
next x
#1.TextEditor " ";
Values$="" 'determine high value of hand
for x=1 to 5
Values$ = Values$ + left$(B$(x),1)
next x
HiValue$ = RealValue$(right$(Values$,1))
 
z=0: Flush=0: Straight=0: Royal=0: FourKind=0
ThreeKind=0: Pair=0: TwoPair=0: FullHouse=0
if Flush() then Flush=1
x = Straight()
if x then Straight=1: if x=9 then Royal=1
z$ = Kind$()
Value$ = RealValue$(right$(z$,1))
z=val(left$(z$, len(z$)-1))
if z=41 then FourKind=1
if z=32 then FullHouse=1
if z=31 then ThreeKind=1
if z=22 then TwoPair=1
if z=21 then Pair=1
select case
case Straight and Royal and Flush: #1.TextEditor "Royal Flush": Stats(1) += 1
case Straight and Flush: #1.TextEditor "Straight Flush, " + HiValue$ + " high": Stats(2) += 1
case FourKind: #1.TextEditor "Four of a kind, " + Value$ + "s": Stats(3) += 1
case FullHouse: #1.TextEditor "Full House, " + Value$ + "s high": Stats(4) += 1
case Flush: #1.TextEditor "Flush, " + HiValue$ + " high": Stats(5) += 1
case Straight: #1.TextEditor "Straight, " + HiValue$ + " high": Stats(6) += 1
case ThreeKind: #1.TextEditor "Three of a kind, " + Value$ + "s": Stats(7) += 1
case TwoPair: #1.TextEditor "Two Pair, " + Value$ + " high": Stats(8) += 1
case Pair: #1.TextEditor "Pair " + Value$ + "s": Stats(9) += 1
case else: #1.TextEditor HiValue$ + " high"
end select
next y
#1.TextEditor ""
#1.TextEditor "Deck #" + str$(Deck)
if TenThousand then goto [Start] else wait
 
function RealValue$(Value$)
select case Value$
case "A": RealValue$="T"
case "B": RealValue$="J"
case "C": RealValue$="Q"
case "D": RealValue$="K"
case "E": RealValue$="A"
case else: RealValue$=Value$
end select
end function
 
sub SaveStats Deck
Stats(0) = 10*Deck
if not(exists("Poker Hands.txt")) then
open "Poker Hands.txt" for output as #2
for x=0 to 9
print #2 Stats(x)
next
close #2
#1.Stats "!Enable"
else
open "Poker Hands.txt" for input as #2
for x=0 to 9
input #2 History(x)
next
close #2
for x=0 to 9
History(x) += Stats(x)
next
open "Poker Hands.txt" for output as #2
for x=0 to 9
print #2 History(x)
next
close #2
end if
end sub
 
sub ShowStats
if exists("Poker Hands.txt") then
open "Poker Hands.txt" for input as #2
for x=0 to 9
input #2 History(x)
next
close #2
#1.TextEditor "!cls"
for x=1 to 9
Total += History(x)
next x
Nothing = History(0) - Total
 
for x=0 to 9
#1.TextEditor using("###,### ", History(x));
select case x
case 0: #1.TextEditor "hands "
case 1: #1.TextEditor "royal flush " + using("##.# %", History(x)/History(0)*100)
case 2: #1.TextEditor "straight flush " + using("##.# %", History(x)/History(0)*100)
case 3: #1.TextEditor "four of a kind " + using("##.# %", History(x)/History(0)*100)
case 4: #1.TextEditor "full house " + using("##.# %", History(x)/History(0)*100)
case 5: #1.TextEditor "flush " + using("##.# %", History(x)/History(0)*100)
case 6: #1.TextEditor "straight " + using("##.# %", History(x)/History(0)*100)
case 7: #1.TextEditor "three of a kind " + using("##.# %", History(x)/History(0)*100)
case 8: #1.TextEditor "two pair " + using("##.# %", History(x)/History(0)*100)
case 9: #1.TextEditor "pair " + using("##.# %", History(x)/History(0)*100)
end select
next
#1.TextEditor using("###,### ", Nothing) + "nothing " + using("###.# %", Nothing/History(0)*100)
end if
end sub
 
function Kind$()
for x=1 to 5
C$(x) = left$(B$(x), 1)
next x
if C$(1) = C$(2) then 'check for Lo4
Lo2=1
if C$(2) = C$(3) then
Lo2=0: Lo3=1
if C$(3) = C$(4) then
Lo3=0: Kind$="41" + left$(C$(4),1): exit function
end if
end if
end if
if C$(5) = C$(4) then 'check for Hi4
Hi2=1
if C$(4) = C$(3) then
Hi2=0: Hi3=1
if C$(3) = C$(2) then
Hi3=0: Kind$="41" + left$(C$(5),1): exit function
end if
end if
end if
if Lo3 then 'check for Full House and 3Kind
if C$(4) = C$(5) then
Kind$="32" + left$(C$(3),1): exit function
else
Kind$="31" + left$(C$(3),1): exit function
end if
end if
if Hi3 then
if C$(1) = C$(2) then
Kind$="32" + left$(C$(5),1): exit function
else
Kind$="31" + left$(C$(5),1): exit function
end if
end if
if C$(2) = C$(3) and C$(3) = C$(4) then 'Mid3
Kind$="31" + left$(C$(4),1): exit function
end if
if Lo2 and Hi2 then 'check for pairs
Kind$="22" + left$(C$(5),1): exit function
end if
if Lo2 and (C$(3)=C$(4)) then
Kind$="22" + left$(C$(4),1): exit function
end if
if Hi2 and (C$(3)=C$(2)) then
Kind$="22" + left$(C$(5),1): exit function
end if
if Lo2 then Kind$="21" + left$(C$(2),1)
if Hi2 then Kind$="21" + left$(C$(5),1)
if C$(2)=C$(3) then Kind$="21" + left$(C$(3),1)
if C$(3)=C$(4) then Kind$="21" + left$(C$(4),1)
end function
 
function Straight()
Order$="23456789ABCDEF"
for x=1 to 5
Ranks$ = Ranks$ + left$(B$(x), 1)
next x
x = instr(Order$, Ranks$)
if x then Straight=x
end function
 
function Flush()
Flush=1
for x=1 to 5
Suits$ = Suits$ + right$(B$(x), 1)
next x
for x=2 to 5
if mid$(Suits$, x, 1) <> left$(Suits$, 1) then Flush=0: exit function
next x
end function
 
sub ShuffleDeck Jokers
Jokers = int(abs(Jokers)): if Jokers>4 then Jokers=4
Size=52 + Jokers
dim CardDeck$(Size+10,1), A$(Size+10) 'Open new card deck
[Start]
for x=1 to Size
CardDeck$(x,0) = "99"
next x
 
for x=1 to Size
1 y=RandomNumber(1,Size)
if CardDeck$(y,0)="99" then CardDeck$(y,0)=str$(x) else goto 1
next x
 
for x=1 to Size 'Examine shuffled deck
if CardDeck$(x,0)=str$(x) then z = 1: exit for
next x
if z then z=0: goto [Start]
for x=1 to Size 'Save shuffled deck
A$(x) = CardFace$(val(CardDeck$(x,0)))
next x
A$(0) = str$(Size)
end sub
 
function CardFace$(n)
select case n
case 1: CardFace$="AD"
case 2: CardFace$="2D"
case 3: CardFace$="3D"
case 4: CardFace$="4D"
case 5: CardFace$="5D"
case 6: CardFace$="6D"
case 7: CardFace$="7D"
case 8: CardFace$="8D"
case 9: CardFace$="9D"
case 10: CardFace$="TD"
case 11: CardFace$="JD"
case 12: CardFace$="QD"
case 13: CardFace$="KD"
case 14: CardFace$="AC"
case 15: CardFace$="2C"
case 16: CardFace$="3C"
case 17: CardFace$="4C"
case 18: CardFace$="5C"
case 19: CardFace$="6C"
case 20: CardFace$="7C"
case 21: CardFace$="8C"
case 22: CardFace$="9C"
case 23: CardFace$="TC"
case 24: CardFace$="JC"
case 25: CardFace$="QC"
case 26: CardFace$="KC"
case 27: CardFace$="AH"
case 28: CardFace$="2H"
case 29: CardFace$="3H"
case 30: CardFace$="4H"
case 31: CardFace$="5H"
case 32: CardFace$="6H"
case 33: CardFace$="7H"
case 34: CardFace$="8H"
case 35: CardFace$="9H"
case 36: CardFace$="TH"
case 37: CardFace$="JH"
case 38: CardFace$="QH"
case 39: CardFace$="KH"
case 40: CardFace$="AS"
case 41: CardFace$="2S"
case 42: CardFace$="3S"
case 43: CardFace$="4S"
case 44: CardFace$="5S"
case 45: CardFace$="6S"
case 46: CardFace$="7S"
case 47: CardFace$="8S"
case 48: CardFace$="9S"
case 49: CardFace$="TS"
case 50: CardFace$="JS"
case 51: CardFace$="QS"
case 52: CardFace$="KS"
case 53: CardFace$="X1"
case 54: CardFace$="X2"
case 55: CardFace$="X3"
case 56: CardFace$="X4"
end select
end function
 
function RandomNumber(a, b)
smaller = min(a, b)
range = abs(int(a-b))+1
if range < 1 then exit function
r = int(rnd()*range)
RandomNumber = r + smaller
end function
 
function ConvertHiCard$(Card$)
select case left$(Card$,1)
case "T": left$(Card$,1)="A"
case "J": left$(Card$,1)="B"
case "Q": left$(Card$,1)="C"
case "K": left$(Card$,1)="D"
case "A": left$(Card$,1)="E"
case "X": left$(Card$,1)="F"
end select
ConvertHiCard$ = Card$
end function
 
sub TestDeck
data KD, KC, KS, AH, AS ' full house
data 6D, 6C, 6S, 6H, 8H ' four of a kind (io)
data 2D, 4S, 4C, TH, TD ' two pair
data 4H, 5H, 6H, 7H, 8H ' straight flush
data 9S, QD, QC, QH, 3D ' three of a kind
data 6H, 7D, 8C, 9C, TS ' straight
data TH, AH, AS, AC, AD ' four of a kind (hI)
data 3S, 5S, 7S, 9S, JS ' flush
data AD, KD, QD, JD, TD ' royal flush
data 2C, 2D, 3H, 4S, 5C ' one pair
dim A$(50)
for x=1 to 50
read A$(x)
next x
end sub
 
function exists(FileName$)
files "", FileName$, FileDir$()
FileCount$ = FileDir$(0, 0)
exists = val(FileCount$)
end function
 
sub Quit
if Deck = MaxDecks then call SaveStats Deck
close #1
end
end sub
 
</syntaxhighlight>
{{out}}
<pre>
JH 8C 8S TH KC Pair 8s
9C JS 3S 5D 3D Pair 3s
TD QH 6S TS AD Pair Ts
AH 9D KD 3H AC Pair As
QS 6D JC QD 2H Pair Qs
4H 2D 5S 4C JD Pair 4s
KH 6C 4S 7C 5H K high
3C 7D 8D 4D 7H Pair 7s
9S 2S 7S 9H 6H Pair 9s
AS QC 5C TC 2C A high
 
Deck #1
</pre>
 
 
=={{header|Lua}}==
<langsyntaxhighlight lang="lua">-- Check whether t is a valid poker hand
function valid (t)
if #t ~= 5 then return false end
Line 1,896 ⟶ 3,362:
"qc 10c 7c 6c 4c" -- flush
}
for _, case in pairs(testCases) do print(case, ": " .. rank(case)) end</langsyntaxhighlight>
{{out}}
<pre>2h 2d 2c kc qd : three-of-a-kind
Line 1,907 ⟶ 3,373:
4h 4s ks 5d 10s : one-pair
qc 10c 7c 6c 4c : flush</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import algorithm, sequtils, strutils, tables, unicode
 
type
 
Suit* = enum ♠, ♥, ♦, ♣
Face* {.pure.} = enum
Ace = (1, "a")
Two = (2, "2")
Three = (3, "3")
Four = (4, "4")
Five = (5, "5")
Six = (6, "6")
Seven = (7, "7")
Eight = (8, "8")
Nine = (9, "9")
Ten = (10, "10")
Jack = (11, "j")
Queen = (12, "q")
King = (13, "k")
 
Card* = tuple[face: Face; suit: Suit]
Hand* = array[5, Card]
 
HandValue {.pure.} = enum
Invalid = "invalid"
StraightFlush = "straight-flush"
FourOfAKind = "four-of-a-kind"
FullHouse = "full-house"
Flush = "flush"
Straight = "straight"
ThreeOfAKind = "three-of-a-kind"
TwoPair = "two-pair"
OnePair = "one-pair"
HighCard = "high-card"
 
CardError = object of ValueError
 
 
proc toCard(cardStr: string): Card =
## Convert a card string to a Card.
var runes = cardStr.toRunes
let suitStr = $(runes.pop()) # Extract the suit.
let faceStr = $runes # Take what’s left as the face.
try:
result.face = parseEnum[Face](faceStr)
except ValueError:
raise newException(CardError, "wrong face: " & faceStr)
try:
result.suit = parseEnum[Suit](suitStr)
except ValueError:
raise newException(CardError, "wrong suit: " & suitStr)
 
 
proc value(hand: openArray[Card]): HandValue =
## Return the value of a hand.
 
doAssert hand.len == 5, "Hand must have five cards."
 
var
cards: seq[Card] # The cards.
faces: CountTable[Face] # Count faces.
suits: CountTable[Suit] # Count suits.
 
for card in hand:
if card in cards: return Invalid # Duplicate card.
cards.add card
faces.inc card.face
suits.inc card.suit
 
faces.sort() # Greatest counts first.
suits.sort() # Greatest counts first.
cards.sort() # Smallest faces first.
 
# Check faces.
for face, count in faces:
case count
of 4:
return FourOfAKind
of 3:
result = ThreeOfAKind
of 2:
if result == ThreeOfAKind: return FullHouse
if result == OnePair: return TwoPair
result = OnePair
else:
if result != Invalid: return
 
# Search straight.
result = Straight
let start = if cards[0].face == Ace and cards[4].face == King: 2 else: 1
for n in start..4:
if cards[n].face != succ(cards[n - 1].face):
result = HighCard # No straight.
break
 
# Check suits.
if suits.len == 1: # A single suit.
result = if result == Straight: StraightFlush else: Flush
 
 
proc `$`(card: Card): string =
## Return the representation of a card.
var val = 0x1F0A0 + ord(card.suit) * 0x10 + ord(card.face)
if card.face >= Queen: inc val # Skip Knight.
result = $Rune(val)
 
 
 
when isMainModule:
 
const HandStrings = ["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♥",
"4♥ 4♠ k♠ 5♦ 10♠",
"q♣ 10♣ 7♣ 6♣ 4♣",
"4♥ 4♣ 4♥ 4♠ 4♦"]
 
for handString in HandStrings:
let hand = handString.split(' ').map(toCard)
echo hand.map(`$`).join(" "), " → ", hand.value</syntaxhighlight>
 
{{out}}
<pre>🂲 🃂 🃒 🃞 🃍 → three-of-a-kind
🂲 🂵 🃇 🃘 🂩 → high-card
🂱 🃂 🃓 🃔 🃅 → straight
🂲 🂳 🃂 🃓 🃃 → full-house
🂲 🂷 🃂 🃓 🃃 → two-pair
🂲 🂷 🃇 🃗 🂧 → four-of-a-kind
🂺 🂻 🂽 🂾 🂱 → straight-flush
🂴 🂤 🂮 🃅 🂪 → one-pair
🃝 🃚 🃗 🃖 🃔 → flush
🂴 🃔 🂴 🂤 🃄 → invalid</pre>
 
=={{header|Perl}}==
I dont like jokers. Instead I decided to give hands proper names. For example, "Kings full of Tens" rather than just "full-house".
 
<langsyntaxhighlight lang="perl">
use strict;
use warnings;
Line 2,054 ⟶ 3,658:
say Hand::describe($_) for @cards;
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,075 ⟶ 3,679:
</pre>
 
=={{header|Perl 6Phix}}==
Woke up this morning with a neat idea for detecting straights, though jokers messed it up a bit.<br>
This solution handles jokers. It has been written to use a Perl 6 grammar.
Uses an ad-hoc ranking system/tie breaker, not recommended for use in tournaments! Displays hands best-first.<br>
<lang perl6>use v6;
Note: I have left a copy of this in demo\HelloUTF8.exw to prove it works, but non-ascii on a Windows
console is not Phix's forte.<br>
grammar PokerHand {
For an(other) example of using the unicode card characters see [[Playing_cards#Phix]]<br>
{{libheader|Phix/online}}
# Perl6 Grammar to parse and rank 5-card poker hands
You can run this online [http://phix.x10.mx/p2js/poker_hand.htm here].
# E.g. PokerHand.parse("2♥ 3♥ 2♦ 3♣ 3♦");
<!--<syntaxhighlight lang="phix">(phixonline)-->
# 2013-12-21: handle 'joker' wildcards; maximum of two
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">poker</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">hand</span><span style="color: #0000FF;">)</span>
rule TOP {
<span style="color: #000000;">hand</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">substitute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"10"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"t"</span><span style="color: #0000FF;">)</span>
:my %*PLAYED;
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cards</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">)</span>
{ %*PLAYED = () }
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cards</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">5</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"invalid hand"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
[ <face-card> | <joker> ]**5
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ranks</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">),</span>
}
<span style="color: #000000;">suits</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">jokers</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
token face-card {<face><suit> <?{
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cards</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
my $card = ~$/.lc;
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ci</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">utf8_to_utf32</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cards</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
# disallow duplicates
<span style="color: #008080;">if</span> <span style="color: #000000;">ci</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"joker"</span> <span style="color: #008080;">then</span>
++%*PLAYED{$card} <= 1;
<span style="color: #000000;">jokers</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
}>
<span style="color: #008080;">if</span> <span style="color: #000000;">jokers</span><span style="color: #0000FF;">></span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"invalid hand"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
}
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ci</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">2</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"invalid hand"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
token joker {:i 'joker' <?{
<span style="color: #004080;">integer</span> <span style="color: #000000;">rank</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ci</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]),</span><span style="color: #008000;">"23456789tjqka"</span><span style="color: #0000FF;">)</span>
my $card = ~$/.lc;
<span style="color: #004080;">integer</span> <span style="color: #000000;">suit</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ci</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #7060A8;">utf8_to_utf32</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"♥♣♦♠"</span><span style="color: #0000FF;">))</span>
# allow two jokers in a hand
<span style="color: #008080;">if</span> <span style="color: #000000;">rank</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">suit</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #008000;">"invalid hand"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
++%*PLAYED{$card} <= 2;
<span style="color: #000000;">ranks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">rank</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
}>
<span style="color: #000000;">suits</span><span style="color: #0000FF;">[</span><span style="color: #000000;">suit</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
}
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
token face {:i <[2..9 jqka]> | 10 }
<span style="color: #004080;">integer</span> <span style="color: #000000;">straight</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)</span>
token suit {<[♥ ♦ ♣ ♠]>}
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">straight</span> <span style="color: #008080;">then</span>
}
<span style="color: #000000;">straight</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">))[$]=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">match</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
class PokerHand::Actions {
<span style="color: #004080;">integer</span> <span style="color: #000000;">_flush</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">suits</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">jokers</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
method TOP($/) {
<span style="color: #004080;">integer</span> <span style="color: #000000;">_pairs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">jokers</span>
my UInt @n = n-of-a-kind($/);
<span style="color: #004080;">integer</span> <span style="color: #000000;">pair</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)</span>
my $flush = flush($/);
<span style="color: #004080;">integer</span> <span style="color: #000000;">full_house</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">_pairs</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span> <span style="color: #008080;">and</span> <span style="color: #000000;">pair</span> <span style="color: #008080;">and</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">jokers</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pair</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">))</span>
my $straight = straight($/);
<span style="color: #004080;">integer</span> <span style="color: #000000;">two_pair</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pair</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
make rank(@n[0], @n[1], $flush, $straight);
<span style="color: #004080;">integer</span> <span style="color: #000000;">high_card</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">rfind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">sq_ne</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">))+</span><span style="color: #000000;">1</span>
}
<span style="color: #008080;">if</span> <span style="color: #000000;">jokers</span> <span style="color: #008080;">and</span> <span style="color: #000000;">_pairs</span><span style="color: #0000FF;">=</span><span style="color: #000000;">jokers</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
multi sub rank(5,$,$,$) { 'five-of-a-kind' }
<span style="color: #000000;">straight</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
multi sub rank($,$,$f,$s where {$f && $s}) { 'straight-flush' }
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">jokers</span>
multi sub rank(4,$,$,$) { 'four-of-a-kind' }
<span style="color: #008080;">for</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">k</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">5</span><span style="color: #0000FF;">-</span><span style="color: #000000;">j</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
multi sub rank($,$,$f,$ where {$f}) { 'flush' }
<span style="color: #008080;">if</span> <span style="color: #000000;">ranks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">l</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
multi sub rank($,$,$,$s where {$s}) { 'straight' }
<span style="color: #008080;">if</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
multi sub rank(3,2,$,$) { 'full-house' }
<span style="color: #000000;">straight</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
multi sub rank(3,$,$,$) { 'three-of-a-kind' }
multi sub rank(2,2,$,$) <span style="color: { 'two-pair' }#008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
multi sub rank(2,$,$,$) { 'one-pair' }
<span style="color: #000000;">j</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
multi sub rank($,$,$,$) is default { 'high-card' }
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">straight</span> <span style="color: #008080;">and</span> <span style="color: #000000;">j</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">high_card</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">high_card</span><span style="color: #0000FF;">+</span><span style="color: #000000;">j</span><span style="color: #0000FF;">,</span><span style="color: #000000;">14</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">straight</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ranks</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">high_card</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">_pairs</span><span style="color: #0000FF;">=</span><span style="color: #000000;">5</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"five of a kind"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">5</span><span style="color: #0000FF;">-</span><span style="color: #000000;">jokers</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">straight</span> <span style="color: #008080;">and</span> <span style="color: #000000;">_flush</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"straight flush"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">high_card</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">_pairs</span><span style="color: #0000FF;">=</span><span style="color: #000000;">4</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"four of a kind"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">4</span><span style="color: #0000FF;">-</span><span style="color: #000000;">jokers</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">full_house</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"full house"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">-</span><span style="color: #000000;">jokers</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">_flush</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"flush"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">high_card</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">straight</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"straight"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">high_card</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">_pairs</span><span style="color: #0000FF;">=</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"three of a kind"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">-</span><span style="color: #000000;">jokers</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ranks</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pair</span> <span style="color: #008080;">and</span> <span style="color: #000000;">two_pair</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"two pair"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">two_pair</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pair</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"one pair"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pair</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">jokers</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"one pair"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">high_card</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"high card"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">high_card</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hands</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"2♥ 2♦ 2♣ k♣ q♦"</span><span style="color: #0000FF;">},</span>
sub n-of-a-kind($/) {
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"2♥ 5♥ 7♦ 8♣ 9♠"</span><span style="color: #0000FF;">},</span>
my %faces := bag @<face-card>.map: -> $/ {~$<face>.lc};
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"a♥ 2♦ 3♣ 4♣ 5♦"</span><span style="color: #0000FF;">},</span>
my @counts = %faces.values.sort.reverse;
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"2♥ 3♥ 2♦ 3♣ 3♦"</span><span style="color: #0000FF;">},</span>
@counts[0] += @<joker>;
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"2♥ 7♥ 2♦ 3♣ 3♦"</span><span style="color: #0000FF;">},</span>
return @counts;
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"2♥ 7♥ 7♦ 7♣ 7♠"</span><span style="color: #0000FF;">},</span>
}
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"10♥ j♥ q♥ k♥ a♥"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"4♥ 4♠ k♠ 5♦ 10♠"</span><span style="color: #0000FF;">},</span>
sub flush($/) {
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"q♣ 10♣ 7♣ 6♣ 4♣"</span><span style="color: #0000FF;">},</span>
my @suits = unique @<face-card>.map: -> $/ {~$<suit>};
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker 2♦ 2♠ k♠ q♦"</span><span style="color: #0000FF;">},</span>
return +@suits == 1;
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker 5♥ 7♦ 8♠ 9♦"</span><span style="color: #0000FF;">},</span>
}
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker 2♦ 3♠ 4♠ 5♠"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker 3♥ 2♦ 3♠ 3♦"</span><span style="color: #0000FF;">},</span>
sub straight($/) {
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker 7♥ 2♦ 3♠ 3♦"</span><span style="color: #0000FF;">},</span>
# allow both ace-low and ace-high straights
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker 7♥ 7♦ 7♠ 7♣"</span><span style="color: #0000FF;">},</span>
constant @Faces = [ "a 2 3 4 5 6 7 8 9 10 j q k a".split: ' ' ];
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker j♥ q♥ k♥ A♥"</span><span style="color: #0000FF;">},</span>
constant @Possible-Straights = [ (0 .. (+@Faces - 5)).map: { set @Faces[$_ .. $_+4] } ];
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker 4♣ k♣ 5♦ 10♠"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker k♣ 7♣ 6♣ 4♣"</span><span style="color: #0000FF;">},</span>
my $faces = set @<face-card>.map: -> $/ {~$<face>.lc};
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker 2♦ joker 4♠ 5♠"</span><span style="color: #0000FF;">},</span>
my $non-jokers = 5 - +@<joker>;
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker Q♦ joker A♠ 10♠"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker Q♦ joker A♦ 10♦"</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"joker 2♦ 2♠ joker q♦"</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hands</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">hands</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">poker</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hands</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">hands</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hands</span><span style="color: #0000FF;">)))</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">rank</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">hand</span><span style="color: #0000FF;">,</span><span style="color: #000000;">desc</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hands</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">rank</span><span style="color: #0000FF;">,</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">},</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hands</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d. %s %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">11</span><span style="color: #0000FF;">-</span><span style="color: #000000;">rank</span><span style="color: #0000FF;">,</span><span style="color: #000000;">hand</span><span style="color: #0000FF;">,</span><span style="color: #000000;">desc</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
1. joker  7♥  7♦  7♠  7♣ five of a kind
2. joker  j♥  q♥  k♥  A♥ straight flush
2. joker  Q♦  joker  A♦ 10♦ straight flush
2. 10♥ j♥ q♥ k♥ a♥ straight flush
3. 2♥ 7♥ 7♦ 7♣ 7♠ four of a kind
3. joker  3♥  2♦  3♠  3♦ four of a kind
3. joker  2♦  2♠  joker  q♦ four of a kind
4. 2♥ 3♥ 2♦ 3♣ 3♦ full house
5. joker  k♣  7♣  6♣  4♣ flush
5. q♣ 10♣ 7♣ 6♣ 4♣ flush
6. joker  Q♦  joker  A♠ 10♠ straight
6. joker  5♥  7♦  8♠  9♦ straight
6. joker  2♦  joker  4♠  5♠ straight
6. joker  2♦  3♠  4♠  5♠ straight
6. a♥ 2♦ 3♣ 4♣ 5♦ straight
7. joker  7♥  2♦  3♠  3♦ three of a kind
7. joker  2♦  2♠  k♠  q♦ three of a kind
7. 2♥ 2♦ 2♣ k♣ q♦ three of a kind
8. 2♥ 7♥ 2♦ 3♣ 3♦ two pair
9. joker  4♣  k♣  5♦ 10♠ one pair
9. 4♥ 4♠ k♠ 5♦ 10♠ one pair
10. 2♥ 5♥ 7♦ 8♣ 9♠ high card
</pre>
 
=={{header|Picat}}==
return ?( @Possible-Straights.first: { +($faces ∩ $_) == $non-jokers; } );
<syntaxhighlight lang="picat">go =>
}
Hands = [
}
[[2,h], [7,h], [2,d], [3,c], [3,d]], % two-pair
[[2,h], [5,h], [7,d], [8,c], [9,s]], % high-card
[[a,h], [2,d], [3,c], [4,c], [5,d]], % straight
[[2,h], [3,h], [2,d], [3,c], [3,d]], % full-house
[[2,h], [7,h], [2,d], [3,c], [3,d]], % two-pair
[[2,h], [7,h], [7,d], [7,c], [7,s]], % four-of-a-kind
[[10,h],[j,h], [q,h], [k,h], [a,h]], % straight-flush
[[4,h], [4,s], [k,s], [5,d], [10,s]], % one-pair
[[q,c], [10,c],[7,c], [6,c], [4,c]], % flush
[[q,c], [q,d], [q,s], [6,c], [4,c]], % three-of-a-kind
 
[[q,c], [10,c], [7,c], [7,c], [4,c]], % invalid (duplicates)
[[q,c], [10,c], [7,c], [7,d]] % invalid (too short)
 
],
foreach(Hand in Hands)
print_hand(Hand),
analyse(Hand, H),
println(hand=H),
nl
end,
nl.
 
 
% Print the hand
print_hand(Hand) =>
println([ F.to_string() ++ S.to_string() : [F,S] in Hand]).
 
% Faces and suites
faces(Faces) => Faces = [a, 2, 3, 4, 5, 6, 7, 8, 9, 10, j, q, k].
faces_order1(Order1) =>
Order1 = new_map([a=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9, 10=10, j=11, q=12, k=13]).
faces_order2(Order2) =>
Order2 = new_map([2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9, 10=10, j=11, q=12, k=13, a=14]).
 
suites(Suites) => Suites = [h,d,c,s].
 
% Order of the hand
hand_order(HandOrder) =>
HandOrder = [straight_flush,
four_of_a_kind,
full_house,
flush,
straight,
three_of_a_kind,
two_pair,
one_pair,
high_card,
invalid].
 
 
% for the straight
in_order(List) =>
foreach(I in 2..List.length)
List[I] = List[I-1] + 1
end.
 
 
% Some validity tests first
analyse(Hand,Value) ?=>
(
Hand.remove_dups.length == 5,
faces(Faces),
foreach([F,_] in Hand)
member(F,Faces)
end,
suites(Suites),
foreach([_,S] in Hand)
member(S,Suites)
end,
analyse1(Hand,Value)
;
Value = invalid
).
 
% Identify the specific hands
 
% straight flush
analyse1(Hand,Value) ?=>
permutation(Hand,Hand1),
Hand1 = [ [_F1,S], [_F2,S], [_F3,S], [_F4,S], [_F5,S] ],
(
faces_order1(Order1),
in_order([Order1.get(F) : [F,S1] in Hand1])
;
faces_order2(Order2),
in_order([Order2.get(F) : [F,S1] in Hand1]),
println("Royal Straight Flush!")
),
Value=straight_flush.
 
% four of a kind
analyse1(Hand,Value) ?=>
faces(Faces),
member(A,Faces),
[1 : [F,_S] in Hand, F = A].length == 4,
Value=four_of_a_kind.
 
% full house
analyse1(Hand,Value) ?=>
permutation(Hand,Hand1),
Hand1 = [ [F1,_S1], [F1,_S2], [F2,_S3], [F2,_S4], [F2,_S5] ],
Value = full_house.
 
% flush
analyse1(Hand,Value) ?=>
permutation(Hand,Hand1),
Hand1 = [ [_,S], [_,S], [_,S], [_,S], [_,S] ],
Value = flush.
 
% straight
analyse1(Hand,Value) ?=>
permutation(Hand,Hand1),
(
faces_order1(Order1),
in_order([Order1.get(F) : [F,_S] in Hand1])
;
faces_order2(Order2),
in_order([Order2.get(F) : [F,_S] in Hand1])
 
),
Value = straight.
 
% three of a kind
analyse1(Hand,Value) ?=>
faces(Faces),
member(A,Faces),
[1 : [F,_S] in Hand, F = A].length == 3,
Value = three_of_a_kind.
 
% two pair
analyse1(Hand,Value) ?=>
permutation(Hand,Hand1),
Hand1 = [ [F1,_S1], [F1,_S2], [F2,_S3], [F2,_S4], [_F3,_S5] ],
Value = two_pair.
 
% one pair
analyse1(Hand,Value) ?=>
faces(Faces),
member(A,Faces),
[1 : [F,_S] in Hand, F = A].length == 2,
Value = one_pair.
 
% high card
analyse1(_Hand,Value) =>
Value = high_card.</syntaxhighlight>
 
my PokerHand::Actions $actions .= new;
 
for ("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
"4♥ 4♠ k♠ 5♦ 10♠", # one-pair
"q♣ 10♣ 7♣ 6♣ 4♣", # flush
"a♥ a♥ 3♣ 4♣ 5♦", # invalid
## EXTRA CREDIT ##
"joker 2♦ 2♠ k♠ q♦", # three-of-a-kind
"joker 5♥ 7♦ 8♠ 9♦", # straight
"joker 2♦ 3♠ 4♠ 5♠", # straight
"joker 3♥ 2♦ 3♠ 3♦", # four-of-a-kind
"joker 7♥ 2♦ 3♠ 3♦", # three-of-a-kind
"joker 7♥ 7♦ 7♠ 7♣", # five-of-a-kind
"joker j♥ q♥ k♥ A♥", # straight-flush
"joker 4♣ k♣ 5♦ 10♠", # one-pair
"joker k♣ 7♣ 6♣ 4♣", # flush
"joker 2♦ joker 4♠ 5♠", # straight
"joker Q♦ joker A♠ 10♠", # straight
"joker Q♦ joker A♦ 10♦", # straight-flush
"joker 2♦ 2♠ joker q♦", # four of a kind
) {
my $rank = do with PokerHand.parse($_, :$actions) {
.ast;
}
else {
'invalid';
}
say "$_: $rank";
}
</lang>
{{out}}
<pre>[2h,7h,2d,3c,3d]
<pre>2♥ 2♦ 2♣ k♣ q♦: three-of-a-kind
hand = two_pair
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
4♥ 4♠ k♠ 5♦ 10♠: one-pair
q♣ 10♣ 7♣ 6♣ 4♣: flush
a♥ a♥ 3♣ 4♣ 5♦: invalid
joker 2♦ 2♠ k♠ q♦: three-of-a-kind
joker 5♠ 7♦ 8♠ 9♦: straight
joker 2♦ 3♠ 4♠ 5♠: straight
joker 3♥ 2♦ 3♠ 3♦: four-of-a-kind
joker 7♥ 2♦ 3♠ 3♦: three-of-a-kind
joker 7♥ 7♦ 7♠ 7♣: five-of-a-kind
joker j♠ q♠ k♠ A♠: straight-flush
joker 4♣ k♣ 5♦ 10♠: one-pair
joker k♣ 7♣ 6♣ 4♣: flush
joker 2♦ joker 4♠ 5♠: straight
joker Q♦ joker A♠ 10♠: straight
joker Q♦ joker A♦ 10♦: straight-flush
joker 2♦ 2♠ joker q♦: four-of-a-kind</pre>
 
[2h,5h,7d,8c,9s]
=={{header|Phix}}==
hand = high_card
Woke up this morning with a neat idea for detecting straights, though jokers messed it up a bit.<br>
Uses an ad-hoc ranking system/tie breaker, not recommended for use in tournaments! Displays hands best-first.<br>
Note: I have left a copy of this in demo\HelloUTF8.exw to prove it works, but non-ascii on a Windows
console is not Phix's forte.<br>
For an example of using the unicode card characters see [[Playing_cards#Phix]]
<lang Phix>function poker(string hand)
hand = substitute(hand,"10","t")
sequence cards = split(hand,no_empty:=1)
if length(cards)!=5 then return "invalid hand" end if
sequence ranks = repeat(0,13),
suits = repeat(0,4)
integer jokers = 0
for i=1 to length(cards) do
sequence ci = utf8_to_utf32(cards[i])
if ci="joker" then
jokers += 1
if jokers>2 then return "invalid hand" end if
else
if length(ci)!=2 then return "invalid hand" end if
integer rank = find(lower(ci[1]),"23456789tjqka")
integer suit = find(ci[2],utf8_to_utf32("♥♣♦♠"))
if rank=0 or suit=0 then return "invalid hand" end if
ranks[rank] += 1
suits[suit] += 1
end if
end for
integer straight = match({1,1,1,1,1},ranks)
if not straight then
straight = sort(ranks)[$]=1 and match({0,0,0,0,0,0,0,0},ranks)
end if
integer _flush = (max(suits)+jokers = 5)
integer _pairs = max(ranks)+jokers
integer pair = find(2,ranks)
integer full_house = _pairs=3 and pair and (jokers=0 or find(2,ranks,pair+1))
integer two_pair = find(2,ranks,pair+1)
integer high_card = rfind(1,sq_ne(ranks,0))+1
if jokers and _pairs=jokers+1 then
straight = 1
integer k = find(1,ranks), j = jokers
for l=k to min(k+5-j,13) do
if ranks[l]=0 then
if j=0 then
straight = 0
exit
end if
j -= 1
end if
end for
if straight and j then
high_card = min(high_card+j,14)
end if
elsif straight and ranks[1]!=0 then
high_card = find(0,ranks)
end if
if _pairs=5 then return {10,"five of a kind", find(5-jokers,ranks)+1} end if
if straight and _flush then return {9,"straight flush", high_card} end if
if _pairs=4 then return {8,"four of a kind", find(4-jokers,ranks)+1} end if
if full_house then return {7,"full house", find(3-jokers,ranks)+1} end if
if _flush then return {6,"flush", high_card} end if
if straight then return {5,"straight", high_card} end if
if _pairs=3 then return {4,"three of a kind", find(3-jokers,ranks)+1} end if
if pair and two_pair then return {3,"two pair", two_pair+1} end if
if pair then return {2,"one pair", pair+1} end if
if jokers then return {2,"one pair", high_card} end if
return {1,"high card",high_card}
end function
 
[ah,2d,3c,4c,5d]
sequence hands = {{0,"2♥ 2♦ 2♣ k♣ q♦"},
hand = straight
{0,"2♥ 5♥ 7♦ 8♣ 9♠"},
 
{0,"a♥ 2♦ 3♣ 4♣ 5♦"},
[2h,3h,2d,3c,3d]
{0,"2♥ 3♥ 2♦ 3♣ 3♦"},
hand = full_house
{0,"2♥ 7♥ 2♦ 3♣ 3♦"},
 
{0,"2♥ 7♥ 7♦ 7♣ 7♠"},
[2h,7h,2d,3c,3d]
{0,"10♥ j♥ q♥ k♥ a♥"},
hand = two_pair
{0,"4♥ 4♠ k♠ 5♦ 10♠"},
 
{0,"q♣ 10♣ 7♣ 6♣ 4♣"},
[2h,7h,7d,7c,7s]
{0,"joker 2♦ 2♠ k♠ q♦"},
hand = four_of_a_kind
{0,"joker 5♥ 7♦ 8♠ 9♦"},
 
{0,"joker 2♦ 3♠ 4♠ 5♠"},
[10h,jh,qh,kh,ah]
{0,"joker 3♥ 2♦ 3♠ 3♦"},
Royal Straight Flush!
{0,"joker 7♥ 2♦ 3♠ 3♦"},
hand = straight_flush
{0,"joker 7♥ 7♦ 7♠ 7♣"},
 
{0,"joker j♥ q♥ k♥ A♥"},
[4h,4s,ks,5d,10s]
{0,"joker 4♣ k♣ 5♦ 10♠"},
hand = one_pair
{0,"joker k♣ 7♣ 6♣ 4♣"},
 
{0,"joker 2♦ joker 4♠ 5♠"},
[qc,10c,7c,6c,4c]
{0,"joker Q♦ joker A♠ 10♠"},
hand = flush
{0,"joker Q♦ joker A♦ 10♦"},
 
{0,"joker 2♦ 2♠ joker q♦"}}
[qc,qd,qs,6c,4c]
hand = three_of_a_kind
 
[qc,10c,7c,7c,4c]
hand = invalid
 
[qc,10c,7c,7d]
hand = invalid</pre>
 
For generating and checking random hands:
<syntaxhighlight lang="picat">go2 =>
_ = random2(),
Hand = random_hand(5),
print_hand(Hand),
analyse(Hand, H),
println(hand=H),
nl.
 
% Get one element of list L
oneof(L) = L[random(1,L.len)].
 
% Get a random hand
random_hand(N) = Hand =>
faces(Faces),
suites(Suites),
M = new_map(),
while (M.keys().length < N)
M.put([oneof(Faces),oneof(Suites)],1)
end,
Hand = [C : C=_ in M].sort().</syntaxhighlight>
 
for i=1 to length(hands) do
hands[i][1] = poker(hands[i][2])
end for
ppOpt({pp_Ascii,{#20,#FF}})
pp(reverse(sort(hands)))</lang>
{{out}}
<pre>[3d,5h,10c,10h,qs]
hand = one_pair</pre>
{{{10, "five of a kind", 7}, "joker 7♥ 7♦ 7♠ 7♣"},
 
{{9, "straight flush", 14}, "joker j♥ q♥ k♥ A♥"},
{{9, "straight flush", 14}, "joker Q♦ joker A♦ 10♦"},
{{9, "straight flush", 14}, "10♥ j♥ q♥ k♥ a♥"},
{{8, "four of a kind", 7}, "2♥ 7♥ 7♦ 7♣ 7♠"},
{{8, "four of a kind", 3}, "joker 3♥ 2♦ 3♠ 3♦"},
{{8, "four of a kind", 2}, "joker 2♦ 2♠ joker q♦"},
{{7, "full house", 3}, "2♥ 3♥ 2♦ 3♣ 3♦"},
{{6, "flush", 13}, "joker k♣ 7♣ 6♣ 4♣"},
{{6, "flush", 12}, "q♣ 10♣ 7♣ 6♣ 4♣"},
{{5, "straight", 14}, "joker Q♦ joker A♠ 10♠"},
{{5, "straight", 9}, "joker 5♥ 7♦ 8♠ 9♦"},
{{5, "straight", 6}, "joker 2♦ joker 4♠ 5♠"},
{{5, "straight", 5}, "joker 2♦ 3♠ 4♠ 5♠"},
{{5, "straight", 5}, "a♥ 2♦ 3♣ 4♣ 5♦"},
{{4, "three of a kind", 3}, "joker 7♥ 2♦ 3♠ 3♦"},
{{4, "three of a kind", 2}, "joker 2♦ 2♠ k♠ q♦"},
{{4, "three of a kind", 2}, "2♥ 2♦ 2♣ k♣ q♦"},
{{3, "two pair", 3}, "2♥ 7♥ 2♦ 3♣ 3♦"},
{{2, "one pair", 13}, "joker 4♣ k♣ 5♦ 10♠"},
{{2, "one pair", 4}, "4♥ 4♠ k♠ 5♦ 10♠"},
{{1, "high card", 9}, "2♥ 5♥ 7♦ 8♣ 9♠"}}
</pre>
 
=={{header|PicoLisp}}==
(rassoc) function in picolisp after 3.1.9.10.
<langsyntaxhighlight PicoLisplang="picolisp">(setq *Rank
'(("2" . 0) ("3" . 1) ("4" . 2)
("5" . 3) ("6" . 4) ("7" . 5)
Line 2,371 ⟶ 4,064:
'two-pair )
((rassoc 2 R) 'pair)
(T 'high-card) ) ) )</langsyntaxhighlight>
 
=={{header|Prolog}}==
{{works with|GNU Prolog|1.4.4}}
Not very efficient version.
<langsyntaxhighlight lang="python">:- initialization(main).
 
 
Line 2,446 ⟶ 4,139:
, write(Cards), write('\t'), write(H), nl
.
main :- findall(_, run_tests, _), halt.</langsyntaxhighlight>
{{out}}
<pre>[c(2,♥),c(2,♦),c(2,♣),c(k,♣),c(q,♦)] three-of-a-kind(2)
Line 2,460 ⟶ 4,153:
=={{header|Python}}==
Goes a little further in also giving the ordered tie-breaker information from the wikipedia page.
<langsyntaxhighlight lang="python">from collections import namedtuple
 
class Card(namedtuple('Card', 'face, suit')):
Line 2,609 ⟶ 4,302:
for cards in hands:
r = rank(cards)
print("%-18r %-15s %r" % (cards, r[0], r[1]))</langsyntaxhighlight>
{{out}}
<pre>HAND CATEGORY TIE-BREAKER
Line 2,623 ⟶ 4,316:
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
(require (only-in srfi/1 car+cdr))
 
Line 2,787 ⟶ 4,480:
(five-of-a-kind 7) (straight-flush 14) (one-pair 13 10 5 4) (flush 14 13 7 6 4) (straight 6)
(straight 14) (straight-flush 14) (four-of-a-kind 2)))
(for ((h e.g.-hands) (r expected-results)) (check-equal? (analyse-hand/string h) r)))</langsyntaxhighlight>
 
{{out}}
Line 2,813 ⟶ 4,506:
4♥ 4♠ K♠ 5♦ T♠: one-pair 4 [tiebreak: K, T, 5]
2♥ 5♥ 7♦ 8♣ 9♠: high-card 9 [tiebreak: 8, 7, 5, 2]</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
This solution handles jokers. It has been written to use a Raku grammar.
<syntaxhighlight lang="raku" line>use v6;
grammar PokerHand {
# Raku Grammar to parse and rank 5-card poker hands
# E.g. PokerHand.parse("2♥ 3♥ 2♦ 3♣ 3♦");
# 2013-12-21: handle 'joker' wildcards; maximum of two
rule TOP {
:my %*PLAYED;
{ %*PLAYED = () }
[ <face-card> | <joker> ]**5
}
token face-card {<face><suit> <?{
my $card = ~$/.lc;
# disallow duplicates
++%*PLAYED{$card} <= 1;
}>
}
token joker {:i 'joker' <?{
my $card = ~$/.lc;
# allow two jokers in a hand
++%*PLAYED{$card} <= 2;
}>
}
token face {:i <[2..9 jqka]> | 10 }
token suit {<[♥ ♦ ♣ ♠]>}
}
 
class PokerHand::Actions {
method TOP($/) {
my UInt @n = n-of-a-kind($/);
my $flush = 'flush' if flush($/);
my $straight = 'straight' if straight($/);
make rank(@n[0], @n[1], $flush, $straight);
}
multi sub rank(5,*@) { 'five-of-a-kind' }
multi sub rank($,$,'flush','straight') { 'straight-flush' }
multi sub rank(4,*@) { 'four-of-a-kind' }
multi sub rank($,$,'flush',$) { 'flush' }
multi sub rank($,$,$,'straight') { 'straight' }
multi sub rank(3,2,*@) { 'full-house' }
multi sub rank(3,*@) { 'three-of-a-kind' }
multi sub rank(2,2,*@) { 'two-pair' }
multi sub rank(2,*@) { 'one-pair' }
multi sub rank(*@) { 'high-card' }
sub n-of-a-kind($/) {
my %faces := bag @<face-card>.map: -> $/ {~$<face>.lc};
my @counts = %faces.values.sort.reverse;
@counts[0] += @<joker>;
return @counts;
}
sub flush($/) {
my @suits = unique @<face-card>.map: -> $/ {~$<suit>};
return +@suits == 1;
}
sub straight($/) {
# allow both ace-low and ace-high straights
constant @Faces = [ "a 2 3 4 5 6 7 8 9 10 j q k a".split: ' ' ];
constant @Possible-Straights = [ (4 ..^ @Faces).map: { set @Faces[$_-4 .. $_] } ];
 
my $faces = set @<face-card>.map: -> $/ {~$<face>.lc};
my $jokers = +@<joker>;
return ?( @Possible-Straights.first: { +($faces ∩ $_) + $jokers == 5 } );
}
}
 
my PokerHand::Actions $actions .= new;
 
for ("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
"4♥ 4♠ k♠ 5♦ 10♠", # one-pair
"q♣ 10♣ 7♣ 6♣ 4♣", # flush
"a♥ a♥ 3♣ 4♣ 5♦", # invalid
## EXTRA CREDIT ##
"joker 2♦ 2♠ k♠ q♦", # three-of-a-kind
"joker 5♥ 7♦ 8♠ 9♦", # straight
"joker 2♦ 3♠ 4♠ 5♠", # straight
"joker 3♥ 2♦ 3♠ 3♦", # four-of-a-kind
"joker 7♥ 2♦ 3♠ 3♦", # three-of-a-kind
"joker 7♥ 7♦ 7♠ 7♣", # five-of-a-kind
"joker j♥ q♥ k♥ A♥", # straight-flush
"joker 4♣ k♣ 5♦ 10♠", # one-pair
"joker k♣ 7♣ 6♣ 4♣", # flush
"joker 2♦ joker 4♠ 5♠", # straight
"joker Q♦ joker A♠ 10♠", # straight
"joker Q♦ joker A♦ 10♦", # straight-flush
"joker 2♦ 2♠ joker q♦", # four of a kind
) {
my $rank = do with PokerHand.parse($_, :$actions) {
.ast;
}
else {
'invalid';
}
say "$_: $rank";
}
</syntaxhighlight>
{{out}}
<pre>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
4♥ 4♠ k♠ 5♦ 10♠: one-pair
q♣ 10♣ 7♣ 6♣ 4♣: flush
a♥ a♥ 3♣ 4♣ 5♦: invalid
joker 2♦ 2♠ k♠ q♦: three-of-a-kind
joker 5♠ 7♦ 8♠ 9♦: straight
joker 2♦ 3♠ 4♠ 5♠: straight
joker 3♥ 2♦ 3♠ 3♦: four-of-a-kind
joker 7♥ 2♦ 3♠ 3♦: three-of-a-kind
joker 7♥ 7♦ 7♠ 7♣: five-of-a-kind
joker j♠ q♠ k♠ A♠: straight-flush
joker 4♣ k♣ 5♦ 10♠: one-pair
joker k♣ 7♣ 6♣ 4♣: flush
joker 2♦ joker 4♠ 5♠: straight
joker Q♦ joker A♠ 10♠: straight
joker Q♦ joker A♦ 10♦: straight-flush
joker 2♦ 2♠ joker q♦: four-of-a-kind</pre>
 
=={{header|REXX}}==
===version 1===
<langsyntaxhighlight lang="rexx">/* REXX ---------------------------------------------------------------
* 10.12.2013 Walter Pachl
*--------------------------------------------------------------------*/
Line 2,913 ⟶ 4,744:
err:
Say deck 'Error:' arg(1)
Return 0</langsyntaxhighlight>
{{out}}
<pre>2h 2d 2s ks qd three-of-a-kind
Line 2,939 ⟶ 4,770:
::* &nbsp; the dealt hands can be in a file &nbsp; (blank lines are ignored)
::* &nbsp; dealt hands in the file can have comments after a semicolon (''';''')
<langsyntaxhighlight lang="rexx">/*REXX program analyzes an N-cardN─card poker hand, and displays what the poker hand is. */
parse arg iFID .; if iFID=='' | iFID=="," then iFID= 'POKERHAN.DAT'
/* [↓] read the poker hands dealt. */
Line 2,965 ⟶ 4,796:
pips= overlay(_, pips, #) /*convert the pip to legitimate number.*/
kinds= max(kinds, _) /*convert certain pips to their number.*/
end /*i*/ /* [↑] keep track of N-of-a-kindN─of─a─kind. */
 
pairs run= countstrrun || left(2run, pips1) /*An ace can /*countbe number ofhigh pairs ─or─ low. (2s in PIPS).*/
pairs= countstr(2, pips) /*count number of pairs (2s in PIPS).*/
straight= pos(....., run || left(run, 1) ) \== 0 /*does the RUN contains a straight? */
if flush==5 & straight then return 'straight-flush'
Line 2,977 ⟶ 4,809:
if kinds==2 & pairs==2 then return 'two-pair'
if kinds==2 then return 'one-pair'
return 'high-card'</langsyntaxhighlight>
Programming note: some older REXXes don't have the '''countstr''' BIF, so that REXX statement (above, line '''48''') can be replaced with:
<langsyntaxhighlight lang="rexx">pairs= 13 - length( space( translate( pips, , 2), 0) ) /*count # of 2's in PIPS.*/</langsyntaxhighlight>
 
{{out|input|text=&nbsp; file:}}
Line 3,016 ⟶ 4,848:
::* &nbsp; supports up to two ''jokers''
::* &nbsp; the ''joker'' card may be abbreviated (and can be in upper/lower/mixed case)
<langsyntaxhighlight lang="rexx">/*REXX program analyzes an N-card poker hand, and displays what the poker hand is, */
/*──────────────────────────────────────────── poker hands may contain up to two jokers.*/
parse arg iFID .; if iFID=='' | iFID=="," then iFID= 'POKERHAJ.DAT'
Line 3,048 ⟶ 4,880:
pips= overlay(_, pips, #) /*convert the pip to legitimate number.*/
kinds= max(kinds, _) /*convert certain pips to their number.*/
end /*i*/ /* [↑] keep track of N-of-a-kindN─of─a─kind. */
 
run= run || left(run, 1) /*An ace can be high -or-─or─ low. */
jok= @.jk; kinds= kinds+jok; flush= flush+jok /*N─of─a─kind; adjustments for jokers.*/
straight= pos(..... , run)\==0 |, /*does the RUN contain a straight? */
Line 3,074 ⟶ 4,906:
if kinds==2 & pairs==2 then return 'two-pair'
if kinds==2 then return 'one-pair'
return 'high-card'</langsyntaxhighlight>
Programming note: &nbsp; the method used for analyzing hands that contain jokers are limited to a maximum of two jokers.
 
Line 3,128 ⟶ 4,960:
q♣ t♣ 7♣ 6♣ jok ◄─── flush
J♥ Q♦ K♠ A♠ jok ◄─── straight
</pre>
 
=={{header|RPL}}==
{{works with|HP|48G}}
≪ → hand
≪ { }
1 15 '''FOR''' j
"A23456789TJQK" hand j DUP SUB POS 1 -
"CDHS" hand j 1 + DUP SUB POS 13 * +
+ 3 '''STEP'''
≫ ≫ '<span style="color:blue>HANDCODE</span>' STO
≪ → diffs
≪ { } 1
1 4 '''FOR''' j
'''IF''' diffs j GET '''THEN''' + 1 '''ELSE''' 1 + '''END NEXT'''
+ SORT REVLIST 1 2 SUB
≫ ≫ '<span style="color:blue>GROUPS</span>' STO
≪ DUP ΠLIST 1 ==
SWAP { 9 1 1 1 } 1 == OR
≫ '<span style="color:blue>STRAIGHT?</span>' STO
≪ <span style="color:blue>HANDCODE</span>
DUP 13 / IP ≪ == ≫ DOSUBS ΠLIST
SWAP 13 MOD SORT ΔLIST
DUP <span style="color:blue>GROUPS</span> SWAP <span style="color:blue>STRAIGHT?</span>
→ flush groups straight
≪ '''CASE'''
straight '''THEN''' flush "Straight flush" "Straight" IFTE '''END'''
groups { 4 1 } == '''THEN''' "Four of a kind" '''END'''
groups { 3 2 } == '''THEN''' "Full house" '''END'''
groups { 3 1 } == '''THEN''' "Three of a kind" '''END'''
groups { 2 2 } == '''THEN''' "Two pairs" '''END'''
groups { 2 1 } == '''THEN''' "One pair" '''END'''
flush "Flush" "High card" IFTE '''END'''
≫ ≫ '<span style="color:blue>→HAND</span>' STO
 
{ "2H 2D 2S KS QD" "2H 5H 7D 8S 9D" "AH 2D 3S 4S 5S" "2H 3H 2D 3S 3D" "2H 7H 2D 3S 3D" "2H 7H 7D 7S 7C" "TH JH QH KH AH" "4H 4C KC 5D TC" "QC TC 7C 6C 4C" }
1 ≪ <span style="color:blue>→HAND</span> ≫ DOLIST
{{out}}
<pre>
1: { "Three of a kind" "High card" "Straight" "Full house" "Two pairs" "Four of a kind" "Straight flush" "One pair" "Flush" }
</pre>
 
=={{header|Ruby}}==
Joker-less hands are sorted high to low.
<langsyntaxhighlight lang="ruby">class Card
include Comparable
attr_accessor :ordinal
Line 3,275 ⟶ 5,150:
best = all_tries.max
puts "#{line.strip}: #{best.rank}"
end</langsyntaxhighlight>
 
{{out}}
Line 3,308 ⟶ 5,183:
joker Q♦ joker A♦ 10♦: straight-flush
joker 2♦ 2♠ joker q♦: four-of-a-kind
</pre>
 
=={{header|Rust}}==
Unicode version with jokers. Also checks for Royal Flush (AKQJ10 suited).
<syntaxhighlight lang="rust">
fn main() {
let hands = vec![
"🂡 🂮 🂭 🂫 🂪",
"🃏 🃂 🂢 🂮 🃍",
"🃏 🂵 🃇 🂨 🃉",
"🃏 🃂 🂣 🂤 🂥",
"🃏 🂳 🃂 🂣 🃃",
"🃏 🂷 🃂 🂣 🃃",
"🃏 🂷 🃇 🂧 🃗",
"🃏 🂻 🂽 🂾 🂱",
"🃏 🃔 🃞 🃅 🂪",
"🃏 🃞 🃗 🃖 🃔",
"🃏 🃂 🃟 🂤 🂥",
"🃏 🃍 🃟 🂡 🂪",
"🃏 🃍 🃟 🃁 🃊",
"🃏 🃂 🂢 🃟 🃍",
"🃏 🃂 🂢 🃍 🃍",
"🃂 🃞 🃍 🃁 🃊",
];
for hand in hands{
println!("{} {}", hand, poker_hand(hand));
}
}
 
fn poker_hand(cards: &str) -> &str {
let mut suits = vec![0u8; 4];
let mut faces = vec![0u8; 15];
let mut hand = vec![];
 
for card in cards.chars(){
if card == ' ' { continue; }
let values = get_card_value(card);
if values.0 < 14 && hand.contains(&values) {
return "invalid";
}
hand.push(values);
faces[values.0 as usize]+=1;
if values.1 >= 0 {
suits[values.1 as usize]+=1;
}
}
if hand.len()!=5 {
return "invalid";
}
faces[13] = faces[0]; //add ace-high count
let jokers = faces[14];
 
//count suits
let mut colors = suits.into_iter()
.filter(|&x| x > 0).collect::<Vec<_>>();
colors.sort_unstable();
colors[0] += jokers; // add joker suits to the highest one;
let is_flush = colors[0] == 5;
 
//straight
let mut is_straight = false;
//pointer to optimise some work
//avoids looking again at cards that were the start of a sequence
//as they cannot be part of another sequence
let mut ptr = 14;
while ptr>3{
let mut jokers_left = jokers;
let mut straight_cards = 0;
for i in (0..ptr).rev(){
if faces[i]==0 {
if jokers_left == 0 {break;}
jokers_left -= 1;
}
else if i==ptr-1 { ptr-=1; }
straight_cards+=1;
}
ptr-=1;
if straight_cards == 5 {
is_straight = true;
break;
}
}
 
//count values
let mut values = faces.into_iter().enumerate().take(14).filter(|&x| x.1>0).collect::<Vec<_>>();
//sort by quantity, then by value, high to low
values.sort_unstable_by(|a, b| if b.1 == a.1 { (b.0).cmp(&a.0) } else { (b.1).cmp(&a.1)} );
let first_group = values[0].1 + jokers;
let second_group = if values.len()>1 {values[1].1} else {0};
match (is_flush, is_straight, first_group, second_group){
(_,_,5,_) => "five-of-a-kind",
(true, true, _, _) => if ptr == 8 {"royal-flush"} else {"straight-flush"},
(_,_,4,_) => "four-of-a-kind",
(_,_,3,2) => "full-house",
(true,_,_,_) => "flush",
(_,true,_,_) => "straight",
(_,_,3,_) => "three-of-a-kind",
(_,_,2,2) => "two-pair",
(_,_,2,_) => "one-pair",
_ => "high-card"
}
}
 
fn get_card_value(card: char) -> (i8,i8) {
// transform glyph to face + suit, zero-indexed
let base = card as u32 - 0x1F0A1;
let mut suit = (base / 16) as i8;
let mut face = (base % 16) as i8;
if face > 11 && face < 14 { face-=1; } // Unicode has a Knight that we do not want
if face == 14 { suit = -1; } //jokers do not have a suit
(face, suit)
}
</syntaxhighlight>
{{out}}
<pre>
🂡 🂮 🂭 🂫 🂪 royal-flush
🃏 🃂 🂢 🂮 🃍 three-of-a-kind
🃏 🂵 🃇 🂨 🃉 straight
🃏 🃂 🂣 🂤 🂥 straight
🃏 🂳 🃂 🂣 🃃 four-of-a-kind
🃏 🃂 🂢 🂮 🃍 three-of-a-kind
🃏 🂵 🃇 🂨 🃉 five-of-a-kind
🃏 🃂 🂣 🂤 🂥 straight-flush
🃏 🂳 🃂 🂣 🃃 one-pair
🃏 🃂 🂢 🂮 🃍 flush
🃏 🂵 🃇 🂨 🃉 straight
🃏 🃂 🂣 🂤 🂥 straight
🃏 🂳 🃂 🂣 🃃 straight-flush
🃏 🃂 🂢 🂮 🃍 four-of-a-kind
🃏 🂵 🃇 🂨 🃉 invalid
🃏 🃞 🃍 🃁 🃊 high-card
</pre>
 
=={{header|Scala}}==
Including jokers, but not special suit characters. Aiming for readability more than performance.
<langsyntaxhighlight lang="scala">val faces = "23456789TJQKA"
val suits = "CHSD"
sealed trait Card
Line 3,385 ⟶ 5,392:
val possibleHands = possibleRealHands(hand)
allHandTypes.find(t => possibleHands.exists(t.check)).map(_.name).getOrElse("high-card")
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="scala">val testHands = List(
"2H 2D 2S KS QD",
"2H 5H 7D 8S 9D",
Line 3,412 ⟶ 5,419:
for (hand <- testHands) {
println(s"$hand -> ${analyzeHand(parseHand(hand))}")
}</langsyntaxhighlight>
 
{{out}}
Line 3,436 ⟶ 5,443:
QC TC 7C joker joker -> flush
QC TC 7H joker joker -> three-of-a-kind</pre>
 
=={{header|Seed7}}==
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "console.s7i";
 
const string: face is "A23456789TJQK";
const string: suit is "♥♦♣♠";
 
const func string: analyzeHand (in array integer: faceCnt, in array integer: suitCnt) is func
result
var string: handValue is "";
local
var boolean: pair1 is FALSE;
var boolean: pair2 is FALSE;
var boolean: three is FALSE;
var boolean: four is FALSE;
var boolean: flush is FALSE;
var boolean: straight is FALSE;
var integer: sequence is 0;
var integer: x is 0;
begin
for x range 1 to 13 do
case faceCnt[x] of
when {2}: if pair1 then pair2 := TRUE; else pair1 := TRUE; end if;
when {3}: three := TRUE;
when {4}: four := TRUE;
end case;
end for;
for x range 1 to 4 until flush do
if suitCnt[x] = 5 then
flush := TRUE;
end if;
end for;
if not pair1 and not three and not four then
for x range 1 to 13 until sequence = 5 do
if faceCnt[x] <> 0 then incr(sequence); else sequence := 0; end if;
end for;
straight := sequence = 5 or (sequence = 4 and faceCnt[1] <> 0);
end if;
if straight and flush then handValue := "straight-flush";
elsif four then handValue := "four-of-a-kind";
elsif pair1 and three then handValue := "full-house";
elsif flush then handValue := "flush";
elsif straight then handValue := "straight";
elsif three then handValue := "three-of-a-kind";
elsif pair1 and pair2 then handValue := "two-pair";
elsif pair1 then handValue := "one-pair";
else handValue := "high-card";
end if;
end func;
const proc: analyze (in string: cards) is func
local
var array integer: faceCnt is 13 times 0;
var array integer: suitCnt is 4 times 0;
var string: card is "";
begin
for card range split(upper(cards), ' ') do
incr(faceCnt[pos(face, card[1])]);
incr(suitCnt[pos(suit, card[2])]);
end for;
writeln(cards <& ": " <& analyzeHand(faceCnt, suitCnt));
end func;
 
const proc: main is func
begin
OUT := STD_CONSOLE;
analyze("2♥ 2♦ 2♠ k♠ q♦");
analyze("2♥ 5♥ 7♦ 8♠ 9♦");
analyze("a♥ 2♦ 3♠ 4♠ 5♠");
analyze("2♥ 3♥ 2♦ 3♠ 3♦");
analyze("2♥ 7♥ 2♦ 3♠ 3♦");
analyze("2♥ 7♥ 7♦ 7♠ 7♣");
analyze("t♥ j♥ q♥ k♥ a♥");
analyze("4♥ 4♣ k♣ 5♦ t♣");
analyze("q♣ t♣ 7♣ 6♣ 4♣");
end func;</syntaxhighlight>
 
{{out}}
<pre>
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
t♥ j♥ q♥ k♥ a♥: straight-flush
4♥ 4♣ k♣ 5♦ t♣: one-pair
q♣ t♣ 7♣ 6♣ 4♣: flush
</pre>
 
=={{header|Standard ML}}==
<syntaxhighlight lang="standard ml">
local
val rec ins = fn x : int*'a => fn [] => [x]
| ll as h::t => if #1 x<= (#1 h) then x::ll else h::ins x t
val rec acount = fn
(n,a::(b::t)) => if a=b then acount (n+1,b::t) else (n,a)::acount(1,b::t)
| (n,[t]) => [(n,t)]
in (* helper count and sort functions *)
val rec sortBy1st = fn [] => [] | h::t => ins h (sortBy1st t)
val addcount = fn ll => acount (1,ll)
end;
 
 
 
val showHand = fn input =>
let
exception Cheat of string
(* replace a j q k by their numbers *)
val translateCardstrings = fn inputstr =>
String.tokens (fn #" "=>true|_=>false) (String.translate (fn #"a"=>"1"| #"j"=>"11"| #"q"=>"12"| #"k"=>"13" | a=>str a ) inputstr )
 
(* parse numbers and characters into int*strings and order those *)
val parseFacesSuits = fn cardcodes =>
sortBy1st (List.map (fn el => (valOf (Int.fromString el ),String.extract (el,String.size el -1,NONE) )) cardcodes )
handle Option => raise Cheat "parse"
 
(* replace the list of face numbers by a list of every face with its count and order it / descending count *)
val countAndSort =fn li =>
let val hand = ListPair.unzip li in (rev (sortBy1st (addcount (#1 hand))) , #2 hand ) end;
 
 
val score = fn
( (4,_)::t , _ ) => "four-of-a-kind"
| ( (3,_)::(2,_)::t , _ ) => "full-house"
| ( (3,_)::t,_) => "three-of-a-kind"
| ( (2,_)::(2,_)::t,_) => "two-pair"
| ( (2,_)::t,_) => "one-pair"
| (x as (1,_)::t,ll) => if #2 (hd x ) - (#2 (hd (rev x))) =4 orelse ( #2 (hd (rev x)) = 1 andalso #2 (hd (tl (rev x))) =10 )
then
if List.all (fn x => hd ll=x) ll
then "straight-flush"
else "straight"
else if List.all (fn x => hd ll=x) ll then "flush" else "high-card"
| _ => "invalid"
 
 
 
(* return 'invalid' if any duplicates or invalid codes *)
val validate = fn lpair : (int * string) list =>
let val rec uniq = fn ([],y) =>true|(x,y) => List.filter (fn a=>a= hd x) y = [hd x] andalso uniq(tl x,y)
in
if List.all (fn x :int*string => #1 x > 0 andalso #1 x < 14 ) lpair
andalso List.all (fn (x) => Option.isSome ( List.find (fn a=> a= #2x) ["c","d","h","s"] ) ) lpair
andalso uniq (lpair ,lpair)
then lpair
else raise Cheat "value"
end
 
in
 
 
( score o countAndSort o validate o parseFacesSuits o translateCardstrings ) input handle Cheat ch => "invalid"
end;
</syntaxhighlight>
Example (interpreter):
<syntaxhighlight lang="standard ml">
val rec printio = fn
[] => ()
| s::t => (print (s^" : "); print ((showHand s)^"\n") before printio t) ;
printio
[ "2h 2d 2c kc qd" ,
"2h 5h 7d 8c 9s",
"ah 2d 3c 4c 5d" ,
"2h 3h 2d 3s 3d",
"2h 7h 2d 3c 3d",
"2h 7h 7d 7c 7s",
"10h jh qh kh ah",
"4h 4s ks 5d 10s",
"qc 10c 7c 6c 4c",
"ac ah ac ad 10h"] ;
 
2h 2d 2c kc qd : three-of-a-kind
2h 5h 7d 8c 9s : high-card
ah 2d 3c 4c 5d : straight
2h 3h 2d 3s 3d : full-house
2h 7h 2d 3c 3d : two-pair
2h 7h 7d 7c 7s : four-of-a-kind
10h jh qh kh ah : straight-flush
4h 4s ks 5d 10s : one-pair
qc 10c 7c 6c 4c : flush
ac ah ac ad 10h : invalid
val it = (): unit
</syntaxhighlight>
 
=={{header|Tcl}}==
{{works with|Tcl|8.6}}
<langsyntaxhighlight lang="tcl">package require Tcl 8.6
namespace eval PokerHandAnalyser {
proc analyse {hand} {
Line 3,554 ⟶ 5,748:
return 0
}
}</langsyntaxhighlight>
Demonstrating:
<langsyntaxhighlight lang="tcl">foreach hand {
"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♥" "4♥ 4♠ k♠ 5♦ 10♠"
Line 3,562 ⟶ 5,756:
} {
puts "${hand}: [PokerHandAnalyser::analyse $hand]"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,574 ⟶ 5,768:
4♥ 4♠ k♠ 5♦ 10♠: one-pair
q♣ 10♣ 7♣ 6♣ 4♣: flush
</pre>
 
=={{header|VBScript}}==
<syntaxhighlight lang="vb">
option explicit
class playingcard
dim suit
dim pips
'public property get gsuit():gsuit=suit:end property
'public property get gpips():gpips=pips:end property
public sub print
dim s,p
select case suit
case "S":s=chrW(&h2660)
case "D":s=chrW(&h2666)
case "C":s=chrW(&h2663)
case "H":s=chrW(&h2665)
end select
 
select case pips
case 1:p="A"
case 11:p="J"
case 12:p="Q"
case 13:p="K"
case else: p=""& pips
end select
 
wscript.stdout.write right(" "&p & s,3)&" "
end sub
end class
 
sub printhand(byref h,start)
dim i
for i =start to ubound(h)
h(i).print
next
'wscript.stdout.writeblanklines(1)
end sub
 
function checkhand(byval arr)
dim ss,i,max,last,uses,toppip,j,straight, flush,used,ace
redim nn(13)
ss=arr(0).suit '?????
straight=true:flush=true
max=0:last=0:used=0:toppip=0:ace=0
for i=0 to ubound(arr)
j=arr(i).pips
if arr(i).suit<>ss then flush=false
if j>toppip then toppip=j
if j=1 then ace=1
nn(j)=nn(j)+1
if nn(j)>max then max= nn(j)
if abs(j-toppip)>=4 then straight=0
next
for i=1 to ubound(nn)
if nn(i) then used=used+1
next
if max=1 then
if nn(1) and nn(10) and nn(11) and nn(12) and nn(13) then straight=1
end if
if flush and straight and max=1 then
checkhand= "straight-flush"
elseif flush then
checkhand= "flush"
elseif straight and max=1 then
checkhand= "straight"
elseif max=4 then
checkhand= "four-of-a-kind"
elseif max=3 then
if used=2 then
checkhand= "full-house"
else
checkhand= "three-of-a-kind"
end if
elseif max=2 then
if used=3 then
checkhand= "two-pair"
else
checkhand= "one-pair"
end if
else
checkhand= "Top "& toppip
End If
end function
 
 
function readhand(h)
dim i,b,c,p
redim a(4)
for i=0 to ubound(a)
b=h(i)
set c=new playingcard
p=left(b,1)
select case p
case "j": c.pips=11
case "q": c.pips=12
case "k": c.pips=13
case "t": c.pips=10
case "a": c.pips=1
case else c.pips=cint(p)
end select
c.suit=ucase(right(b,1))
set a(i)=c
next
readhand=a
erase a
end function
 
dim hands,hh,i
hands = Array(_
Array("2h", "5h", "7d", "8c", "9s"),_
Array("2h", "2d", "2c", "kc", "qd"),_
Array("ah", "2d", "3c", "4c", "5d"),_
Array("2h", "3h", "2d", "3c", "3d"),_
Array("2h", "7h", "2d", "3c", "3d"),_
Array("th", "jh", "qh", "kh", "ah"),_
Array("4h", "4s", "ks", "5d", "ts"),_
Array("qc", "tc", "7c", "6c", "4c"),_
Array("ah", "ah", "7c", "6c", "4c"))
 
for i=1 to ubound(hands)
hh=readhand(hands(i))
printhand hh,0
wscript.stdout.write vbtab & checkhand(hh)
wscript.stdout.writeblanklines(1)
'exit for
next
 
</syntaxhighlight>
{{out}}
<pre>
2♥ 2♦ 2♣ K♣ Q♦ three-of-a-kind
A♥ 2♦ 3♣ 4♣ 5♦ straight
2♥ 3♥ 2♦ 3♣ 3♦ full-house
2♥ 7♥ 2♦ 3♣ 3♦ two-pair
10♥ J♥ Q♥ K♥ A♥ straight-flush
4♥ 4♠ K♠ 5♦ 10♠ one-pair
Q♣ 10♣ 7♣ 6♣ 4♣ flush
A♥ A♥ 7♣ 6♣ 4♣ one-pair
</pre>
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-dynamic}}
{{libheader|Wren-sort}}
{{libheader|Wren-str}}
{{libheader|Wren-seq}}
===Basic Version===
<syntaxhighlight lang="wren">import "./dynamic" for Tuple
import "./sort" for Sort
import "./str" for Str
import "./seq" for Lst
 
var Card = Tuple.create("Card", ["face", "suit"])
 
var FACES = "23456789tjqka"
var SUITS = "shdc"
 
var isStraight = Fn.new { |cards|
var cmp = Fn.new { |i, j| (i.face - j.face).sign }
var sorted = Sort.merge(cards, cmp)
if (sorted[0].face + 4 == sorted[4].face) return true
if (sorted[4].face == 14 && sorted[0].face == 2 && sorted[3].face == 5) return true
return false
}
 
var isFlush = Fn.new { |cards|
var suit = cards[0].suit
if (cards.skip(1).all { |card| card.suit == suit }) return true
return false
}
 
var analyzeHand = Fn.new { |hand|
var h = Str.lower(hand)
var split = Lst.distinct(h.split(" ").where { |c| c != "" }.toList)
if (split.count != 5) return "invalid"
var cards = []
for (s in split) {
if (s.count != 2) return "invalid"
var fIndex = FACES.indexOf(s[0])
if (fIndex == -1) return "invalid"
var sIndex = SUITS.indexOf(s[1])
if (sIndex == -1) return "invalid"
cards.add(Card.new(fIndex + 2, s[1]))
}
var groups = Lst.groups(cards) { |card| card.face }
if (groups.count == 2) {
if (groups.any { |g| g[1].count == 4 }) return "four-of-a-kind"
return "full-house"
} else if (groups.count == 3) {
if (groups.any { |g| g[1].count == 3 }) return "three-of-a-kind"
return "two-pair"
} else if (groups.count == 4) {
return "one-pair"
} else {
var flush = isFlush.call(cards)
var straight = isStraight.call(cards)
if (flush && straight) return "straight-flush"
if (flush) return "flush"
if (straight) return "straight"
return "high-card"
}
}
 
var hands = [
"2h 2d 2c kc qd",
"2h 5h 7d 8c 9s",
"ah 2d 3c 4c 5d",
"2h 3h 2d 3c 3d",
"2h 7h 2d 3c 3d",
"2h 7h 7d 7c 7s",
"th jh qh kh ah",
"4h 4s ks 5d ts",
"qc tc 7c 6c 4c",
"ah ah 7c 6c 4c"
]
for (hand in hands) {
System.print("%(hand): %(analyzeHand.call(hand))")
}</syntaxhighlight>
 
{{out}}
<pre>
2h 2d 2c kc qd: three-of-a-kind
2h 5h 7d 8c 9s: high-card
ah 2d 3c 4c 5d: straight
2h 3h 2d 3c 3d: full-house
2h 7h 2d 3c 3d: two-pair
2h 7h 7d 7c 7s: four-of-a-kind
th jh qh kh ah: straight-flush
4h 4s ks 5d ts: one-pair
qc tc 7c 6c 4c: flush
ah ah 7c 6c 4c: invalid
</pre>
===Extra Credit Version===
<syntaxhighlight lang="wren">import "./dynamic" for Tuple
import "./sort" for Sort
import "./seq" for Lst
 
var Card = Tuple.create("Card", ["face", "suit"])
 
var cmp = Fn.new { |i, j| (i.face - j.face).sign }
 
var isStraight = Fn.new { |cards, jokers|
var sorted = Sort.merge(cards, cmp)
if (jokers == 0) {
if (sorted[0].face + 4 == sorted[4].face) return true
if (sorted[4].face == 14 && sorted[3].face == 5) return true
return false
} else if (jokers == 1) {
if (sorted[0].face + 3 == sorted[3].face) return true
if (sorted[0].face + 4 == sorted[3].face) return true
if (sorted[3].face == 14 && sorted[2].face == 4) return true
if (sorted[3].face == 14 && sorted[2].face == 5) return true
return false
} else {
if (sorted[0].face + 2 == sorted[2].face) return true
if (sorted[0].face + 3 == sorted[2].face) return true
if (sorted[0].face + 4 == sorted[2].face) return true
if (sorted[2].face == 14 && sorted[1].face == 3) return true
if (sorted[2].face == 14 && sorted[1].face == 4) return true
if (sorted[2].face == 14 && sorted[1].face == 5) return true
return false
}
}
 
var isFlush = Fn.new { |cards|
var sorted = Sort.merge(cards, cmp)
var suit = sorted[0].suit
if (sorted.skip(1).all { |card| card.suit == suit || card.suit == "j" }) return true
return false
}
 
var analyzeHand = Fn.new { |hand|
var split = Lst.distinct(hand.split(" ").where { |c| c != "" }.toList)
if (split.count != 5) return "invalid"
var cards = []
var jokers = 0
for (s in split) {
if (s.bytes.count != 4) return "invalid"
var cp = s.codePoints[0]
var card =
cp == 0x1f0a1 ? Card.new(14, "s") :
cp == 0x1f0b1 ? Card.new(14, "h") :
cp == 0x1f0c1 ? Card.new(14, "d") :
cp == 0x1f0d1 ? Card.new(14, "c") :
cp == 0x1f0cf ? Card.new(15, "j") : // black joker
cp == 0x1f0df ? Card.new(16, "j") : // white joker
(cp >= 0x1f0a2 && cp <= 0x1f0ab) ? Card.new(cp - 0x1f0a0, "s") :
(cp >= 0x1f0ad && cp <= 0x1f0ae) ? Card.new(cp - 0x1f0a1, "s") :
(cp >= 0x1f0b2 && cp <= 0x1f0bb) ? Card.new(cp - 0x1f0b0, "h") :
(cp >= 0x1f0bd && cp <= 0x1f0be) ? Card.new(cp - 0x1f0b1, "h") :
(cp >= 0x1f0c2 && cp <= 0x1f0cb) ? Card.new(cp - 0x1f0c0, "d") :
(cp >= 0x1f0cd && cp <= 0x1f0ce) ? Card.new(cp - 0x1f0c1, "d") :
(cp >= 0x1f0d2 && cp <= 0x1f0db) ? Card.new(cp - 0x1f0d0, "c") :
(cp >= 0x1f0dd && cp <= 0x1f0de) ? Card.new(cp - 0x1f0d1, "c") :
Card.new(0, "j") // invalid
if (card.face == 0) return "invalid"
if (card.suit == "j") jokers = jokers + 1
cards.add(card)
}
var groups = Lst.groups(cards) { |card| card.face }
if (groups.count == 2) {
if (groups.any { |g| g[1].count == 4 }) {
if (jokers == 0) return "four-of-a-kind"
return "five-of-a-kind"
}
return "full-house"
} else if (groups.count == 3) {
if (groups.any { |g| g[1].count == 3 }) {
if (jokers == 0) return "three-of-a-kind"
if (jokers == 1) return "four-of-a-kind"
return "five-of-a-kind"
}
return (jokers == 0) ? "two-pair" : "full-house"
} else if (groups.count == 4) {
if (jokers == 0) return "one-pair"
if (jokers == 1) return "three-of-a-kind"
return "four-of-a-kind"
} else {
var flush = isFlush.call(cards)
var straight = isStraight.call(cards, jokers)
if (flush && straight) return "straight-flush"
if (flush) return "flush"
if (straight) return "straight"
return (jokers == 0) ? "high-card" : "one-pair"
}
}
 
var hands = [
"🃏 🃂 🂢 🂮 🃍",
"🃏 🂵 🃇 🂨 🃉",
"🃏 🃂 🂣 🂤 🂥",
"🃏 🂳 🃂 🂣 🃃",
"🃏 🂷 🃂 🂣 🃃",
"🃏 🂷 🃇 🂧 🃗",
"🃏 🂻 🂽 🂾 🂱",
"🃏 🃔 🃞 🃅 🂪",
"🃏 🃞 🃗 🃖 🃔",
"🃏 🃂 🃟 🂤 🂥",
"🃏 🃍 🃟 🂡 🂪",
"🃏 🃍 🃟 🃁 🃊",
"🃏 🃂 🂢 🃟 🃍",
"🃏 🃂 🂢 🃍 🃍",
"🃂 🃞 🃍 🃁 🃊"
]
for (hand in hands) {
System.print("%(hand): %(analyzeHand.call(hand))")
}</syntaxhighlight>
 
{{out}}
<pre>
🃏 🃂 🂢 🂮 🃍: three-of-a-kind
🃏 🂵 🃇 🂨 🃉: straight
🃏 🃂 🂣 🂤 🂥: straight
🃏 🂳 🃂 🂣 🃃: four-of-a-kind
🃏 🂷 🃂 🂣 🃃: three-of-a-kind
🃏 🂷 🃇 🂧 🃗: five-of-a-kind
🃏 🂻 🂽 🂾 🂱: straight-flush
🃏 🃔 🃞 🃅 🂪: one-pair
🃏 🃞 🃗 🃖 🃔: flush
🃏 🃂 🃟 🂤 🂥: straight
🃏 🃍 🃟 🂡 🂪: straight
🃏 🃍 🃟 🃁 🃊: straight-flush
🃏 🃂 🂢 🃟 🃍: four-of-a-kind
🃏 🃂 🂢 🃍 🃍: invalid
🃂 🃞 🃍 🃁 🃊: high-card
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang "XPL0">string 0; \Use null-terminated strings (vs MSB terminated)
int Count(1+18); \Counts of ranks and suits in a hand
 
proc ShowCat; \Show category of poker hand
int I, J;
[for I:= 1 to 14 do
[if Count(I) = 1 then
[for J:= I+1 to I+4 do \are next 4 cards present?
if Count(J) # 1 then J:= 100;
if J <= 100 then
[Text(0, "straight");
for J:= 15 to 18 do \scan suits
if Count(J) >= 4 then Text(0, "-flush");
return;
];
];
];
for I:= 15 to 18 do
if Count(I) = 4 then [Text(0, "flush"); return];
for I:= 1 to 14 do \scan ranks
if Count(I) = 4 then
[Text(0, "four-of-a-kind"); return];
for I:= 1 to 14 do
[if Count(I) = 3 then
[for J:= 1 to 14 do
if Count(J) = 2 then
[Text(0, "full-house"); return];
Text(0, "three-of-a-kind"); return;
];
];
for I:= 1 to 14 do
[if Count(I) = 2 then
[for J:= 1 to 14 do
if J # I and Count(J) = 2 then
[Text(0, "two-pairs"); return];
Text(0, "one-pair"); return;
];
];
Text(0, "high-card");
];
 
int Hands, H, Card, I, Char, N, Invalid, Valid(4), Suit, Rank;
char Str;
[Hands:= [
"2h 2d 2c kc qd ",
"2h 5h 7d 8c 9s ",
"ah 2d 3c 4c 5d ",
"2h 3h 2d 3c 3d ",
"2h 7h 2d 3c 3d ",
"2h 7h 7d 7c 7s ",
"10h jh qh kh ah ",
"4h 4s ks 5d 10s ",
"qc 10c 7c 6c qc "];
for H:= 0 to 9-1 do
[for I:= 0 to 18 do Count(I):= 0;
for I:= 0 to 3 do Valid(I):= 0;
Invalid:= false;
Str:= Hands(H);
Card:= 0; I:= 0;
loop [Char:= Str(I); I:= I+1;
case Char of
^h: N:= 18;
^d: N:= 17;
^c: N:= 16;
^s: N:= 15;
^a: N:= 14;
^k: N:= 13;
^q: N:= 12;
^j: N:= 11;
^1: N:= 10;
^ : [N:= 0; Card:= Card+1; if Card >= 5 then quit]
other N:= Char-^0;
Count(N):= Count(N)+1;
if N = 14 then Count(1):= Count(1)+1; \two-place ace
if N <= 14 then Rank:= N
else [Suit:= N - 15;
if Valid(Suit) and 1<<Rank then Invalid:= true
else Valid(Suit):= Valid(Suit) or 1<<Rank;
];
];
Text(0, Str);
if Invalid then Text(0, "invalid")
else ShowCat;
CrLf(0);
];
]</syntaxhighlight>
{{out}}
<pre>
2h 2d 2c kc qd three-of-a-kind
2h 5h 7d 8c 9s high-card
ah 2d 3c 4c 5d straight
2h 3h 2d 3c 3d full-house
2h 7h 2d 3c 3d two-pairs
2h 7h 7d 7c 7s four-of-a-kind
10h jh qh kh ah straight-flush
4h 4s ks 5d 10s one-pair
qc 10c 7c 6c qc invalid
</pre>
297

edits