A while ago, I decided to take a shot at writing a poker hand evaluator in the programming language "C". There are already numerous evaluators out there, but I had an idea for an algorithm that might be faster than anything already out there. The basic concept is to write a routine that would take a five card poker hand and return it's overall "value". This is extremely valuable in any poker-related software, since the code will constantly be comparing various player's hand with each other to determine the "winner". Here is my concept on how I thought I could write a fast evaluator.

*
However, one day, I got an email from an actual poker software
company from Canada called
Poker Academy. They also wanted to know if I had written
a seven-card evaluator, and if so, could they test it to see if it
was faster than their current code? We converted my code from 'C'
to Java, and they gave it a whirl. Turns out it was about three times
faster than what they were currently using, so they asked if I'd
be willing to sell/license it to their company for use in the next
version of their software. We worked out a contract and the deal
was inked. If you visit their site, download version 2.5, and select
Version History, you can see my name in the notes for the February 15,
2006 2.5.0 Release (b164). The downside of all this, is that I cannot
pass on my seven-card evaluator algorithm to any curious poker math-geeks
who stumble upon my site. So don't email me asking for the code or
algorithm, because I can't give it to you. Sorry, mate.
*

First off, any person who has studied combinatorics will know that there are

Here's another way to look at it.
Suppose you were able to round up 2,598,960
of your friends on a football field, and you gave each of them one
of the unique 2,598,960 poker hands to hold. You then yell in a loud voice,
asking everyone to compare their hand with everybody else's
hand. (This will take some time, of

- 3: four people holding Queen-High Straight Flushes
- 4: four people holding Jack-High Straight Flushes
- 5: four people holding Ten-High Straight Flushes
- 6: four people holding Nine-High Straight Flushes
- 7: four people holding Eight-High Straight Flushes
- 8: four people holding Seven-High Straight Flushes
- 9: four people holding Six-High Straight Flushes
- 10: four people holding Five-High Straight Flushes

- 11: four people holding Four Aces with a King kicker
- 12: four people holding Four Aces with a Queen kicker
- ...
- 165: four people holding Four Deuces with a Four kicker
- 166: four people holding Four Deuces with a Trey kicker

- 167: twenty-four people holding Full Houses of Aces over Kings
- 168: twenty-four people holding Full Houses of Aces over Queens
- ...
- 321: twenty-four people holding Full Houses of Deuces over Fours
- 322: twenty-four people holding Full Houses of Deuces over Treys

For query #323, four people will step foward, each holding
a `AKQJ9` Flush. Then, four people holding `AKQJ8`
Flushes, and so forth.

- 323: four people holding AKQJ9 Flushes
- 324: four people holding AKQJ8 Flushes
- ...
- 1598: four people holding 76432 Flushes
- 1599: four people holding 75432 Flushes

- 1600: 1,020 people holding Ace High Straights
- 1601: 1,020 people holding King High Straights
- ...
- 1608: 1,020 people holding Six High Straights
- 1609: 1,020 people holding Five High Straights

- 1610: sixty-four people holding AAAKQ
- 1611: sixty-four people holding AAAKJ
- ...
- 2466: sixty-four people holding 22253
- 2467: sixty-four people holding 22243

- 2468: 144 people holding AAKKQ
- 2469: 144 people holding AAKKJ
- ...
- 3324: 144 people holding 33225
- 3325: 144 people holding 33224

- 3326: 384 people holding AAKQJ
- 3327: 384 people holding AAKQT
- ...
- 6184: 384 people holding 22643
- 6185: 384 people holding 22543

- 6186: 1,020 people holding AKQJ9
- 6187: 1,020 people holding AKQJ8
- ...
- 7461: 1,020 people holding 76432
- 7462: 1,020 people holding 75432

Straight Flush | 40 | 10 |

Four of a Kind | 624 | 156 |

Full Houses | 3744 | 156 |

Flush | 5108 | 1277 |

Straight | 10200 | 10 |

Three of a Kind | 54912 | 858 |

Two Pair | 123552 | 858 |

One Pair | 1098240 | 2860 |

High Card | 1302540 | 1277 |

TOTAL |
2598960 |
7462 |

Once I determined that there were only 7462 distinct values of
poker hands, I needed a way to quickly transform each of the
2,598,960 unique five-card poker hands into its actual value.
To complicate matters, the algorithm needed to be order independant.
In other words, if I pass the cards
**Kd Qs Jc Th 9s***still* return
the value of 1601. Mixing up the five cards does not change the
overall value of the hand. At first, I thought that I could always
simply sort the hand first before passing it to the evaluator; but
sorting takes time, and I didn't want to waste any CPU cycles sorting
hands. I needed a method that didn't care what order the five cards
were given as.

After a lot of thought, I had a brainstorm to use prime numbers. I would assign a prime number value to each of the thirteen card ranks, in this manner:

Rank | Deuce | Trey | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King | Ace |

Prime | 2 | 3 | 5 | 7 | 11 | 13 | 17 | 19 | 23 | 29 | 31 | 37 | 41 |

The beauty of this system is that if you * multiply* the prime
values of the rank of each card in your hand, you get a unique
product, regardless of the order of the five cards. In my above
example, the King High Straight hand will

One last step is required, however, before multiplying our prime
rank values. We must first check to see if all five cards are of
the same suit. It is extremely important that our evaluator
realize that the value of a `KQJT9` hand is *much*
higher if all the suits are the same.

Okay. At this point, I was ready to start writing some code.
I decided to use the following bit scheme for a single card,
where each card is of type ` integer` (and therefore,
four bytes long).

**
+--------+--------+--------+--------+
|xxxbbbbb|bbbbbbbb|cdhsrrrr|xxpppppp|
+--------+--------+--------+--------+
p = prime number of rank (deuce=2,trey=3,four=5,...,ace=41)
r = rank of card (deuce=0,trey=1,four=2,five=3,...,ace=12)
cdhs = suit of card (bit turned on based on suit of card)
b = bit turned on depending on rank of card
**

Using such a scheme, here are some bit pattern examples:

xxxAKQJT 98765432 CDHSrrrr xxPPPPPP 00001000 00000000 01001011 00100101 King of Diamonds 00000000 00001000 00010011 00000111 Five of Spades 00000010 00000000 10001001 00011101 Jack of Clubs

Now, for my evaluator function, I would pass in five integers,
each representing one of the five cards in the hand to evaluate.
We will label these ` c1` through

c1 AND c2 AND c3 AND c4 AND c5 AND 0xF000

First, I do another bitwise OR of all five cards, and then bit shift that value 16 bits to the right:

q = (c1 OR c2 OR c3 OR c4 OR c5) >> 16

If we should determine that we do not have *Flush* or *
Straight Flush* hand, we move on to tackle *Straight* and
*High Card* hands. Again, we use a lookup table for speed.
We create another array, which will we will call
` unique5[]`. We use the
same index

With just two easy calculations and two quick lookups, we have eliminated 2574 out of the 7462 possible distinct hand values. That's a little over a third of all the hands. Now it's time to use our trick with prime numbers. We take each card, extract its prime number value, and then multiply them all together:

q = (c1 AND 0xFF) * (c2 AND 0xFF) * ... * (c5 AND 0xFF)

That's it! I coded this algorithm, and ran it against some of the other poker evaluators out there, and it beat them all. Now all you need to do is get over to an online casino to give it a try! I'm pretty proud of it, and kudos to you if you've actually read this far. For your prize, you get to download the actual source code to experiment with.

LATE BREAKING NEWS!!!Paul Senzee of Florida decided that he could speed up my evaluator by using a pre-computed perfect hash function instead of a binary search for those final 4888 hand values. He says he obtained a speedup factor of 2.7x! Not too shabby! Anyway, you can read about his optimization and download his new evaluator code here.