patternjavascriptMinor
isStraight evaluation function
Viewed 0 times
isstraightfunctionevaluation
Problem
The context is Weekend Challenge #2 (Poker hand evaluation).
My approach to detect straightness seems like the hard way. Can anyone suggest something else?
Okay, Poker is tough. I will revise this question once I have my new
Hand.prototype.isStraight = function()
{
for( var i = 1 ; i < this.cards.length ; i++ )
if( this.cards[i].value + 1 != this.cards[i-1].value )
return false;
return true;
}cards is an array with card objects { suit : "x" , value : "0->12" }. The cards are sorted during the creation of the hand.My approach to detect straightness seems like the hard way. Can anyone suggest something else?
Okay, Poker is tough. I will revise this question once I have my new
isStraight.Solution
It's not that hard.
Instead of sorting the cards, looping over them and skipping double results, let's convert them to a more useful format:
Now, if there's a card of value
Next, we scan the bitmap for 5 consecutive bits set, which is equivalent to 31 (
The lowest straight is 0, if there is no straight
The method works for games with more than 5 cards. Note that in any variant of Poker, 5 cards make a hand, so even in Omaha with 9 cards, 5 cards give you a straight.
Note: The method is roughly equivalent to creating a set (and checking for 5 consecutive elements). As you can see, with bit-wise operators it is much simpler to check for 5 consecutive cards.
Another note: There's a harder-to-understand but slightly faster method for testing a straight given the bitmap. I might add it later, but for now I think this method hard enough to understand for beginners.
Instead of sorting the cards, looping over them and skipping double results, let's convert them to a more useful format:
var bitmap = 0;
for(var i = 0; i < cards.length; i++)
{
var value = cards[i].value;
// set i+1 bit in the bitmap
bitmap |= 1 << (value + 1);
// if it's an ace, also set the low bit
if(value === 12)
bitmap |= 1;
}Now, if there's a card of value
i in your hand, the i+1 bit will be set in the bitmap. An Ace is treated as two cards with values 13 and 0.Next, we scan the bitmap for 5 consecutive bits set, which is equivalent to 31 (
1 | 2 | 4 | 8 | 16). We start with the highest straight, which is 9.The lowest straight is 0, if there is no straight
i is -1.for(var i = 10; i--; )
{
if((bitmap & 31 << i) === (31 << i))
{
break;
}
}The method works for games with more than 5 cards. Note that in any variant of Poker, 5 cards make a hand, so even in Omaha with 9 cards, 5 cards give you a straight.
Note: The method is roughly equivalent to creating a set (and checking for 5 consecutive elements). As you can see, with bit-wise operators it is much simpler to check for 5 consecutive cards.
Another note: There's a harder-to-understand but slightly faster method for testing a straight given the bitmap. I might add it later, but for now I think this method hard enough to understand for beginners.
Code Snippets
var bitmap = 0;
for(var i = 0; i < cards.length; i++)
{
var value = cards[i].value;
// set i+1 bit in the bitmap
bitmap |= 1 << (value + 1);
// if it's an ace, also set the low bit
if(value === 12)
bitmap |= 1;
}for(var i = 10; i--; )
{
if((bitmap & 31 << i) === (31 << i))
{
break;
}
}Context
StackExchange Code Review Q#37077, answer score: 8
Revisions (0)
No revisions yet.