Code Golf: Who has the best poker hand?
Asked Answered
M

6

18

I love challenges like this, I'll hopefully submit my answer soon.

Which player has the best 7 card hand?

Given an unordered list of 9 cards (separated by a space), work out which player has the best poker hand. Here is a list of poker hand rankings. Example input:

2C 5H AS KS 2D 4D QD KH 3S
(ie: [[2C 5H] [AS KS] [2D 4D QD KH 3S]])

First 2 cards in the array represent player 1's hand, second 2 in the array represent player 2's hand. The last 5 cards represent the community cards, cards both players share. In effect, both players have 7 cards, and you must determine which player has the best 5 card poker hand.

A card is defined as a string, with the first character representing the card value, and the second value representing the suit. Always upper-case. No card may appear twice.

The function will calculate if the hand is a draw or a win to either player. It will ouput the totals at the end of the input. The output format is defined later on in this post.

Examples

2C 5H AS KS 2D 4D QD KH 3S
(ie: [[2C 5H] [AS KS] [2D 4D QD KH 3S]])
Player 2 wins this hand.  Player 1 has a pair of 2's, player 2 has a pair of kings.

5S 6S 8H 9D 7S 8S JH TS 2H
(ie: [[5S 6S] [8H 9D] [7S 8S JH TS 2H]])
Player 1 wins this hand  Player 1 has a flush, player 2 has a straight.

2S 2H AC AS 2C AH 9H TS 2D    
(ie: [[2S 2H] [AC AS] [2C AH 9H TS 2D]])
Player 1 wins this hand.  Player 1 has quads, player 2 has a full house

5S 6S 2D 4D 9S AS KD JC 9D
(ie: [[5S 6S] [2D 4D] [9S AS KD JC 9D]])
A draw.  Both players have Ace high.

More Info

Thanks to mgroves for the following link to Project Euler which has a similar problem: http://projecteuler.net/index.php?section=problems&id=54

Test Data

We will use the Project Euler test data:

http://projecteuler.net/project/poker.txt

Your solution should accept that text file as input, and output a total of wins and draws.

Example Output

Output must be in this format:

1: 45
2: 32
D: 12

Player 1 won 45 hands, player 2 won 32 hands, and there were 12 draws. (Not actual results)

Rules

  • Doesn't have to return the winning hand type, only WHO won if anyone
  • Card list input has no particular order
  • No card appears twice in the input
  • Input is always uppercase
  • Takes the Project Euler test data as an input
  • Outputs a count, of which player won the most hands and total draws in given format above
