Python Forum
Dice Roll (Find out how many rolls until specified streak)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Dice Roll (Find out how many rolls until specified streak)
#1
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?

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.
Reply
#2
You could learn generators for this task. For example
>>> 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
>>> 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!
Reply
#3
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
SNAKE_EYES = (1, 1)
Make a function to roll dice
def roll_dice(num_of_dice):
    ....
    return # returns the rolled dice, possible result (1, 1) if called as roll_dice(2)
Make a function that counts how many rolls to find a match that can be called like this roll_till_match(SNAKE_EYES)
def roll_till_match(match):
   num_of_dice = len(match)
    ....
   # uses roll_dice(num_of_dice) in a loop checking if the result is the same as match
    return # count of rolls till the match
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)
def roll_till_match_x_times(match, x_times):
   ...
   # uses roll_till_match(match) in a loop of x_times
   return # total sum of rolls
The same functions can be used against other matches.
Reply
#4
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

import random

def snake_eyes(count):
    streak_cnt = 0  # Step 1
    overall_cnt = 0 # Step 1
    while streak_cnt < count: # Step 5
        roll = (random.randint(1, 6), random.randint(1, 6)) # Step 2
        if roll == (1, 1): # Step 3
            streak_cnt += 1  # Step 3
        else: # Step 3
            streak_cnt = 0 # Step 3
        overall_cnt += 1 # Step 4
    return overall_cnt # Step 5

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.
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.
Reply
#5
Here is a shorter version of the infinite sequences method
>>> 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
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Help with dice roll program kraco 4 2,043 Sep-22-2020, 02:06 PM
Last Post: kraco
  simple dice roll Byzas 1 2,318 Mar-21-2019, 02:29 AM
Last Post: ichabod801
Photo roll of the dice kyle007 0 1,695 Mar-11-2019, 01:58 AM
Last Post: kyle007
  unit test roll die saladgg 5 4,121 Nov-06-2018, 11:39 PM
Last Post: stullis
  Issue with my 'roll the dice simulation'-exercise (cannot break out of the loop) Placebo 2 3,465 Sep-30-2018, 01:19 PM
Last Post: Placebo
  Making a percentile dice roller and dice roller Fixer243 2 3,199 Sep-30-2018, 12:18 PM
Last Post: gruntfutuk
  Random Dice roll program th3h0bb5 1 5,512 Oct-18-2016, 09:25 PM
Last Post: ichabod801

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020