This post works with 5-card Poker hands drawn from a standard deck of 52 cards. The discussion is mostly mathematical, using the Poker hands to illustrate counting techniques and calculation of probabilities
Next in the poker hands list is a straight, consisting of a run of five cards of consecutive values, such as 4-5-6-7-8. Aces count as high or low, so you can make a 10-J-Q-K-A straight, the highest, or an A-2-3-4-5 straight, which is the lowest and sometimes called a “wheel”. The poker odds calculators on CardPlayer.com let you run any scenario that you see at the poker table, see your odds and outs, and cover the math of winning and losing poker hands. Texas Hold'em Omaha. Official poker rankings: ties and kickers. Poker is all about making the best five-card poker hand from the seven cards available (five community cards plus your own two hole cards). That means in the event of a tie with four of a kind, three of a kind, two pair, one pair, or high card, a side card, or 'kicker', comes into play to decide who wins the pot.
Working with poker hands is an excellent way to illustrate the counting techniques covered previously in this blog – multiplication principle, permutation and combination (also covered here). There are 2,598,960 many possible 5-card Poker hands. Thus the probability of obtaining any one specific hand is 1 in 2,598,960 (roughly 1 in 2.6 million). The probability of obtaining a given type of hands (e.g. three of a kind) is the number of possible hands for that type over 2,598,960. Thus this is primarily a counting exercise.
___________________________________________________________________________
Preliminary Calculation
Usually the order in which the cards are dealt is not important (except in the case of stud poker). Thus the following three examples point to the same poker hand. The only difference is the order in which the cards are dealt.
These are the same hand. Order is not important.
The number of possible 5-card poker hands would then be the same as the number of 5-element subsets of 52 objects. The following is the total number of 5-card poker hands drawn from a standard deck of 52 cards.
The notation is called the binomial coefficient and is pronounced “n choose r”, which is identical to the number of -element subsets of a set with objects. Other notations for are , and . Many calculators have a function for . Of course the calculation can also be done by definition by first calculating factorials.
Thus the probability of obtaining a specific hand (say, 2, 6, 10, K, A, all diamond) would be 1 in 2,598,960. If 5 cards are randomly drawn, what is the probability of getting a 5-card hand consisting of all diamond cards? It is
This is definitely a very rare event (less than 0.05% chance of happening). The numerator 1,287 is the number of hands consisting of all diamond cards, which is obtained by the following calculation.
The reasoning for the above calculation is that to draw a 5-card hand consisting of all diamond, we are drawing 5 cards from the 13 diamond cards and drawing zero cards from the other 39 cards. Since (there is only one way to draw nothing), is the number of hands with all diamonds.
If 5 cards are randomly drawn, what is the probability of getting a 5-card hand consisting of cards in one suit? The probability of getting all 5 cards in another suit (say heart) would also be 1287/2598960. So we have the following derivation.
Thus getting a hand with all cards in one suit is 4 times more likely than getting one with all diamond, but is still a rare event (with about a 0.2% chance of happening). Some of the higher ranked poker hands are in one suit but with additional strict requirements. They will be further discussed below.
Another example. What is the probability of obtaining a hand that has 3 diamonds and 2 hearts? The answer is 22308/2598960 = 0.008583433. The number of “3 diamond, 2 heart” hands is calculated as follows:
One theme that emerges is that the multiplication principle is behind the numerator of a poker hand probability. For example, we can think of the process to get a 5-card hand with 3 diamonds and 2 hearts in three steps. The first is to draw 3 cards from the 13 diamond cards, the second is to draw 2 cards from the 13 heart cards, and the third is to draw zero from the remaining 26 cards. The third step can be omitted since the number of ways of choosing zero is 1. In any case, the number of possible ways to carry out that 2-step (or 3-step) process is to multiply all the possibilities together.
___________________________________________________________________________
The Poker Hands
Here’s a ranking chart of the Poker hands.
The chart lists the rankings with an example for each ranking. The examples are a good reminder of the definitions. The highest ranking of them all is the royal flush, which consists of 5 consecutive cards in one suit with the highest card being Ace. There is only one such hand in each suit. Thus the chance for getting a royal flush is 4 in 2,598,960.
Royal flush is a specific example of a straight flush, which consists of 5 consecutive cards in one suit. There are 10 such hands in one suit. So there are 40 hands for straight flush in total. A flush is a hand with 5 cards in the same suit but not in consecutive order (or not in sequence). Thus the requirement for flush is considerably more relaxed than a straight flush. A straight is like a straight flush in that the 5 cards are in sequence but the 5 cards in a straight are not of the same suit. For a more in depth discussion on Poker hands, see the Wikipedia entry on Poker hands.
The counting for some of these hands is done in the next section. The definition of the hands can be inferred from the above chart. For the sake of completeness, the following table lists out the definition.
Definitions of Poker Hands
Poker Hand | Definition | |
---|---|---|
1 | Royal Flush | A, K, Q, J, 10, all in the same suit |
2 | Straight Flush | Five consecutive cards, |
all in the same suit | ||
3 | Four of a Kind | Four cards of the same rank, |
one card of another rank | ||
4 | Full House | Three of a kind with a pair |
5 | Flush | Five cards of the same suit, |
not in consecutive order | ||
6 | Straight | Five consecutive cards, |
not of the same suit | ||
7 | Three of a Kind | Three cards of the same rank, |
2 cards of two other ranks | ||
8 | Two Pair | Two cards of the same rank, |
two cards of another rank, | ||
one card of a third rank | ||
9 | One Pair | Three cards of the same rank, |
3 cards of three other ranks | ||
10 | High Card | If no one has any of the above hands, |
the player with the highest card wins |
___________________________________________________________________________
Poker Hands In Order Of Value
Counting Poker Hands
Straight Flush
Counting from A-K-Q-J-10, K-Q-J-10-9, Q-J-10-9-8, …, 6-5-4-3-2 to 5-4-3-2-A, there are 10 hands that are in sequence in a given suit. So there are 40 straight flush hands all together.
Four of a Kind
There is only one way to have a four of a kind for a given rank. The fifth card can be any one of the remaining 48 cards. Thus there are 48 possibilities of a four of a kind in one rank. Thus there are 13 x 48 = 624 many four of a kind in total.
Full House
Let’s fix two ranks, say 2 and 8. How many ways can we have three of 2 and two of 8? We are choosing 3 cards out of the four 2’s and choosing 2 cards out of the four 8’s. That would be = 4 x 6 = 24. But the two ranks can be other ranks too. How many ways can we pick two ranks out of 13? That would be 13 x 12 = 156. So the total number of possibilities for Full House is
Note that the multiplication principle is at work here. When we pick two ranks, the number of ways is 13 x 12 = 156. Why did we not use = 78?
Flush
There are = 1,287 possible hands with all cards in the same suit. Recall that there are only 10 straight flush on a given suit. Thus of all the 5-card hands with all cards in a given suit, there are 1,287-10 = 1,277 hands that are not straight flush. Thus the total number of flush hands is 4 x 1277 = 5,108.
Straight
There are 10 five-consecutive sequences in 13 cards (as shown in the explanation for straight flush in this section). In each such sequence, there are 4 choices for each card (one for each suit). Thus the number of 5-card hands with 5 cards in sequence is . Then we need to subtract the number of straight flushes (40) from this number. Thus the number of straight is 10240 – 10 = 10,200.
Three of a Kind
There are 13 ranks (from A, K, …, to 2). We choose one of them to have 3 cards in that rank and two other ranks to have one card in each of those ranks. The following derivation reflects all the choosing in this process.
Two Pair and One Pair
These two are left as exercises.
High Card
The count is the complement that makes up 2,598,960.
The following table gives the counts of all the poker hands. The probability is the fraction of the 2,598,960 hands that meet the requirement of the type of hands in question. Note that royal flush is not listed. This is because it is included in the count for straight flush. Royal flush is omitted so that he counts add up to 2,598,960.
Probabilities of Poker Hands
Poker Hand | Count | Probability | |
---|---|---|---|
2 | Straight Flush | 40 | 0.0000154 |
3 | Four of a Kind | 624 | 0.0002401 |
4 | Full House | 3,744 | 0.0014406 |
5 | Flush | 5,108 | 0.0019654 |
6 | Straight | 10,200 | 0.0039246 |
7 | Three of a Kind | 54,912 | 0.0211285 |
8 | Two Pair | 123,552 | 0.0475390 |
9 | One Pair | 1,098,240 | 0.4225690 |
10 | High Card | 1,302,540 | 0.5011774 |
Total | 2,598,960 | 1.0000000 |
___________________________________________________________________________
2017 – Dan Ma
Last Updated on January 1, 2018
I recently took a Hackerrank challenge for a job application that involved poker. I'm not a poker player, so I had a brief moment of panic as I read over the problem the description. In this article I want to do some reflection on how I approached the problem.
The hackerrank question asked me to write a program that would determine the best poker hand possible in five-card draw poker. We are given 10 cards, the first 5 are the current hand, and the second 5 are the next five cards in the deck. We assume that we can see the next five cards (they are not hidden). We want to exchange any n
number of cards (where n <= 5
) in our hand for the next n
cards in the deck. For example, we can take out any combination of 2 cards from the hand we are given, but we must replace these two cards with the next two cards from the deck (we can't pick any two cards from the deck).
Suit and value make up the value of playing cards. For example, you can have a 3 of clubs. 3 is the value, clubs is the suit. We can represent this as 3C
.
Suits
Clubs CSpades SHeart HDiamonds D
Value (Rank)
2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace
Hands
Here are the hands of poker
Royal flush (the problem didn't ask me to consider Royal Flush)
A, K, Q, J, 10, all the same suit.
Straight flush
Five cards in a sequence, all in the same suit. Ace can either come before 2 or come after King.
Four of a kind
All four cards of the same rank.
Full house
Three of a kind with a pair.
Flush
Any five cards of the same suit, but not in a sequence.
Straight
Five cards in a sequence, but not of the same suit.
Three of a kind
Three cards of the same rank.
Two pair
Two different pairs.
Pair
Two cards of the same rank.
High Card
When you haven't made any of the hands above, the highest card plays.In the example below, the jack plays as the highest card.
Evaluating a hand of cards
A hand is five cards. The first thing I did was write out functions to evaluate if a group of 5 cards satisfies the conditions of one of the ten hands.
Here's a sample hand:
To write functions, I reached for using 2 important python features: set
and defaultdict
.
Here's an example of a simple function to detect a flush, a hand with cards of all the same suit:
Checking a flush
This function creates a list of the suits in our hand, and then counts the unique elements in that list by making it a set. If the length of the set is 1, then all the cards in the hand must be of the same suit.
But wait, what if we have a straight flush? Also, a hand that satisfies a flush could also be described as a two pair hand. The problem asked me to find the highest possible hand for a given set of cards, so I tried to keep things simple by writing a check_hand()
function that checks each hand starting from straight flush down to high card. As soon as a condition for a hand was satisfied, I returned a number that corresponded to the strength of the hand (1 for high card up to 10 for straight flush). The problem didn't include Royal flush, so I will not include that here.
Poker Starting Hands Value
Here's the check_hand
function:
This function starts checking the most valuable hands. After it checks the second to lowest hand (pair), it returns a value of 1. This value of 1 corresponds to the 'highest card' hand. Since I'm not comparing the relative value of hands, it doesn't matter what the highest card is, so the number just represents the type of hand that is the strongest.
Other hands
Here are the all of the functions I used to detect hands:
defaultdict
is a great built-in that is good to use when you don't know what elements will be in your dictionary, but you know what the initial values of any key that could be added should be. We don't need it here, but the alternative would be to write a very long dictionary where keys are the possible card values and the values of each key is 0.
It would certainly be cleaner and more efficient to write out the above functions into one large function, but I wanted to keep things simple as I was under time constraints.
The next step in the problem is to determine the best possible hand we can get given the hand we are dealt and the 5 cards on top of the deck. I decided to first solve this problem with brute force. Here was my logic for this part: use itertools
to get all combinations of groups of 0, 1, 2, 3, 4 and 5 cards from my hand and add the first 5 - n
cards from the deck so we get a five card deck. For each combination of cards we can run check_hand()
and keep track of the highest rank hand, and then return that hand as the best hand. Here's the code I wrote for this part of the problem:
Lastly, I need to check each hand and print out the best hand possible. Here's the loop I wrote to do this:
This will accept one round of cards per line:
and it will output the following:
This was an interesting problem to deal with as the solution contained several parts that worked together. While solving the problem I aimed worked through to the end leaving some parts to come back to that I felt confident in solving. Instead of writing each function to check differnt hands at the beginning, I filled most of these functions with pass
and moved on to write the next part that involves checking each different combination of cards. Recently having worked through python's itertools
exercises on Hackerrank, the combinations
functions was fresh in my mind.
While I was able to arrive at a solution that satisfied the test cases, I did not have time to think about the efficiency or Big O analysis of the problem.
There is obviously some refactoring that I could do to make things cleaner. With more time I would take an object oriented approach by making classes for cards and hands, and adding class methods to evaluate the hands.
For each round, we have to run check_hand()
on each hand combination. Let's think about how many hands we have to evaluate:
We have to consider combinations of cards formed by taking out groups of 0, 1, 2, 3, 4 and 5 cards and adding the next number of cards in the deck that bring the total card count to 5, which means we have to do 5C0 + 5C1 + 5C2 + 5C3 + 5C4 + 5C5 calls to check_hand()
. So the sum of total calls is 1 + 5 + 10 + 10 + 5 + 1 = 32.
For each of these 32 calls that happen when we run play()
, check_hands()
runs through each of the check_
functions starting with the highest value hand. As soon as it finds a 'match', check_hands()
returns a number value (hand_value
) corresponding to straight flush, four of a kind, etc. This value is then compared with the highest value that has been previously found (best_hand
) and replaces that value if the current hand's hand rank has a higher value.
I'm not sure if there is faster way to find the best hand than the brute force method I implemented.