Posts: 13
Threads: 8
Joined: Oct 2019
I am trying to figure out how many rolls of dice it would take to get a specified number of snake eye rolls. For instance if I want to get snake eyes 5 times in a row and roll until I get it, how many rolls would it take when it's random?
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import random
streaks = 0
a = random.randint( 1 , 6 )
b = random.randint( 1 , 6 )
rollnum = 1
while a + b ! = 2 :
a = random.randint( 1 , 6 )
b = random.randint( 1 , 6 )
rollnum + = 1
if a + b = = 2 :
streaks + = 1
print ( f "number of rolls: {rollnum}" )
|
So far my code is very basic as I'm a beginner, but what I'd like to do is have a variable that the user can specify (x) and then the dice will roll again and again until it hits snake eyes x times in a row. Then it tells you how many times it had to roll before it hit snake eyes x times in a row.
Posts: 4,801
Threads: 77
Joined: Jan 2018
Jun-12-2021, 01:25 PM
(This post was last modified: Jun-12-2021, 01:25 PM by Gribouillis.)
You could learn generators for this task. For example
1 2 3 4 5 6 7 8 |
>>> from random import randint
>>> from itertools import islice
>>> def rolls():
... while True :
... yield 1 if (randint( 1 , 6 ) + randint( 1 , 6 ) = = 2 ) else 0
...
>>> list (islice(rolls(), 100 ))
[ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]
|
In this code, rolls() is an infinite sequence of 0s and 1s obtained by rolling two dice and looking for a snake eyes. Here 1 means a success an 0 a failure.
Next you could use a function that transforms such a sequence by summing consecutive 1s, for example
Output: 0 0 1 1 1 0 0 1 0 1 1 0 0 0 1 1 1 1 0 0 1 becomes
0 0 1 2 3 0 0 1 0 1 2 0 0 0 1 2 3 4 0 0 1
Here is how you can write such an infinite sequence
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
>>> def sum_consec(seq):
... s = 0
... for x in seq:
... if x: s + = 1
... else : s = 0
... yield s
...
>>> list (sum_consec([ 0 , 0 , 1 , 1 , 1 , 0 , 0 , 1 , 0 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 1 ]))
[ 0 , 0 , 1 , 2 , 3 , 0 , 0 , 1 , 0 , 1 , 2 , 0 , 0 , 0 , 1 , 2 , 3 , 4 , 0 , 0 , 1 ]
>>>
>>> target = 4
>>> for i, v in enumerate (sum_consec(rolls())):
... if v = = target:
... print (i)
... break
...
4698374
>>>
|
We rolled 4,698,375 times the dice before getting 4 snake eyes in a row!
Posts: 2,168
Threads: 35
Joined: Sep 2016
Jun-12-2021, 01:46 PM
(This post was last modified: Jun-12-2021, 01:46 PM by Yoriz.)
You could break it down into functions.
I've given an outline below for you to fill in the gaps.
create a constant variable for the rolled dice pattern you would like to match
Make a function to roll dice
1 2 3 |
def roll_dice(num_of_dice):
....
return
|
Make a function that counts how many rolls to find a match that can be called like this roll_till_match(SNAKE_EYES)
1 2 3 4 5 |
def roll_till_match(match):
num_of_dice = len (match)
....
return
|
Another function that can call roll_till_match x amount of times that can be called like this roll_till_match_x_times(SNAKE_EYES, 5)
1 2 3 4 |
def roll_till_match_x_times(match, x_times):
...
return
|
The same functions can be used against other matches.
Posts: 6,809
Threads: 20
Joined: Feb 2020
I like to start out by first solving the problem the same way I would solve it if I were doing so without a computer.
1. Set count and snake eye count = 0
2. Roll the dice
3. If roll is snake eyes, increment snake eye count by 1, else set count to zero
4. Increment count by 1
5. Repeat 2 through 4 until snake eye count = 5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import random
def snake_eyes(count):
streak_cnt = 0
overall_cnt = 0
while streak_cnt < count:
roll = (random.randint( 1 , 6 ), random.randint( 1 , 6 ))
if roll = = ( 1 , 1 ):
streak_cnt + = 1
else :
streak_cnt = 0
overall_cnt + = 1
return overall_cnt
print (snake_eyes( 5 ))
|
Output: 6984725
When you roll 2 dice there are 36 possible outcomes and only 1 of those is snake eyes. Your probability of rolling snake eyes is 1/36 and your probability of rolling snake eyes 5 times in a row is (1/36)^5. On average you will need to roll the dice 60, 466, 176 times to roll 5 snake eyes in a row. My second time running the program it printed 12297433 and the third time 57268606.
These numbers are all suspiciously low, so I modified the code to calculate how long it takes to roll snake eyes and see if that agrees with my estimate of 1/36.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import random
import statistics
def snake_eyes(count):
streak_cnt = 0
overall_cnt = 0
while streak_cnt < count:
roll = (random.randint( 1 , 6 ), random.randint( 1 , 6 ))
if roll = = ( 1 , 1 ):
streak_cnt + = 1
else :
streak_cnt = 0
overall_cnt + = 1
return overall_cnt
print (statistics.mean([snake_eyes( 1 ) for _ in range ( 100000 )]))
|
Running this code I consistently get numbers very close to 36. I repeated with fewer iterations for rolling snake-eyes twice in a row (1296 times expected, 1292 times measured) for three times in a row (46,656 times expected, 47,955 times measured). Finally I ran the test for 5 consecutive snake-eyes. The average of 100 tests was 56, 0711,113 times with a high of 102,260,693 and a low of 4,217,949.
Posts: 4,801
Threads: 77
Joined: Jan 2018
Jun-13-2021, 09:44 AM
(This post was last modified: Jun-13-2021, 09:44 AM by Gribouillis.)
Here is a shorter version of the infinite sequences method
1 2 3 4 5 6 7 |
>>> from random import randint
>>> import itertools as itt
>>> rolls = (randint( 1 , 6 ) + randint( 1 , 6 ) = = 2 for _ in itt.repeat( None ))
>>> sum_consec = (s : = x and s + 1 for x in rolls)
>>> target = 4
>>> next (itt.dropwhile(( lambda t: t[ 1 ] < target), enumerate (sum_consec, 1 )))[ 0 ]
2378988
|
|