Task

Create a program to parse a single five card poker hand and rank it according to this list of poker hands.



A poker hand is specified as a space separated list of five playing cards.

Each input card has two characters indicating face and suit.



Example

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

alternatively,   the unicode card-suit characters:     ♥ ♦ ♣ ♠ 



Duplicate cards are illegal.

The program should analyze a single hand and produce one of the following outputs:

 straight-flush
 four-of-a-kind
 full-house
 flush
 straight
 three-of-a-kind
 two-pair
 one-pair
 high-card
 invalid



Examples

   2♥ 2♦ 2♣ k♣ q♦:   three-of-a-kind
   2♥ 5♥ 7♦ 8♣ 9♠:   high-card
   a♥ 2♦ 3♣ 4♣ 5♦:   straight
   2♥ 3♥ 2♦ 3♣ 3♦:   full-house
   2♥ 7♥ 2♦ 3♣ 3♦:   two-pair
   2♥ 7♥ 7♦ 7♣ 7♠:   four-of-a-kind 
   10♥ j♥ q♥ k♥ a♥:  straight-flush
   4♥ 4♠ k♠ 5♦ 10♠:  one-pair
   q♣ 10♣ 7♣ 6♣ q♣:  invalid

The programs output for the above examples should be displayed here on this page.



Extra credit

 use the playing card characters introduced with Unicode 6.0 (U+1F0A1 - U+1F0DE).
 allow two jokers
 use the symbol   joker
 duplicates would be allowed (for jokers only)
 five-of-a-kind would then be the highest hand


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


with javascript_semantics
function poker(string hand)
    hand = substitute(hand,"10","t")
    sequence cards = split(hand)
    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(deep_copy(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
 
sequence hands = {{0,"2♥ 2♦ 2♣ k♣ q♦"},
                  {0,"2♥ 5♥ 7♦ 8♣ 9♠"},
                  {0,"a♥ 2♦ 3♣ 4♣ 5♦"},
                  {0,"2♥ 3♥ 2♦ 3♣ 3♦"},
                  {0,"2♥ 7♥ 2♦ 3♣ 3♦"},
                  {0,"2♥ 7♥ 7♦ 7♣ 7♠"},
                  {0,"10♥ j♥ q♥ k♥ a♥"},
                  {0,"4♥ 4♠ k♠ 5♦ 10♠"},
                  {0,"q♣ 10♣ 7♣ 6♣ 4♣"},
                  {0,"joker  2♦  2♠  k♠  q♦"},
                  {0,"joker  5♥  7♦  8♠  9♦"},
                  {0,"joker  2♦  3♠  4♠  5♠"},
                  {0,"joker  3♥  2♦  3♠  3♦"},
                  {0,"joker  7♥  2♦  3♠  3♦"},
                  {0,"joker  7♥  7♦  7♠  7♣"},
                  {0,"joker  j♥  q♥  k♥  A♥"},
                  {0,"joker  4♣  k♣  5♦ 10♠"},
                  {0,"joker  k♣  7♣  6♣  4♣"},
                  {0,"joker  2♦  joker  4♠  5♠"},
                  {0,"joker  Q♦  joker  A♠ 10♠"},
                  {0,"joker  Q♦  joker  A♦ 10♦"},
                  {0,"joker  2♦  2♠  joker  q♦"}}
 
for i=1 to length(hands) do
    hands[i][1] = poker(hands[i][2])
end for
hands = reverse(sort(deep_copy(hands)))
integer rank
string hand,desc
for i=1 to length(hands) do
    {{rank,desc},hand} = hands[i]
    printf(1,"%d. %s %s\n",{11-rank,hand,desc})
end for
