[Jprogramming] Faster array lookup? (poker hand evaluator)

Ryan Eckbo eckbo at cim.mcgill.ca
Mon Jan 4 02:05:08 UTC 2016


Henry's idea made the computation 10 times faster:

   	hands=. |: 53,.~ >:(1e7#7)?52
   6!:2 'handvalues=. (HR {~ +)/ hands'
3.08429

HANDTYPE=: <;._2 [0 : 0
BAD
High Card
One Pair
Two Pair
Trips
Straight
Flush
Full House
Quads
Straight Flush
)
HANDTYPE {~ _12 (33 b.)  10  {. handvalues  NB. right shift 12 bits to 
get hand type id
┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬─────────┬─────┬────────┐
│Two Pair│One Pair│One Pair│Two Pair│One Pair│One Pair│One 
Pair│High Card│Flush│One Pair│
└────────┴────────┴────────┴────────┴────────┴────────┴────────┴─────────┴─────┴────────┘
By the way you can also use this method to evaluate 5 or 6 card hands:
hr7=: (HR {~ +)/@:(,&53)
hr5or6=: HR {~ hr7

I think this should be fast enough for my purposes, if not I'll either 
write a C api
as Raul suggested or test other evaluator implementations (like 
http://suffe.cool/poker/evaluator.html,
which is actually used to construct the HR lookup table, and is fast for 
5 card evaluations -- although
I can't imagine it being faster than a lookup table).

Here's an interesting fact: there are 2.5 millions 5 card hand 
combinations but only 7462 distinct hand values.
The hand values returned by HR aren't in this range but they do 
guarantee that if HR[hand1_idx] > HR[hand2_idx]
then hand1 beats hand2.

Thanks for the help!
Ryan


On 3 Jan 2016, at 14:56, Ryan Eckbo wrote:

> I've implemented the twoplustwo 7 card poker hand evaluator[1] in J 
> but it's
> slower than I expected.  The evaluator works by accepting an array of 
> 7
> integers between 1 and 52, representing a 7 card hand, and uses them 
> as indices
> in a lookup table, which returns the best 5 card hand's rank value.  
> Here's the
> C code that does this (HR is the lookup table):
>
> int LookupHand(int* pCards)
> {
> int p = HR[53 + *pCards++];
> p = HR[p + *pCards++];
> p = HR[p + *pCards++];
> p = HR[p + *pCards++];
> p = HR[p + *pCards++];
> p = HR[p + *pCards++];
> 	return HR[p + *pCards++];
> }
>
> My J version is:
>
> hr=: (HR {~ +)/@:(,&53)	 NB. hr 1 5 9 12 20 25 42
>
> This is one of the fastest evaluators out there, for example a 
> javascript version
> can run at 20 million evaluations per second.  My J version takes 30 
> seconds
> to evaluate just 10 million hands:
>
> hands=. 53,.~ >: ? 1e7 7 $ 52  NB. 10 million hands, with initial 
> index 53 added
> 6!:2 '(HR {~ +)/"1 hands'  NB. 32.14 sec on a 2.8GHz Mac
>
> I wonder why it's slow and if there's a way to make it faster?
>
>
> [1] 
> https://github.com/christophschmalhofer/poker/blob/master/XPokerEval/XPokerEval.TwoPlusTwo.Test/test.cpp
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm


More information about the Programming mailing list