Magulac answered 29/7, 2010 at 16:34 Comment(25)
Wouldn't it be better to calculate who has the best 5 card hand? Since the only poker variation that uses 7 cards is 7 card stud, and even then the hand is calculated via the 5 best cards.Salo
Note that the rules for who wins from the "5 best cards" is not trivial. I think for example '2H 3H 4H 5H 6H 7H 8H' and '4D 5D 6D 7D 8D AS AC' are equal (but I might be wrong).Jurat
"No lookup tables" seems pointlessly constraining. What tables are you envisioning being so short that they make other approaches unfeasible?Ovalle
@Mark Byers- by the rules of every variation of poker I know, you are correct: both would have "best" hands of a Straight-Flush, 4 - 8. By the OPs rules, this would return 0.Thermoluminescent
Your "integer" values don't work for this, though. Every card should have two values: Suit and Value. With your current example, you could not have an Ace of Spades (12 % 4 = 0 => Heart). I suppose you could only use ints 0 - 51, and then map directly, but I don't see a way to use a single value to get both 12%13 = 12 AND 12%4 = [anything but 0]Thermoluminescent
You are correct that a poker hand contains five cards, later when i'm not on my phone I will rephrase, you take the best 5 cards from the 7 available as this reflects most common variations of poker. For example in holdem you have 2 cards, and 5 community. So this challenge reflects on that problem.Magulac
@Allen: He mis-spoke. You use integer division, and the remainder to separate suit and rank. Now he just need to clear up which is which...Ovalle
similar Project Euler problem if anyone's interested: projecteuler.net/index.php?section=problems&id=54Ultranationalism
@Allen: 38 is the Ace of Spades, as 38%13 == 12 and 38%4 == 2. You can use remainder for both suit and rank as 13 and 4 are relatively prime.Antoinetteanton
@dmckee, a lookuptable is byfar the best solution, although it is a lot of work to build one. Pass in the hand Id which can be represented as a key from card ids and return the relative hand value as an integer (there are thousands of possible hand strength values)Magulac
@alleng, a straight to a queen (89tjq) is better than a straight to an 8 (45678). Also if both have flushes, you see who has the highest flush card, I equal 2nd highest etc. Wikipedia article explains it. I will phrase question better with better examples when I get home tonightMagulac
couldn't you make it accept 2h, 3d, 4c, 5s or something more readable for the input?Vizcacha
Whoops misread question, yes it's not trivial, I've studied the problem a lot and there are some very clever things you can do :-)Magulac
@chris yes but you will have a lot more chars to convert to usable format. I'll think about tonight and update later. Sorry for fannying round it's a bit more complicated than some othersMagulac
@Tom: Do you mean then "no lookup tables as input"? Because a table is big, and putting it in the program is a losing strategy. OTOH, writing a compact generator for the table would be both challenging and clever, making it a solution that we would want to see. For examples of previous involving tables in the code see the Morse Code question.Ovalle
@Tom Gullen - I was refering to Mark's example of two 4 - 8 straight-flush hands. Yes, with different straights, the higher straight wins, and with different flushes, the highest card in the flush wins. Same as two hands 2C, 2H, 5D, 5C, AH & 2D, 2S, 5S, 5H, KC: the first would win (an Ace "kicker.")Thermoluminescent
I've revised the description, made the inputs more readable and given better examples.Magulac
I've always played poker where [[5S 6S] [2D 4D] [9S AS KD JS 9D]] is not a draw. You successively weed out equal best hands (from a five card hand regardless of how many cards are available) until either one player does indeed have a better best hand or until all five cards are gone in wich there is a draw. So in this case player 1 wins, as a 6 is higher than a 4. (Their other highest cards are all in the community hand.) This is how I implemented my Haskell solution. Now if we had [[5S 6S] [2D 6D] [9S AS KD JS 9D]], then we would have a draw. The 5S and 2D have no impact on the game.Cording
Also the test input lines contain 10 cards, whereas we want 9 cards per line.Cording
Sorry, the above argument would work if player 1 doesn't have a flush. You get the idea.Cording
@trinithis, I've taken the flush out, thanks for spotting it. The rules of holdem state clearly that (without a flush) that hand is a draw. You take the best 5 available from the selection of 7. Both players play the board.Magulac
I'll change the test data to have 9 cards asap.Magulac
@Gullen: en.wikipedia.org/wiki/… Plus, you have to admit, kickers make the challenge more interesting :DCording
@Trinithis, kickers don't always qualify, I'm not saying NO kickers, I'm only saying they count when they count. 45 vs 67 on a 9TJKA board is a draw. 23 vs 67 on a 5TJKA board, 67 wins as their hand 7TJKA beats 9TJKAMagulac
Right, my mistake. I didn't properly look at the high cards in the shared board. No wonder why my code seemed buggy when it was correct (to my knowledge).Cording
S
15

Perl, 414 398 370/458 344/416 char

Line breaks are not significant.

