This is a fun evening exploration to teach myself how to code Python by asking the question "What does the distribution of games of Chutes & Ladders look like by number of spins to win?"
If you're new to Jupyter or Python you might find this interesting.
There's quite a long tail distribution - if you get very unlucky, the game might last well over 200 spins, but if you're super lucky you could get it in 7. :)
# We'll be lazy and code both chutes and ladders as "portals",
# first specifying the square FROM which the portal will go and
# then the square TO which the portal will take you. This allows
# both forward and backward movement. This set of coded portals
# maps the Chutes & Ladders game.
portals = {
1 : 38,
4 : 14,
9 : 31,
16 : 6,
21 : 42,
28 : 84,
36 : 44,
47 : 26,
49 : 11,
56 : 53,
51 : 67,
62 : 19,
64 : 60,
71 : 91,
80 : 100,
87 : 24,
93 : 73,
96 : 75,
98 : 78,
}
# Plays a game of Chutes & Ladders, returns # spins to win
# If printGame is true, will print details of the game.
import random
def playGame(printGame):
currentSquare = 0
spins = 0
while True:
spin = random.randint(1,6)
spins = spins + 1
if printGame: print "you spun a", spin
if currentSquare + spin > 100:
if printGame: print "oh no, you can't go past 100"
else:
currentSquare += spin
if printGame: print "after roll you landed on", currentSquare
portalDest = portals.get(currentSquare)
if portalDest is not None:
if printGame:
if portalDest < currentSquare: print "oh no, a chute to", portalDest
if portalDest > currentSquare: print "oh yay, a ladder to", portalDest
currentSquare = portalDest
if currentSquare == 100:
break
if printGame: print "you won in", spins, "spins!"
return spins
playGame(True)
you spun a 4 after roll you landed on 4 oh yay, a ladder to 14 you spun a 6 after roll you landed on 20 you spun a 5 after roll you landed on 25 you spun a 1 after roll you landed on 26 you spun a 2 after roll you landed on 28 oh yay, a ladder to 84 you spun a 6 after roll you landed on 90 you spun a 6 after roll you landed on 96 oh no, a chute to 75 you spun a 1 after roll you landed on 76 you spun a 3 after roll you landed on 79 you spun a 6 after roll you landed on 85 you spun a 4 after roll you landed on 89 you spun a 5 after roll you landed on 94 you spun a 3 after roll you landed on 97 you spun a 5 oh no, you can't go past 100 you spun a 1 after roll you landed on 98 oh no, a chute to 78 you spun a 1 after roll you landed on 79 you spun a 2 after roll you landed on 81 you spun a 2 after roll you landed on 83 you spun a 2 after roll you landed on 85 you spun a 5 after roll you landed on 90 you spun a 3 after roll you landed on 93 oh no, a chute to 73 you spun a 4 after roll you landed on 77 you spun a 1 after roll you landed on 78 you spun a 3 after roll you landed on 81 you spun a 4 after roll you landed on 85 you spun a 5 after roll you landed on 90 you spun a 5 after roll you landed on 95 you spun a 5 after roll you landed on 100 you won in 28 spins!
28
# Now we're going to play a whole bunch of games to get a distribution.
print "Playing games..."
gameOutcomes = [playGame(False) for game in range(100000)]
print "100,000 games completed."
Playing games... 100,000 games completed.
print "Fastest game is in", min(gameOutcomes), "spins."
print "Slowest game is in", max(gameOutcomes), "spins."
Fastest game is in 7 spins. Slowest game is in 317 spins.
%matplotlib inline
import numpy as np
import pandas as pd
from scipy import stats, integrate
import matplotlib.pyplot as plt
import seaborn as sns
print "Median game takes", int(np.median(gameOutcomes)), "spins."
print "95th %ile game takes", int(np.percentile(gameOutcomes, 95)), "spins."
sns.distplot(gameOutcomes, axlabel="spins to win", hist_kws={"histtype":"step", "alpha":1, "color":"g" })
Median game takes 33 spins. 95th %ile game takes 89 spins.
<matplotlib.axes.AxesSubplot at 0x1113e2390>