# // <![CDATA[</p> <p>// ]]&gt;What happens when we toss a dice with more than 6 sides?// <![CDATA[ init_mathjax = function() { if (window.MathJax) { // MathJax loaded MathJax.Hub.Config({ tex2jax: { inlineMath: [ ['$','$'], ["\$","\$"] ], displayMath: [ ['$$','$$'], ["\$","\$"] ] }, displayAlign: 'left', // Change this to 'center' to center equations. "HTML-CSS": { styles: {'.MathJax_Display': {"margin": 0}} } }); MathJax.Hub.Queue(["Typeset",MathJax.Hub]); } } init_mathjax(); // ]]&gt;

In a previous post we looked at the question:

How many times, on average do you need to toss a dice with 6 sides until you get a 6?

Python has some cool randomness features so let’s look at those.

In [1]:
import random
In [2]:
random.choice?

random.choice is pretty cool. Here’s the documentation:

Choose a random element from a non-empty sequence.

We can give it a list of stuff and it’ll pick on out at random.

Here’s a dice with 6 sides:

This is easy to create with Python

In [3]:
sides = [1, 2, 3, 4, 5, 6]
In [4]:
random.choice(sides)
Out[4]:
4
In [5]:
random.choice(sides)
Out[5]:
1

Every time we call random.choice it randomly pulls a number from our list. Very cool! It’s like pulling a number from a hat.

Pulling random numbers happens quite a lot. In fact, it’s how the NBA drafts new playes fon the upcoming year.

Perhaps I’ll talk about the NBA draft at a later date, let’s continue with our dice example.

random.choice is cool because it allows us to construct any type of dice that want.

Here are some examples

In [6]:
six_sided = [1, 2, 3, 4, 5, 6]
ten_sided_norm = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
ten_sided_irregular = [1, 1, 1, 2, 2, 3, 3, 4, 5, 6]

Previously we had a function that threw the die until we got a certain number.

Let’s write it again, this time using random.choice

In [7]:
def toss_till_value(value, sides):
tosses = []
while 1:
outcome = random.choice(sides)
tosses.append(outcome)
if outcome == value:
break
return tosses

Now we can toss any die we want and get back the results!

We know a little bit about a die with 6 sides, so let’s try that first, tossing it until we get a 4.

In [9]:
toss_till_value(4, six_sided)
Out[9]:
[3, 3, 5, 4]

The result from our function is the hisory of tosses.

Toss it a few more times for fun!

In [11]:
toss_till_value(4, six_sided)
Out[11]:
[1, 6, 4]
In [12]:
toss_till_value(4, six_sided)
Out[12]:
[2, 6, 2, 4]
In [13]:
toss_till_value(4, six_sided)
Out[13]:
[1, 1, 5, 2, 5, 1, 6, 5, 1, 1, 3, 5, 5, 3, 4]
In [14]:
toss_till_value(4, six_sided)
Out[14]:
[6, 1, 6, 3, 2, 3, 5, 5, 5, 6, 2, 5, 6, 5, 1, 3, 3, 3, 5, 6, 2, 1, 4]

Wow! That last resulrt was really long!

Now, let’s use our 10 sided die, stopping when we get a 4.

In [16]:
toss_till_value(4, ten_sided_norm)
Out[16]:
[1, 2, 1, 10, 3, 7, 5, 4]
In [17]:
toss_till_value(4, ten_sided_norm)
Out[17]:
[8, 4]
In [18]:
toss_till_value(4, ten_sided_norm)
Out[18]:
[4]
In [19]:
toss_till_value(4, ten_sided_norm)
Out[19]:
[2, 5, 5, 10, 2, 1, 2, 5, 9, 9, 3, 3, 9, 3, 10, 1, 3, 8, 4]
In [22]:
toss_till_value(4, ten_sided_norm)
Out[22]:
[7, 3, 10, 5, 6, 6, 10, 2, 1, 9, 7, 8, 8, 7, 9, 9, 4]

The previous question was:
How many times, on average, do we have to throw a 6 sided die untill we get a 6?

Now we have a 10 sided dice, so let’s use that?

