Estimate Probabilities of Card Games
By: George Pipis
Tags: Card Game, Probability, Python, Monte Carlo, AI

Estimate Probabilities of Card Games

A practical example of how you can calculate Card Probabilities with Monte Carlo Simulation and Numerically

Photo by Amanda Jones on Unsplash

We are going to show how we can estimate card probabilities by applying Monte Carlo Simulation and how we can solve them numerically in Python. The first thing that we need to do is to create a deck of 52 cards.

How to Generate a Deck of Cards

import itertools, random # make a deck of cards

deck = list(itertools.product(['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'],['Spade','Heart','Diamond','Club'])) deck

And we get:

[('A', 'Spade'),

('A', 'Heart'),

('A', 'Diamond'),

('A', 'Club'),

('2', 'Spade'),

('2', 'Heart'),

('2', 'Diamond'),

('2', 'Club'),

('3', 'Spade'),

('3', 'Heart'),

('3', 'Diamond'),

('3', 'Club'),

('4', 'Spade'),

('4', 'Heart'),

('4', 'Diamond'),

('4', 'Club'),

('5', 'Spade'),

('5', 'Heart'),

...

How to Shuffle the Deck

# shuffle the cards

random.shuffle(deck)

deck[0:10]

And we get:

[('6', 'Club'),

('8', 'Spade'),

('J', 'Heart'),

('10', 'Heart'),

('Q', 'Spade'),

('7', 'Diamond'),

('K', 'Diamond'),

('J', 'Club'),

('J', 'Diamond'),

('A', 'Club')]

How to Sort the Deck

For some probabilities where the order does not matter, a good trick is to sort the cards. The following commands can be helpful.

# sort the deck

sorted(deck) # sort by face

sorted(deck, key = lambda x: x[0]) # sort by suit

sorted(deck, key = lambda x: x[1])

How to Remove Cards from the Deck

Depending on the Games and the problem that we need to solve, sometimes there is a need to remove from the Deck the cards which have already been served. The commands that we can use are the following:

# assume that card is a tuple like ('J', 'Diamond')

deck.remove(card) # or we can use the pop command where we remove by the index

deck.pop(0) # or for the last card

deck.pop()

Part 1: Estimate Card Probabilities with Monte Carlo Simulation

Question 1: What is the probability that when two cards are drawn from a deck of cards without a replacement that both of them will be Ace?

Let’s say that we were not familiar with formulas or that the problem was more complicated. We could find an approximate probability with a Monte Carlo Simulation (10M Simulations)

N = 10000000

double_aces = 0 for hands in range(N):

# shuffle the cards

random.shuffle(deck)

aces = [d[0] for d in deck[0:2]].count('A')

if aces == 2:

double_aces+=1 prob = double_aces/N

prob

And we get 0.0045214 where the actual probability is 0.0045

Question 2: What is the probability of two Aces in 5 card hand without replacement.

FYI: In case you want to solve it explicitly by applying mathematical formulas:

from scipy.stats import hypergeom # k is the number of required aces

# M is the total number of the cards in a deck

# n how many aces are in the deck

# N how many aces cards we will get hypergeom.pmf(k=2,M=52, n=4, N=5)

And we get 0.03992981808107859 . Let’s try to solve it by applying simulation:

N = 10000000

double_aces = 0 for hands in range(N):

# shuffle the cards

random.shuffle(deck)

aces = [d[0] for d in deck[0:5]].count('A')

if aces == 2:

# print(deck[0:2])

double_aces+=1 prob = double_aces/N

prob

And we get 0.0398805. Again, quite close to the actual probability

Question 3: What is the probability of being dealt a flush (5 cards of all the same suit) from the first 5 cards in a deck?

If you would like to see the mathematical solution of this question you can visit PredictiveHacks. Let’s solve it again by applying a Monte Carlo Simulation.

N = 10000000 flushes = 0 for hands in range(N):

# shuffle the cards

random.shuffle(deck)

flush = [d[1] for d in deck[0:5]]

if len(set(flush))== 1:

flushes+=1

prob = flushes/N

prob

And we get 0.0019823 which is quite close to the actual probability which is 0.00198.

Question 4: What is the probability of being dealt a royal flush from the first 5 cards in a deck?

The actual probability of this case is around 0.00000154. Let’s see if the Monte Carlo works with such small numbers.

# royal flush N = 10000000

royal_flushes = 0

for hands in range(N):

# shuffle the cards

random.shuffle(deck)

flush = [d[1] for d in deck[0:5]]

face = [d[0] for d in deck[0:5]]

if len(set(flush))== 1 and sorted(['A','J', 'Q', 'K', '10'])==sorted(face):

royal_flushes+=1 prob = royal_flushes/N

prob