Search code examples
phparraysalgorithmsortingpoker

Check for poker straight


I have managed to create an algorithm to check the rank of a poker hand. It works 100% correctly, but it's very slow. I've been analysing the code, and the check straight function is one of the slowest parts of it.

So my question is, is there a better way of calculating whether a hand make a straight?

Here is some details:

7 cards, 2 from holder, 5 from board. A can be high or low.

Each card is assigned a value: 2 = 2 3 = 3 .. 9 = 9 T = 10 J = 11 Q = 12 K = 13 A = 14

The script has an array of all 7 cards:

$cards = array(12,5,6,7,4,11,3);

So now I need to be able to sort this into an array where it:

  • discards duplicates
  • orders the card from lowest to highest
  • only returns 5 consecutive cards I.e. (3,4,5,6,7)

It needs to be fast; loops and iterations are very costly. This is what I currently use and when it tries to analyse say 15000 hands, it takes its toll on the script.

For the above, I used:

  • discard duplicates (use array_unique)
  • order cards from lowest to highest (use sort())
  • only return 5 consecutive cards (use a for loop to check the values of cards)

Does anyone have any examples of how I could improve on this? Maybe even in another language that I could perhaps look at and see how it's done?


Solution

  • Instead of working with array deduping and sorting, consider using a bitmask instead, and setting bits to 1 where the card value is set. A bitmask works like a Set datastructure and comes with additional advantages when it comes to detecting contiguous elements.

    for ($i = 0; $i < count($cards); $i++) {
        $card = $cards[$i];
        // For each card value, set the bit
        if ($card == 14) {
            // If card is an ace, also set bit 1 for wheel
            $cardBitmask |= 0x2;
        }
        $cardBitmask |= (1 << $card);
    }
    
    // To compare, you simply write a for loop checking for 5 consecutive bits
    for($i = 10; $i > 0; $i--)
    {
        if ($cardBitmask & (0x1F << $i) == (0x1F << $i)) {
            // Straight $i high was found!
        }
    }