How many times, on average, do we have to throw a 10 sided die until we get a 6?

What are we going to do here? Can you write it down?

1. Toss the die until we get a 6.
2. Count the number of times we tossed it, and write it down.
3. Repeat step 1 and 2 100 times, untill we have 100 records of the number of throws it took to get a 6.

How do we record, or write down, our numbers? Python has a list! We .append items to our list, which is like writing them down.

In [24]:
number_of_tosses = []
for i in range(100):
result = toss_till_value(6, ten_sided_norm)
# Count how many times we threw the die, in python terms this is called the 'length'
number_of_tosses.append(len(result))

print number_of_tosses
[3, 8, 3, 8, 8, 11, 5, 1, 15, 1, 6, 6, 4, 1, 5, 15, 9, 6, 1, 16, 9, 2, 8, 1, 2, 1, 13, 2, 2, 2, 7, 43, 7, 3, 11, 9, 11, 4, 18, 6, 2, 6, 7, 34, 15, 5, 8, 3, 4, 14, 17, 10, 31, 3, 10, 2, 4, 2, 17, 9, 9, 12, 15, 14, 10, 30, 5, 1, 2, 4, 16, 7, 15, 13, 19, 28, 4, 2, 7, 39, 4, 10, 2, 4, 8, 6, 6, 5, 8, 7, 5, 5, 8, 1, 9, 4, 10, 56, 7, 9]

We can see the results. In snome cases it took 1 throw to get a 6, other times it took as many as 39, 43, and even 56 throws!

To get the average number of throws, we add up all our numbers, and divide by the number of “trails”, in this case it was 100.

In [25]:
sum(number_of_tosses) / 100.
Out[25]:
9.22

This means that it took 9.22 throws on average to get a 6.

What would happen if we did it with 500 throws instead of 100?

I’m going to copy and paste the code above and change 100 -> 500, then re-run our experiment.

In [28]:
number_of_tosses = []
for i in range(500):
result = toss_till_value(6, ten_sided_norm)
# Count how many times we threw the die, in python terms this is called the 'length'
number_of_tosses.append(len(result))

sum(number_of_tosses) / 500.
Out[28]:
9.836

Humm… 9.836. That’s similar to before, but this time a little closer to 10.

What would happen if we did it with 1000, 10000, or even 100000?

Here something nice about doing math with computers, we don’t have to copy and past and do a lot by hand, the computer can do the work for us. But we need to tell the computer how to run our expirement.

This is the same code we used before, I’m just replacing the specific numbers with a place holder.

• 500 -> trials
• 6 -> value
• ten_sided_norm -> dice_type This is special because now we can use any type of dice we want
In [32]:
def run_experiment(value, dice_type, trials):
number_of_tosses = []
for i in range(trials):
result = toss_till_value(value, dice_type)
# Count how many times we threw the die, in python terms this is called the 'length'
number_of_tosses.append(len(result))

return sum(number_of_tosses) / float(trials)
In [33]:
run_experiment(6, ten_sided_norm, 1000)
Out[33]:
10.072

It took, on average, about 10 throws to get a 6 when using a 10 sided die.

To be sure that the average is close to 10, let’s throw it 100000 times (one hundred thousand times!). What do you think will happen?

In [34]:
run_experiment(6, ten_sided_norm, 100000)
Out[34]:
10.02647

Yep, 10!

But I wonder if it changes if we use something other than 6? Let’s try all the numbers!

In [35]:
print ten_sided_norm
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [36]:
print " 1:", run_experiment(1, ten_sided_norm, 10000)
print " 2:", run_experiment(2, ten_sided_norm, 10000)
print " 3:", run_experiment(3, ten_sided_norm, 10000)
print " 4:", run_experiment(4, ten_sided_norm, 10000)
print " 5:", run_experiment(5, ten_sided_norm, 10000)
print " 6:", run_experiment(6, ten_sided_norm, 10000)
print " 7:", run_experiment(7, ten_sided_norm, 10000)
print " 8:", run_experiment(8, ten_sided_norm, 10000)
print " 9:", run_experiment(9, ten_sided_norm, 10000)
print "10:", run_experiment(10, ten_sided_norm, 10000)
 1: 10.1279
