In [1]:
#%autosave 0
from IPython.core.display import HTML, display
display(HTML('<style>.container { width:100%; !important } </style>'))


Generating Random Permutations


In [2]:
import random as rnd

In [3]:
def permute(L):
    if len(L) == 1:
        return L
    k = rnd.randint(0, len(L)-1)
    return permute(L[:k] + L[k+1:]) + [L[k]]

In [4]:
for _ in range(20):
    print(permute([1,2,3,4,5]))


[2, 1, 4, 5, 3]
[3, 1, 5, 2, 4]
[4, 3, 5, 1, 2]
[3, 2, 4, 5, 1]
[1, 4, 2, 3, 5]
[5, 4, 1, 2, 3]
[5, 2, 1, 4, 3]
[4, 3, 1, 5, 2]
[5, 4, 3, 1, 2]
[5, 2, 4, 3, 1]
[4, 5, 3, 1, 2]
[3, 4, 2, 5, 1]
[1, 3, 5, 2, 4]
[3, 2, 1, 4, 5]
[2, 3, 4, 1, 5]
[5, 1, 4, 3, 2]
[5, 4, 2, 1, 3]
[1, 4, 5, 3, 2]
[1, 2, 5, 3, 4]
[2, 3, 1, 5, 4]

Case Study: Computation of Probabilities in Poker

This notebook shows how to compute probabilities in

Texas Hold'em Poker. Texas Hold'em is played with a deck of 52 cards. The cards have 13 different values and four different suits. The values are:


In [5]:
Values = { "2", "3", "4", "5", "6", "7", "8", "9", "T", 
           "J", "Q", "K", "A" 
         }

The four suits are clubs, hearts, diamonds, and spades. We represent these suits by their first letter:


In [6]:
Suits = { "c", "h", "d", "s" }

Now the deck of cards is convieniently represented by the Cartesian product of the two sets Values and Suits.


In [7]:
Deck = { (v, s) for v in Values for s in Suits }

Let's assume you have been dealt the three of clubs and the three of spades. In Texas Hold'em, the hand dealt to a player at the beginning is called the hole, so we have:


In [8]:
Hole = { ('3', 'c'), ('3', 's') }

The remaining cards are all other cards, lets call them rest:


In [9]:
Rest = Deck - Hole

In [10]:
50 * 49 * 48 * 47 * 46 / (1 * 2 * 3 * 4 * 5)


Out[10]:
2118760.0

We are interested in the probability that on the river you will improve your hand to four of a kind. As there are 5 cards that will be dealt, three cards in the flop, the turn, and the river, there are $$ (50 \cdot 49 \cdot 48 \cdot 47 \cdot 46) / (1 \cdot 2 \cdot 3 \cdot 4 \cdot 5) = 2\,118\,760 $$ possibilities for these cards. Let's pretend that we do not have enough main memory to store all these different possibilities. Instead, we want to run a Monte-Carlo Simulation.


In [11]:
def get_four_of_a_kind(n, Rest, v):
    no_four_of_a_kind = 0
    Rest = list(Rest)
    for _ in range(n):
        Rest  = permute(Rest)
        Cards = Hole | set(Rest[:5])
        if len({ card for card in Cards if card[0] == v }) == 4:
            no_four_of_a_kind += 1
    return no_four_of_a_kind / n

In [12]:
%%time
get_four_of_a_kind(1000000, Rest, '3')


CPU times: user 1min 28s, sys: 309 ms, total: 1min 28s
Wall time: 1min 29s
Out[12]:
0.00802