Is it possible to extract that info from the equivalence value?
I understand that the higher the equivalence value the better. Category and rank can also be extracted from the equivalence value. But is there a way to find out what the best 5 cards combination are from the 7 that you passed to it?
Twoplustwo is the fastest poker hand evaluator around (14-15 million hands evaluated per second). You give your 7 cards to it and it spits out a hand equivalence value. The higher the value, the better is card is.
Here's a great summary on twoplustwo: http://www.codingthewheel.com/archives/poker-hand-evaluator-roundup#2p2
Cached version of the link above:
http://web.archive.org/web/20130116102452/http://www.codingthewheel.com/archives/poker-hand-evaluator-roundup
(disclaimer: I'm working on a poker software that does, amongst other, hand evaluations)
You give your 7 cards to it and it spits out a hand equivalence value.
there are several evaluators doing that and if I'm not mistaken some of them compute more than a hundred million hands per second (!). These evaluators basically come down to 7 array lookups in a gigantic array and it only takes a few cycles (despite the cache misses) to evaluate a hand. I don't think 14-15 millions / second is anywhere near the fastest. CactusKev's evaluator is 10x faster if I'm not mistaken.
Now to answer your question:
how do you get the best 5 cards combination out of the 7 that you
passed to it?
Well it doesn't tell you but once you have the strength of the hand it can become very easy: you don't need to re-invent the wheel.
You can use the strength to simplify your "best five out of seven" computation.
You could also use other libraries, giving your directly the five best card (instead of just their strength) or you can use the strength to find the five best cards yourself.
I'll just give a few examples...
You know you have a full house (a.k.a. a "boat"), then you know that you're looking for three cards that have the same rank and then the best pair (if there are two pairs, but you're sure to find at least one, because the evaluator told you you have a boat).
You know you have a straight: find five cards that follow each other, starting from the best one (beware of the special wheel case case).
You could also get a bit fancier for the straight: you could take the strength of every possible straight and compare the strength that the evaluator gives you with these. If it matches, say, a ten-high straight, then simply look for any T, 9, 8, 7 and 6 card (no matter the suit).
You know you have "no pair": simply take the five highest card you find
etc.
There are only a few different ranks... They could be, for example:
NO_PAIR
ONE_PAIR
TWO_PAIRS
SET
STRAIGHT
FLUSH
FULL_HOUSE
FOUR_OF_A_KIND
STRAIGHT_FLUSH
(you could of course create intermediate "wheel straight" and "wheel straight flush" and "royal flush" cases if you want, etc.)
Once you know the which type of hand your hand is (thanks to the fast evaluator you're using), simply switch to a piece of code that finds the five best out of seven for that particular hand.
I think it's a good way to proceed because you leverage the ultra-fast evaluator and it then greatly simplifies your logic.
At startup, you'd need to compute the strenth once, for example by computing:
HIGHEST_NO_PAIR_HAND = ultraFastEvaluator( "As Kd Qh Jc 9d 5s 2c" );
HIGHEST_FULL_HOUSE = ultraFastEvaluator( "As Ac Ad Kh Ks 8s 2h" );
I'm of course not advocating to use strings here. It's just an example...
You could then, for each hand you want to find the actual five best:
- compute the strength using the fast evaluator
- is it <= HIGHEST_NO_PAIR_HAND ?
- yes: take five highest cards
- no: is it <= HIGHEST_ONE_PAIR_HAND ?
yes: take highest pair + highest three cards
no: is it <= HIGHEST_TWO_PAIRS_HAND?
So in my opinion you could reuse an API that directly finds the five best out of seven or entirely rewrite your own, but it's going to faster if you use the fast evaluator's result to then simplify your logic.
EDIT note that there's not necessarily one way to do "five best out of seven". For example with As Ac on a Kc Kd Qh Qs 2c board, both "As Ac Kc Kd Qh" and "As Ac Kc Kd Qs" are "five best" (the last queen's suit doesn't matter).
No, it's not possible to extract that information. The lookup table contains only the equivalence values, which are broken into hand type and rank; no other information is preserved.
If you need to evaluate millions of hands per second and get the winning hand for each, instead of just the rank, you'll need to use a different evaluator. If you only need to extract the winning hand rarely, you could use this evaluator, and resort to a slower method to find the best 5 cards when necessary.
Old post but I'll give it a shot. If you're using a table lookup (e.g., the 7-card arrays mentioned above, aka the Ray Wotton method), construct a second table with your target information in the same slot positions. Example: I ended up in slot 167,452 to find my eval, now I'll look at my other array in slot 167,452 to find my 5-card hand.
A single card can be represented by 6 bits - 2 for the suit and 4 for the rank. 30 bits would give you the entire 5-card hand. Maybe not quite that simple, but that's the general idea. I've used this exact technique for some stuff I did awhile back.
Alternatively, you could pass in all the 7-choose-5-card combinations (21 of 'em I believe) and find out which matches the original eval.
The twoplustwo hand evaluator can evaluate five cards hands. Here's the code for that in C#:
int LookupFiveCardHand(int[] cards) {
//assert cards size is 5
int p = HR[53 + cards[i++]];
p = HR[p + cards[i++]];
p = HR[p + cards[i++]];
p = HR[p + cards[i++]];
p = HR[p + cards[i++]];
return HR[p];
}
Notice there's 6 array look-ups despite there being 5 cards.
Anyways, since the evaluator is so fast, you can just compare every possible 5 card combination. A hand containing 7 card hands will have twenty-one 5 card combinations. Code in C#:
List<int> GetBestFiveCards(List<int> sevenCardHand) {
List<List<int>> fiveCardHandCombos = new List<List<int>>();
// adds all combinations of five cards to fiveCardHandCombos
for (int i = 0; i < sevenCardHand.Count; i++) {
for (int j = i+1; j < sevenCardHand.Count; j++) {
List<int> fiveCardCombo = new List<int>(sevenCardHand);
fiveCardHandCombos.RemoveAt(j); // j > i, so remove j first
fiveCardHandCombos.RemoveAt(i);
fiveCardHandCombos.Add(fiveCardCombo);
}
}
Dictionary<List<int>, int> comboToValue = new Dictionary<List<int>, int>();
for (int i = 0; i < fiveCardHandCombos.Count; i++) {
comboToValue.Add(fiveCardHandCombos[i], LookupFiveCardHand(fiveCardHandCombos[i]));
}
int maxValue = comboToValue.Values.Max();
return comboToValue.Where(x => x.Value == maxValue).Select(x => x.Key).First(); //grab only the first combo in the event there is a tie
}