2: 9.9722
3: 9.9648
4: 9.7546
5: 9.9235
6: 10.142
7: 9.98
8: 10.0858
9: 10.0105
10: 10.0697

Wow, all the numbers are pretty close to 10.

I guess it doesn’t matter what face value we choose.

But, I wonder what happens if we start with a 6 sided dice, and increasing the side each time so that we get try a 7 , then an 8, then a 9…

In [37]:
print " 6 sides:", run_experiment(6, [1, 2, 3, 4, 5, 6], 10000)
print " 7 sides:", run_experiment(6, [1, 2, 3, 4, 5, 6, 7], 10000)
print " 8 sides:", run_experiment(6, [1, 2, 3, 4, 5, 6, 7, 8], 10000)
print " 9 sides:", run_experiment(6, [1, 2, 3, 4, 5, 6, 7, 8, 9], 10000)
print "10 sides:", run_experiment(6, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10000)
print "11 sides:", run_experiment(6, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 10000)
print "12 sides:", run_experiment(6, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 10000)
 6 sides: 6.0582
7 sides: 6.9162
8 sides: 8.0179
9 sides: 9.1095
10 sides: 9.9055
11 sides: 10.7736
12 sides: 12.1072

What’s going on here?

We have a 6 sided die and it takes 6 throws?

A 7 sided die and it takes 7 throws?

It seams that the number of sides on the dice, is the number of throws, on average it takes.

Let’s test out our idea. How about we try a 50 sided die!

Believe it or not, a 50 sided die actually exists!