%M=map{$_,$Z++}0..9,T,J,Q,K,A;sub N{/.$/;$M{$`}.$&}

sub B{$s=@p=();
for$m(@_){$m-$_||($s+=2,++$p[$m])for@_}
@_=sort{$p[$b]-$p[$a]||$b-$a}@_;
$s=23 if$s<11&&($_[0]-$_[4]<5||$_[0]-$_[1]>8&&push@_,shift);
"@_"=~/.$/;$s+=14*(4<grep/$&/,@_);
$s=100*$s+$_ for@_;$s}

++$X{B((@c=map{N}split)[0..4])<=>B(@c[5..9])}for<>;
printf"1: %d\n2: %d\nD: %d\n",@X{1,-1,0}

This solves the "10 card" problem (10 cards are dealt, player 1 has the first 5 cards and player 2 has the second 5 cards).

The first section defines a subroutine N that can transform each card so that it has a numerical value. For non-face cards, this is a trivial mapping (5H ==> 5H) but it does transform the face cards (KC => 13C, AD => 14D).

The last section parses each line of input into cards, transforms the cards to contain numerical values, divides the cards into separate hands for the two players, and analyzes and compares those hands. Every hand increments one element of the hash %X. When all the input is parsed, %X contains the number of hands won by player 1, won by player 2, or ties.

The middle section is a subroutine that takes a set of five cards as input and produces a 12-digit number with the property that stronger poker hands will have higher-valued numbers. Here's how it works:

    for$m(@_){$m-$_||($s+=2,++$p[$m])for@_}

This is the "pair" detector. If any two cards have the same numerical value, increment a hash element for one of the cards and increase the "score" variable $s by two. Note that we will end up comparing each card to itself, so $s will be at least 10 and $p[$x] will be at least one for every card $x. If the hand contains three of a kind, then those three cards will match with the other two cards -- it will be like there are 9 matches among those three cards and the "score" will be at least 18.

    @_=sort{$p[$b]-$p[$a]||$b-$a}@_;

Sort the cards by (1) the number of times that card is part of a "pair" and (2) the value of the card. Thus in a hand with two 7's and two 3's, the two 7's will appear first, followed by the two 3's, followed by the kicker. In a hand with two 7's and three 3's, the three 3's will be first followed by the two 7's. The goal of this ordering is to distinguish two hands that have the same score -- a hand with a pair of 8's and a hand with a pair of 7's both have one pair, but we need to be able to tell that a pair of 8's is better.

    $s=23 if$s<11&&($_[0]-$_[4]<5||$_[0]-$_[1]>8&&push@_,shift);

This line is the "straight" detector. A straight is worth 23 points and occurs when there are no pairs in the hand ($s<11 means only 5 "pairs" - each card matching with itself - were found) and either (1) the value of the highest card is exactly four more than the value of the lowest card ($_[0]-$_[4]==4), or (2) the highest value card is an Ace and the next highest card is a 5 ($_[0]-$_[1]==9), which means the hand has an A-2-3-4-5 straight. In the latter case, the Ace is now the least valuable card in the hand, so we manipulate @_ to reflect that (push@_,shift)

    "@_"=~/.$/;$s+=14*(4<grep/$&/,@_);

This line is the flush detector. A flush is worth 14 more points and occurs when the last character is the same for each card. The first expression ("@_"=~/.$/) has the side effect of setting $& to the last character (the suit) of the last card in the hand. The final expression (4<grep/$&/,@_) will be true if and only if all elements of @_ have the same last character.

    $s=100*$s+$_ for@_;$s}

Creates and returns a value that begins with the hand's score and then contains the values of the cards, in order of the card's importance. Scores for the various hands will be

Hand           Score
----------    ------
High card       10     (each card matches itself for two points)
One pair        14     (2 additional matches)
Two pair        18     (4 additional matches)
Three of a kind 22     (6 additional matches)
Straight        23     (no pair, but 23 points for straight)
Flush           24     (no pair, but 14 additional points for the flush)
Full house      26     (8 additional matches)
4 of a kind     34     (12 additional matches)
Straight flush  37     (23 + 14 points)

which is consistent with the rules of poker. Hands with the same score can be distinguished by the values of the hand's cards, in order of importance to the hand, all the way down to the least valuable card in the hand.

The solution to the 9 card problem (two cards to player 1, two cards to player 2, the players share the next 5 cards and build their best 5 card hand) needs about 70 more strokes to choose the best 5 card hand out of the 7 cards available to each player:

%M=map{$_,$Z++}0..9,T,J,Q,K,A;sub N{/./;$M{$&}.$'}

sub A{my$I;
for$k(0..41){@d=@_;splice@d,$_,1for$k%7,$k/7;$s=@p=();
for$m(grep$_=N,@d){$m-$_||($s+=2,$p[$m]++)for@d}
@d=sort{$p[$b]-$p[$a]||$b-$a}@d;
$s=23 if$s<11&&($d[0]-$d[4]<5||$d[0]-$d[1]>8&&push@d,shift@d);
"@d"=~/.$/;$s+=14*(4<grep/$&/,@d);
$s=100*$s+$_ for@d;
$I=$s if$s>$I}$I}

++$X{A((@c=split)[0,1,4..8])<=>A(@c[2..8])}for<>;
printf"1: %d\n2: %d\nD: %d\n",@X{1,-1,0}
Sunshade answered 29/7, 2010 at 16:34 Comment(0)
B
7

GolfScript - 151/187 chars

This program works on an input list of 10 cards per line, i.e. two 5 card hands.

n%0.@{3/5/{[zip~;.&,(!15*\[{n),*"TJQKA"+?}/]:|$),-4>=14*+1|{.2\?|@-,5\-.49?@*@+\.+@+\}/.16445=13*@+\]}%.~={0):0;;}{~>.!@+\@+\}if}/"1: "@@n"2: "@n"D: "0

This program works on an input list of 9 cards per line, of the format described in the specifications.

n%0.@{3/.4>:D;2/2<{D+.{3/1$^.{3/1$^[zip~;.&,(!15*\[{n),*"TJQKA"+?}/]$:|),-4>=14*+1|{.2\?|@-,5\-.49?@*@+\.+@+\}/.16445=13*@+\]}%\;~}%$-1=\;}%.~={0):0;\(\}*~>.!@+\@+\}/"1: "@@n"2: "@n"D: "0
Build answered 29/7, 2010 at 16:34 Comment(0)
C
7

Haskell: 793 796 806 826 864 904 901 880 863


Since the text file is inconsistent with 9 card hands, I'm just reading a line from the console and outputting who wins.


Bugfixes:

  • Ace now counts lower than a 2 in an ace-low run.
  • Comparing full houses fixed (again :D).
  • Guarantees that the best version of a given hand type is chosen. For example, if a player can choose between a 2-6 run and a 3-7 run, the 3-7 run is chosen (flushes aside).
  • Now shorter than the PHP solution!

Golfed:

import Data.List
(%)=mod
m=map
y=foldr1
t=0<1
z=13
w=[0,1,2,3,12]
n&x|length x<n=[]|t=take n x
b?x|b=x|t=[]
n!k= \c->e(n&m(%k)c)?(n&c)
e[]=1<1
e(x:y)=all(x==)y
k q c|any null[q c,p$c\\q c]=[]|t=q c
f=5!4
s c=(sort(m(%z)c)`elem`w:[[n..n+4]|n<-[0..8]])?c
r=3!z
p=2!z
g x y|c x y<2=x|t=y
q x(_,[])=x
q _ y=y
b h=y q$m($h)$zipWith(\t f->(,)t.y g.m(f.take 5).permutations)[1..][1!1,p,k p,r,s,f,k r,4!z,s.f]
h=reverse.a.m(%z)
a v|w\\v==[]=[-1..3]|t=sort v
c x y=o(h x)$h y
o[](_:_)=2
o[]_=0
o _[]=1
o(a:b)(k:d)|a>k=1|a<k=2|t=o b d
d n(a,k)|a==[]=0|n<1=0|r>s=1|r<s=2|f/=0=f|t=d(n-length o)(a\\o,k\\u)where(r,o)=b a;(s,u)=b k;f=c o u
i x=head.findIndices(x==)
u(n:k)c@[r,s]|n%z==i r"23456789TJQKA"&&n%4==i s"HDSC"=n|t=u k c
l c=(2&c++snd(splitAt 4c),drop 2c)
main=getLine>>=print.d 5.l.m(u[0..]).words

Ungolfed:

import Control.Exception (assert)
import Data.List (permutations, sort, intersect, findIndices, (\\))
import Data.Function (on)

(%) = mod

aceLowRun = [0,1,2,3,12]

tryTake n xs
  | length xs < n = []
  | otherwise = take n xs

cond ? xs
  | cond = xs
  | otherwise = []

eqOn n f cards = allEq (tryTake n $ map f cards) ? tryTake n cards

allEq [] = False
allEq (x:xs) = all (== x) xs

combWithPair pokerHand cards
  | any null [picked1, picked2] = []
  | otherwise = pokerHand cards
  where
    picked1 = pokerHand cards
    picked2 = pair $ cards \\ picked1

straightFlush = straight . flush

quads = eqOn 4 (% 13)

fullHouse = combWithPair triples

flush = eqOn 5 (% 4)

straight cards = (sort (map (% 13) cards) `elem` runs) ? cards
  where
    runs = aceLowRun : [[n..n+4] | n <- [0..8]]

triples = eqOn 3 (% 13)

twoPair = combWithPair pair

pair = eqOn 2 (% 13)

single = eqOn 1 id

bestVersionOfHand [] ys = ys
bestVersionOfHand xs [] = xs
bestVersionOfHand xs ys
  | compareSameRankedHands xs ys < 2 = xs
  | otherwise = ys

rate rating pokerHand cards = (rating, handResult)
  where
    handResult = foldr1 bestVersionOfHand
                        (map (pokerHand . take 5) $ permutations cards)

pokerHands = zipWith rate [1..] [
    single
  , pair
  , twoPair
  , triples
  , straight
  , flush
  , fullHouse
  , quads
  , straightFlush
  ]

bestHand hand = foldr1 (\xs ys -> if null (snd ys) then xs else ys)
                       (map ($ hand) pokerHands)

highestVals = reverse . arrangeVals . map (% 13)
  where
    arrangeVals vals = if vals `intersect` aceLowRun == aceLowRun
      then [-1..3]
      else sort vals

compareSameRankedHands = compareSameRankedHands' `on` highestVals

compareSameRankedHands' [] [] = 0
compareSameRankedHands' (card1:cards1) (card2:cards2)
  | card1 > card2 = 1
  | card1 < card2 = 2
  | otherwise = compareSameRankedHands' cards1 cards2

decideWinner n cards1 cards2
  | null cards1 = assert (null cards2) 0
  | n < 1 = 0
  | rating1 > rating2 = 1
  | rating1 < rating2 = 2
  | cmpRes /= 0 = cmpRes
  | otherwise = decideWinner
                  (n - assert (length bests1 == length bests2) (length bests1))
                  (cards1 \\ bests1)
                  (cards2 \\ bests2)
  where
    (rating1, bests1) = bestHand cards1
    (rating2, bests2) = bestHand cards2
    cmpRes = compareSameRankedHands bests1 bests2

indexOf x = head . findIndices (x==)

toNum = toNum' [0..]

toNum' (n:ns) [rank, suit]
  | n % 13 == indexOf rank "23456789TJQKA" && n % 4 == indexOf suit "HDSC" = n
  | otherwise = toNum' ns [rank, suit]

cluster cards = (take 2 cards ++ snd (splitAt 4 cards), drop 2 cards)

main = getLine >>= print
  . uncurry (decideWinner 5)
  . cluster
  . map toNum
  . words
Cording answered 29/7, 2010 at 16:34 Comment(1)
Excellent! Thanks for the efforts, I hope the revisions to the description won't be too much of a pain for you.Magulac
S
4

GolfScript 258 241 247/341 217/299 char

Solution for the 10 card problem. Only the last couple of newlines are significant:

10:T):J):Q):K):A;0:a;0:b;0:d;"\r\n"%{' '/5/{.{)\;}/4*-+++!:f;{);~}%{$0:z(%{.z-
!99*+:z}%}5*.{+}*99/:P!{..)\(@4+-!2*\;\.2<~9+-!\;+}and:s;[s f*6P=4P=f s P 6$]\;}
%.~={;;d):d;}{~>{a):a;}{b):b;}if}if}/
'1: 'a'
2: 'b'
D: 'd n

The 9 card problem currently needs about 80 more characters.

10:T):J):Q):K):A;0:a;0:b;0:d;"\r\n"%{' '/);{('Z'%+}2*[0$2>\7<]
{:H;7,{H=:x;H{x=!},:I;6,{I=:x;I{x=!},}/}%{.{)\;}/4*-+++!:f;
{);~}%{$0:z(%{.z-!99*+:z}%}5*.{+}*99/:P!{..)\(@4+-!2*\;\.2<~9+-!\;+}and:s;[
s f*6P=4P=f s P 6$]\;}%{[\].~>{~;}{~\;}if}*}%.~={;;d):d;}{~>{a):a;}{b):b;}if}if}/
'1: 'a'
2: 'b'
D: 'd n

Less golfed version of 10 card problem.

10:T;11:J;12:Q;13:K;14:A;              # map for face cards
0:a;0:b;0:d;                           # other initialization

"\r\n"%                                # split input on \n
{                                      # on each line of input
    ' '/                               #  divide line into ten cards
    5/                                 #  split into five card hands

    {.                                 #  on each of the two hands

         {)\;}%                        #   chop last character of each card
         .(5*\;\{+}*=                  #   check sum of elem == 5*1st elem
         :f;                           #   this is the flush flag

         {);~}%$                       #   reduce cards to numerical values

         0:z;{.z- 20%{}                
             {;z 20+}if:z}%{-1*}$      #   detect pairs

         .(:h;;                        #   extract value of highest card


         20h>{..)\(@4+-!2*\;\          # detect straight
             .2<~9+-!\;+}and:s;        # s=2 for regular straight, s=1 for A-5 straight

                                       # result of this mapping - 6 elem array
         [ 0$                          #   #6 - cards in the hand
           .{20/}%{+}*:P               #   #5 - number of pairs
           s                           #   #4 - is this a straight?
           f                           #   #3 - is this a flush?
           4P=                         #   #2b - is this a full house?
           h 59>                       #   #2 - is this 4 of a kind?
           s f *                       #   #1 - is this a straight flush?
         ]-1% 

    \;
    }/

    \.@.@                             # put [hand1 hand2 hand1 hand2] on stack

    =                                 # check hand1==hand2

    {;;d):d;}                         # if equal, increment d (draw)
       {>{a):a;}                      # if >, increment a (player 1 wins)
       {b):b;}if                      # if <, increment b (player 2 wins)
     }if
}/

                                      # output results    
'1: 'a'
2: 'b'
D: 'd n
Sunshade answered 29/7, 2010 at 16:34 Comment(0)
L
3

C, 665+379 chars

Here's my answer in 2 parts.

The first is a complete 7 card evaluator, including the "AddCard" macro A. It returns a 32-bit number ranking the hand. The high nibble is the type, bits 13..25 indicate the high card(s) and bits 0..12 indicate the kicker(s). When comparing the results, the better hand will always have the larger value.

#define U unsigned
#define c(a)X=a;i=C=0;while(X){C|=(X&1)<<i++;X/=4;}
#define A(h,c)h[c&7]+=c,h[3]|=c
U C,i,X;
U E(U h[]){
U a=h[0]+h[1]+h[2]+h[4]-(h[3]&-16),t,v,k,e=a&0x55555540,o=a&0xAAAAAA80;
if(v=e&o/2){t=7;k=h[3]^v;i=0;while(k/=4)i++;k=1<<2*i;}
else if(v=o&o-1){t=6;v/=2;k=o/2^v;}
else if(e>1&o>1){t=6;v=o/2;k=(i=e&e-1)?i:e;}
else{a=h[3];
if(t=h[i=1]-(a&1)&4||h[i=2]-(a&2)&8||h[i=4]-(a&4)&16||h[i=0]-(a&8)&32)a=h[i];
a&=-64;v=a|a>>26&16;t*=5;
if(v=v&v<<2&v<<4&v<<6&v<<8){t+=4;a=v&=~(v/2);}
else if(t)for(i=(h[i]&63)/(i?i:8),v=a;i-->5;)a&=a-1;
else if(v=o/2)t=3;
else if (e){o=e&e-1;v=(i=o&o-1)?o:e;t=1+(o>0);}
k=a^v;k&=k-1;k&=k-(i==0);}
c(v);v=C/8;c(k);
return t<<28|v<<13|C/8;}

The second is the input processor. It parses the project Euler file as 2+2+5 cards (ignoring the 10th card). It uses the Parse macro, P to create 32-bit values representing each card. The representation is 0A0K0Q0J0T090807060504030200shdc. A hand is stored as an array of 5 ints.

char*gets(char*);char*strchr(char*,char);
#define P(c)X=strchr(R,*c++)-R;C=1<<strchr(S,*c++)-S|64<<X*2;c++;
#define L(n)for(i=0;i<n;i++)
U g[5],h[5];
char*c,b[32];
char*S="CDHS";
char*R="23456789TJQKA";
int d,r[3]={0};
main(q){while(c=gets(b)){
L(2){P(c)A(g,C);}
L(2){P(c)A(h,C);}
L(5){P(c)A(g,C);A(h,C);}
d=E(g)-E(h);
r[d>0?0:d<0?1:2]++;
L(7)g[i]=h[i]=0;
}L(3)printf("%c:%d\n","12D"[i],r[i]);}

I'm sure there are a few more characters to be trimmed off. I'll add an explanation soon.

The evaluator runs @17.6 Million hands/second on my 3Ghz Core2 Duo. That's only 3.5x slower than the PokerSource evaluator, which uses at least 56K of lookup tables.

Laccolith answered 29/7, 2010 at 16:34 Comment(3)
Add a ; to the end of the A macro to save some chars.Cording
Excellent answer, and well done for comparission with another evaluator.Magulac
reduced to 694 bytes total hereLaccolith
A
3

PHP, 799 chars

Line breaks are not significant. This takes input from the linked url, which is different from the example input (doesn't deal with community cards). Processing is similar to mobrule's perl answer, with a different scoring method.

<?php
function s($i){$o=array_map('intval',$i);$f=(count(array_unique(str_replace($o,'',$i)))==1);
sort($o);$v=array_count_values($o);arsort($v);$u=array_keys($v);$h=max($u);$m=$u[0];$c=reset($v);
$p=count($v);$e=$c==1&&$o[4]==14&&$o[3]==5;$r=$o==range($o[0],$o[0]+4)||$e;$q=$e?5:$h;
$s=($f&&$r&&($h==12)?2<<11:($f&&$r?(2<<10)+$q:0))+($c==4?(2<<9)+$m:0)+($c==3&&$p==2?(2<<8)+$m:0)+($f?(2<<7)+$h:0)+
($r?(2<<6)+$q:0)+($c==3?(2<<5)+$m:0)+($c==2&&$p==3?(2<<4)+$m:0)+($p==4?(2<<3)+$m:0);$s+=!$s?$h:0;return array($s,$u);}

foreach(file($argv[1]) as $d){
list($y,$z)=array_chunk(explode(' ',trim(strtr($d,array('T'=>10,'J'=>11,'Q'=>12,'K'=>13,'A'=>14)))),5);
$y=s($y);$z=s($z);$w=$y[0]-$z[0];$x=1;while(!$w&&$x<5){$w=$y[1][$x]-$z[1][$x++];}if(!$w)@$t++;elseif($w<0)@$l++;else @$k++;}
@print "1: $k\n2: $l\nD: $t";
Alkyne answered 29/7, 2010 at 16:34 Comment(2)
Well I can tell from trying this code with many of random hands that it does not always give the correct result. Ie it favors a straight with A low over a straight with 2 low and sometimes it signals a false straight. But thanks anyway for the inspiration. :)Isologous
Good catches! I've edited my solution with fixes for incorrectly favoring the A low straight over a 2 low and the false straights that were being signaled when the hand has an A with the 4 low cards being some other combination of cards 5 or lower (i.e., 2355A was incorrectly being flagged a straight). The fixes for these has increased the character count by 6.Alkyne

© 2022 - 2024 — McMap. All rights reserved.