In [40]:
fifty_sided_die = [1, 2, 3, 4, 5, 6, 7, 8, 9, \
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, \
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, \
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, \
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
In [42]:
print "50 sides:", run_experiment(6, fifty_sided_die, 10000)
50 sides: 49.8958

That’s pretty close to 50!

The number of sides on the dice is the number of times we have to roll the dice, on average, until we get a 6

A 100-sided die exists too!

Since the computer allowed us to try a 50-sided die without breaking a sweat, let’s do a 100 sided die!

(And you can get it on Amazon.)

Note: not only do I hate calculating, that’s why I want to use a computer, I hate typing stuff out. I don’t want to type out all those numbers.

hundred_sided_die = [1, 2, 3, 4, .... 100]


That’s a lot of typing!

Python has a trick for generating number and it’s:

range

In [41]:
fifty_sided_die == range(1, 51)
Out[41]:
True

We can make any number of sides with a simple range

range(1, sides + 1)

In [44]:
hundred_sided_die = range(1, 101)
In [45]:
print "100 sides:", run_experiment(6, hundred_sided_die, 10000)
100 sides: 100.0524

# Problem

## On average how many throws does it take to get a 6?

People are familiar with a dice that has 6 sides, with each face having 1-6 on each side.

This problem begs for a simulation. Python has a cool random funciton that let’s us simulate a dice throw.

We begin by creating a function that toss 6-sided die until we get a 6.

In [157]:
import random
In [158]:
def toss_till_6():
tosses = []
while True:
face = random.randint(1, 6)
tosses.append(face)
if face == 6:
break
return tosses

We can toss the die

In [164]:
toss_till_6()
Out[164]:
[4, 4, 1, 6]

Let’s toss it 10 times and see what happens

In [162]:
for i in range(10):
print toss_till_6()
[5, 6]
[3, 5, 3, 5, 5, 3, 4, 6]
[3, 2, 5, 2, 2, 2, 2, 4, 5, 3, 6]
[6]
[3, 4, 1, 6]
[2, 3, 2, 6]
[6]
[4, 3, 5, 6]
[5, 3, 2, 1, 5, 6]
[2, 2, 3, 3, 1, 1, 6]

That’s interesting, sometimes we get 6 on the first throw, sometimes it takes quite a while. Check out that big string of 2′s in the third trial.

So, on average, how many throws did it take to get a 6?

Let’s count them up.

• The 1st trial took 2 throws.
• The 2nd trial took 8 throws.
• The 3rd trial took 11 throws.
• The 4th trial took 1 throw.
• The 5th trial took 4 throws.
• The 6th trial took 4 throws.
• The 7th trial took 1 throws.
• The 8th trial took 4 throws.
• The 9th trial took 6 throws.
• The 10th trial took 7 throws.

That’s a lot of calculating. Python can handle the heavy lifting.

In [165]:
throw_counts = [2, 8, 11, 1, 4, 4, 1, 4, 6, 7]
sum(throw_counts)
Out[165]:
48

We threw the dice until we got a 6. And we did it 10 times. It too a total of 48 throws. How many is that on average?

In [168]:
sum(throw_counts) / 10. #Note, that period after the 10 is really important. If we don't use it we won't get a decimal.
Out[168]:
4.8

It took almost 5 throws before we got a 6.

Ah, but sometimes we got a 6 on the first throw, sometimes it took as many as 11 throws.

If we did our experiment one time and got 6 onthe first throw we’d be way off. We’d also be way off if we had the throw the dice 11 times beore getting a 6.

What would happen if we repeated this experiment more times?

How many more… 100, 1000, 10000?

Let’s begin with 100.

(Note: I’m only choosing 100 because it’s more than 10. We could also choose some other number like 82 if we wanted.)

In [169]:
trials = 100
results = []
for i in range(trials):
trial = toss_till_6()
results.append(trial)

results
Out[169]:
[[2, 3, 3, 3, 3, 3, 2, 5, 5, 1, 2, 4, 6],
[5, 4, 4, 4, 6],
[2, 6],
[6],
[3, 4, 4, 3, 3, 4, 4, 6],
[4, 5, 1, 4, 2, 5, 1, 1, 1, 4, 5, 4, 6],
[1, 2, 5, 5, 5, 6],
[6],
[5, 3, 1, 3, 5, 4, 1, 3, 6],
[5, 1, 3, 2, 3, 6],
[4, 1, 3, 2, 5, 3, 2, 6],
[1, 3, 3, 1, 6],
[4, 3, 3, 4, 5, 3, 3, 2, 5, 2, 1, 1, 4, 4, 6],
[1, 3, 1, 1, 6],
[4, 1, 4, 3, 4, 2, 4, 2, 3, 2, 6],
[5, 4, 4, 4, 3, 2, 5, 1, 6],
[1, 5, 5, 4, 5, 1, 4, 6],
[3, 6],
[2, 2, 2, 5, 3, 2, 3, 1, 1, 3, 4, 2, 1, 6],
[5, 2, 2, 1, 4, 3, 3, 3, 3, 1, 6],
[4, 1, 6],
[1, 4, 5, 5, 4, 2, 3, 2, 6],
[6],
[6],
[5, 3, 4, 2, 1, 6],
[1, 5, 5, 3, 5, 4, 5, 6],
[1, 3, 2, 1, 3, 4, 3, 5, 3, 6],
[5, 2, 1, 5, 5, 2, 3, 4, 5, 5, 3, 2, 2, 6],
[2, 2, 2, 3, 1, 5, 4, 1, 4, 6],
[6],
[6],
[6],
[6],
[1, 1, 3, 4, 5, 1, 3, 6],
[2, 3, 6],
[2, 2, 2, 6],
[4, 2, 5, 4, 2, 2, 4, 3, 3, 4, 5, 1, 6],
[1, 4, 4, 2, 4, 6],
[6],
[6],
[2, 3, 6],
[3, 4, 3, 2, 6],
[4, 6],
[3, 4, 4, 3, 4, 6],
[4, 6],
[2, 4, 2, 4, 5, 5, 1, 5, 2, 5, 6],
[3, 1, 3, 4, 6],
[3, 1, 4, 3, 6],
[3, 3, 5, 2, 2, 3, 1, 3, 6],
[2, 2, 3, 6],
[3,
1,
1,
2,
5,
4,
5,
1,
4,
2,
5,
1,
4,
5,
2,
4,
1,
1,
5,
4,
5,
2,
1,
3,
3,
5,
4,
2,
4,
6],
[3, 1, 4, 6],
[4, 6],
[4, 3, 2, 3, 2, 3, 2, 5, 5, 3, 1, 2, 2, 3, 6],
[6],
[4, 5, 4, 4, 6],
[2, 4, 2, 2, 6],
[4, 6],
[5, 4, 1, 3, 1, 6],
[6],
[5, 2, 2, 1, 3, 1, 3, 1, 2, 4, 3, 1, 1, 6],
[2, 2, 1, 5, 3, 5, 5, 6],
[3,
4,
3,
2,
3,
4,
1,
2,
3,
4,
1,
3,
2,
4,
2,
2,
3,
2,
1,
4,
4,
4,
2,
4,
2,
6],
[5, 2, 2, 4, 3, 3, 3, 4, 3, 6],
[4, 1, 6],
[4, 2, 1, 4, 1, 1, 3, 4, 5, 3, 6],
[6],
[2, 6],
[4, 1, 5, 5, 5, 5, 1, 2, 1, 5, 4, 6],
[1, 3, 6],
[1, 5, 2, 5, 1, 3, 5, 2, 3, 2, 6],
[6],
[2, 1, 1, 1, 4, 5, 5, 3, 3, 6],
[2, 4, 6],
[6],
[4, 5, 4, 4, 5, 1, 5, 6],
[1, 2, 6],
[6],
[3, 3, 6],
[5, 4, 4, 3, 3, 5, 1, 3, 4, 1, 4, 3, 5, 1, 5, 6],
[5, 6],
[1, 2, 6],
[5, 4, 2, 6],
[2, 2, 5, 5, 5, 6],
[5, 3, 1, 6],
[3, 4, 6],
[6],
[1, 4, 2, 4, 1, 4, 2, 1, 4, 6],
[4, 4, 1, 6],
[4, 6],
[5, 6],
[5, 1, 1, 6],
[4, 2, 1, 2, 6],
[3, 5, 2, 5, 5, 1, 2, 2, 2, 2, 5, 5, 4, 3, 1, 3, 1, 6],
[1, 3, 4, 3, 5, 4, 1, 2, 2, 5, 4, 2, 3, 5, 4, 6],
[5, 1, 4, 6],
[5, 6],
[1, 6],
[4, 5, 1, 4, 6],
[1, 1, 3, 4, 5, 5, 3, 5, 1, 4, 6]]

Now we have a bunch of results. Python can count them for us.

In [174]:
counted_throws = []
for trial in results:
throws = len(trial)
counted_throws.append(throws)

counted_throws
Out[174]:
[13,
5,
2,
1,
8,
13,
6,
1,
9,
6,
8,
5,
15,
5,
11,
9,
8,
2,
14,
11,
3,
9,
1,
1,
6,
8,
10,
14,
10,
1,
1,
1,
1,
8,
3,
4,
13,
6,
1,
1,
3,
5,
2,
6,
2,
11,
5,
5,
9,
4,
30,
4,
2,
15,
1,
5,
5,
2,
6,
1,
14,
8,
26,
10,
3,
11,
1,
2,
12,
3,
11,
1,
10,
3,
1,
8,
3,
1,
3,
16,
2,
3,
4,
6,
4,
3,
1,
10,
4,
2,
2,
4,
5,
18,
16,
4,
2,
2,
5,
11]

We can see that on the first trial we had to throw the dice 13 times before getting a 6

In [175]:
len(results[0])
Out[175]:
13

How many times in total did we throw the dice?

In [176]:
sum(counted_throws)
Out[176]:
632

We threw it 632 times! Wow, that’s a lot.

But how many times on average? We’ll we had 100 trials? How much is that?

In [178]:
sum(counted_throws) / float(trials) # See that 'float' just ignore it for the time being.
Out[178]:
6.32

Humm… so, its taken us about 6.3 throws on average to get a 6.

Let’s see what happens if we throw more than 100 times.

But, before we do our experiment, let’s writes some code to simplify our testing.

In [179]:
# This code is similar to the code above, but I changed some variable names to make it easier to read.
def average_throws_till_6(trials):
throws = []
for i in range(trials):
trial = toss_till_6()
throws.append(trial)

counted_throws = []
for throw in throws:
counted_throws.append(len(throw))

average = sum(counted_throws) / float(trials)
return average
In [180]:
trials = 1000
average_throws_till_6(trials)
Out[180]:
5.906

Wow. 5.906 throws on average.

When we did it with 10 trials we got 4.8 throws on average….

100 throws was 6.3 throws on average.

1000 throws got 5.906 throws on average.

But why stop at 1000 throws… let’s go higher! Let’s push the limits. It’s not like our arm will fall off from throwing the dice.

In [181]:
trials = 10000 # That's ten thousand throws!
average_throws_till_6(trials)
Out[181]:
5.9077

Throws on average with 10,000 throws is 5.9077.

It looks like we’re getting pretty close to 6.

What will happen if we do it 50,000 times? What about 100,000 times?

In [182]:
trials = 50000
average_throws_till_6(trials)
Out[182]:
6.02692
In [183]:
trials = 100000
average_throws_till_6(trials)
Out[183]:
5.98154

It looks like as we go a lot higher the number doesn’t change much.

How many tosses, on average, does it take to get a 6?

I guess it takes about 6 throws on average until we reach the number 6

It seems that we’ve answered our question, the answer is 6. Right?

But what if we change the question.

How many throws, on average does it take to get a 3?

Note: I just decided on 3, it could have been a different number. But, maybe we should test other numbers too?

Our original code was written to only test for a 6, so let’s change to to test for any number.

In [184]:
# our original one was called "toss_til_6" we've renamed the 6 to "value"
# Now we can test numbers other than 6, like 3.

def toss_till_value(value):
tosses = []
while True:
face = random.randint(1, 6)
tosses.append(face)
if face == value:
break
return tosses

How about we try out our new code by running an experiment with 3.

In [185]:
toss_till_value(3)
Out[185]:
[5, 4, 2, 1, 4, 3]

We had to toss the dice 6 times until we got a 3.

What happens if we toss it a bunch of times like before?

Let’s create some code to do the calculations.

In [187]:
# This code is similar to the code above, but made a couple changes...
# "toss_till_6" is now "toss_till_value"
# we have to supply a value
def average_throws_till_value(trials, value):
throws = []
for i in range(trials):
trial = toss_till_value(value)
throws.append(trial)

counted_throws = []
for throw in throws:
counted_throws.append(len(throw))

average = sum(counted_throws) / float(trials)
return average
In [188]:
average_throws_till_value(10, 3)
Out[188]:
7.1

Humm, when we do 10 throws it takes 7.1 throws on average until we get a 3.

What happens if we do it more and more!

In [189]:
average_throws_till_value(1000, 3)
Out[189]:
5.916
In [190]:
average_throws_till_value(10000, 3)
Out[190]:
5.9771
In [191]:
average_throws_till_value(10000, 3)
Out[191]:
6.0047
In [192]:
average_throws_till_value(1000000, 3)
Out[192]:
5.996575

These numbers are pretty close to 6, especially when we do a high number of throws.

We’ve done 3 and 6, both take about 6 throws on average. What about the remaining faces…

1. ???
2. ???
4. ???
5. ???

Testing 1, 2, 4, 5

In [194]:
print "1:", average_throws_till_value(10000, 1)
print "2:", average_throws_till_value(10000, 2)
print "3:", average_throws_till_value(10000, 3)
print "4:", average_throws_till_value(10000, 4)
print "5:", average_throws_till_value(10000, 5)
print "6:", average_throws_till_value(10000, 6)
1: 5.9834
2: 6.0456
3: 6.0248
4: 5.9496
5: 5.9938
6: 5.9935

I guess it doesn’t matter what face value we choose. It takes 6 throws on average to get any face!

# What if…

• We tried a dice with 6 sides, but what if we used one with 10 sides? 15 sides? 20 sides? 20-sided dice exist!
• What if we had a die that had 6 sides but instead of 1,2,3,4,5,6 they were 1,2,3,3,3,4? (See, it doesn’t even go to 6!)
• Or a 10 sided die that went to 6 but had sides like 1,1,1,2,2,3,4,5,6,6 ?