Reputation:
I was doing practice problems from 'Automate the Boring Stuff with Python' and I came across this question. Write a program to find out how often a streak of six heads or a streak of six tails comes up in a randomly generated list of heads and tails.
1.the first part generates a list of randomly selected 'heads' and 'tails' values 2.the second part checks if there is a streak in it.
Put all of this code in a loop that repeats the experiment 10,000 times so we can find out what percentage of the coin flips contains a streak of six heads or tails in a row.
Here what i have done till now :
import random
myList = []
n = int(input('How many times do you want to toss the coin : '))
i = 0
while i <= n :
outcome = random.randint(0,1)
if outcome == 0 :
toss = 'H'
myList.append(toss)
elif outcome == 1 :
toss = 'T'
myList.append(toss)
i += 1
headStreak = 0
total_H_Streak = 0
for i in myList :
if i == 'H' :
headStreak += 1
if headStreak == 6 :
total_H_Streak += 1
else :
headStreak = 0
print('The streak of 6 heads in a row is : ',total_H_Streak)
tailStreak = 0
total_T_Streak = 0
for j in myList :
if j == 'T' :
tailStreak += 1
if tailStreak == 6 :
total_T_Streak += 1
else :
tailStreak = 0
print('The Streak of 6 tails in a row is : ',total_T_Streak)
Although I think this code is correct, I was wondering if there is any other approach to this problem. Any suggestion is appreciated.
Upvotes: 1
Views: 4791
Reputation: 1
Solution using one loop:
#Heads and Tails
import random
numberOfStreaks = 0
coinFlips = []
for __ in range(10000): # number of experiments
# Code that creates a list of 100 'heads' or 'tails' values.
coinFlips = random.choices('HT', k=100)
# Code that checks if there is a streak of 6 heads or tails in a row.
numberOfStreaks += ('T'*6 in ''.join(coinFlips)) or ('H'*6 in ''.join(coinFlips))
print('Chance of a streak = :%s%%' %(numberOfStreaks /100))
Upvotes: 0
Reputation: 1
import random
heads = 0
tails = 0
streak = 0
lister = []
for x in range(10001):
for x in range(101):
x = random.randint(0,1)
if x == 0:
heads = heads + 1
lister.append('H')
print(lister)
if x == 1:
tails = tails + 1
lister.append('T')
print(lister)
for l in range(len(lister)):
if tails == 6 or heads == 6:
streak += 1
break
print('Probability: %s%% streak' %(streak/100))
Upvotes: 0
Reputation: 11
import random
numberOfStreaks = 0
result = []
for i in range(100):
if random.randint(0,1) == 0:
value = 'H'
else:
value = 'T'
result.append(value)
streaks = 1
for i in range(len(result)):
try:
if result[i] == result[i+1]:
streaks += 1
else:
streaks = 1
if streaks == 6:
numberOfStreaks +=1
streaks = 0
except IndexError:
print('done')
print(result)
print(numberOfStreaks)
Upvotes: 1
Reputation: 1
def factorial(number):
if number > 1:
return number * factorial(number - 1)
else:
return 1
'''
Using combinations:
https://en.wikipedia.org/wiki/Combination
'''
def combinations(k, n):
return factorial(n) / (factorial(k) * factorial(n-k))
'''
Using Bernulli's formula
'''
def Bernulli_scheme(k, n):
return combinations(k, n) * (0.5 ** k) * (0.5 ** (n-k))
print(Bernulli_scheme(6,100))
Upvotes: 0
Reputation: 11
New to both programming and StackOverflow, so please bear with me if my formatting isn't correct, but I figured this one out. I think that the question is correctly interpreted as case #1 on this guy's Quora post wherein any set of 100 flips which contains at least 6 consecutive heads or tails is considered a streak:
Therefore, the probability should be around 0.8. The following code gives this probability:
import random
numberOfStreaks = 0
for experimentNumber in range(10000):
#Code that creates a list of 100 'heads' or 'tails' values.
list=[]
for flip in range(100):
value=random.randint(0,1)
if value == 0:
value = 'heads'
else:
value = 'tails'
list.append(value)
#Code that checks if there is a streak of 6 heads or tails in a row.
streak=1 # No matter which value we start on, we can consider it to be the first of a potential streak of 6
for i in range(len(list)):
if i==0:
pass
elif list[i]==list[i-1]:
streak+=1 # Reset back to the first of a potential streak of 6 if it doesn't work out
else:
streak=1
if streak>=6: # Include streaks of more than 6 consecutive identical results
numberOfStreaks+=1
break
print('Chance of streak: %s%%' % (numberOfStreaks / 100))
Upvotes: 1
Reputation: 149
I see a lot of people using for loops to calculate the streak of six in their lists. Whilst the question asks you to create a list of outcomes, you can actually just then convert the list to a string and then use the .count() method to identify the number of occurrences:
import random
#Produce list of 100 flips
outcomes = []
for ii in range(100):
rand = random.randint(0,1)
if rand == 0:
outcomes.append('T')
else:
outcomes.append('H')
#Count number of streaks
outcomes_string = ''.join(outcomes)
tail_streak = outcomes_string.count('T'*6)
head_streak = outcomes_string.count('H'*6)
streaks = tail_streak + head_streak
print(streaks)
#Calculate percentage
#add your code here
The previous question in the book actually asks you to write a piece of code that can print any list into a specified string format as well.
Obviously you modify the code accordingly so it runs the experiment 10000 times.
Upvotes: 1
Reputation: 23
The premise of the question was working on lists. Below is my solution. Keep in mind, the odds of it happening at any one point in time are:
(1/2)(1/2)(1/2)(1/2)(1/2)*(1/2) or (1/2)^6, so your sample set answer should be around 1.56%
NOTE: the try / except block was just to handle the issue of the index + x running out of actual index numbers towards the end of the list.
import random
streak = 0
number_of_100_flips = 10000
for num in range(number_of_100_flips):
coin_flip = []
#flip 100 times
for val in range(101):
toss = random.randint(0,1)
if toss == 0:
coin_flip.append('H')
else:
coin_flip.append('T')
for i in range(len(coin_flip)+1):
counter = 0
try:
for x in range(1,7):
if coin_flip[i] == coin_flip[i+x]:
counter += 1
if counter == 6:
streak += 1
counter = 0
except:
pass
print('A streak of 6 in a row during 100 flips occured {:.2%} of the time.'.format(streak/(100*number_of_100_flips), number_of_100_flips))
print(f'The experiment was done {number_of_100_flips} times')
Upvotes: 1
Reputation: 1
I tried to keep it simple( from what I know of, I'm learning). I noted everything to break it down easier.
import random
numberOfStreaks = 0
H = 0 # Tracks number of times H in a row.
T = 0 # Tracks number of times T in a row.
for experimentNumber in range(10000):
r= (random.randint(0, 1))
if r == 0:
print('H')
H = H + 1 # Adds to number of H in a row
T = 0 # resets T to 0 when H is produced
if H == 6: # Checks for streak
numberOfStreaks= numberOfStreaks + 1
H = 0 # sets H back to 0 after streak acheived
elif r == 1:
print('T')
T = T + 1
H = 0
if T == 6:
numberOfStreaks = numberOfStreaks + 1
T = 0
# code that checks if there is a streak of 6 heads or tails in a row.
print(' Chance of streak: %s%%' % (numberOfStreaks / 100))
Upvotes: 0
Reputation: 11
While I was solving practice problems from the book Automate the boring stuff with Python, I came across this problem. Write a program to find out how often a streak of six heads or a streak of six tails comes up in a randomly generated list of heads and tails.
The approach that I took, comprised of breaking down the problem into two sub-parts, the first part generates a list of randomly selected 'heads' and 'tails' values, and the second part checks if there is a streak in it. Put all of this code in a loop that repeats the experiment 10,000 times so we can find out what percentage of the coin flips contains a streak of six heads or tails in a row.
Here is what I have done till now:
import random
numberOfStreaks = 0
for experimentNumber in range(10000):
# Code that creates a list of 100 'heads' or 'tails' values.
experimentOutcomes =[]
for i in range(100):
if random.randint(0,1) == 0:
experimentOutcomes.append('H')
else:
experimentOutcomes.append('T')
#print(experimentOutcomes)
# Code that checks if there is a streak of 6 heads or tails in a row.
for i in range(len(experimentOutcomes)):
count = 0
for j in range(6):
try: # at item 95, Python will report error Index out of range which can be ignored.
if experimentOutcomes[i] == experimentOutcomes[i+j]:
count += 1
else:
break
except IndexError:
break
if count == 6:
numberOfStreaks += 1
print('The percentage of the coin flips that contain a streak of six heads or tails in a row: ' + str((numberOfStreaks / (10000*95))*100) +'%')
How did I calculate the percentage? For an experiment of tossing a coin 100 times in a row, there are 95 such possible streaks of 6. For 10000 times the experiment was repeated, multiply 10000 with 95. So these are the total possible outcomes of a streak of length 6. So, we divide the actual outcomes with the number of possible outcomes to find the probability.
Upvotes: 1
Reputation: 21
I actually used only one "for loop" counting and updating all the things needed within every loop and assuming that 0 is head and 1 is tail. Here it is how:
import random
# Head = 0 - Tail = 1
# Vars
head_count = 0
tail_count = 0
head_streaks = 0
tail_streaks = 0
# If head or tail, add 1 to the side counter. If it gets to 6, add 1 to the streake counter and reset the side counter
for i in range(10000):
rand = random.randint(0,1)
if rand == 0:
head_count +=1
if head_count == 6:
head_streaks +=1
# Every time a side happens, the opposite side count is set to 0
tail_count = 0
else:
tail_count +=1
if tail_count == 6:
tail_streaks +=1
head_count = 0
print("Head odds: ", str(head_streaks/10000), "%")
print("tail odds: ", str(tail_streaks/10000), "%")
Upvotes: 1
Reputation: 93
#first part: generates a list of random H/T.
import random
streak = 0
repeat = 0
while repeat < 10000:
flips = []
#Generates a random list of H or T with 100 items.
for i in range(100):
if random.randint(0, 1) == 0:
flips.append('H')
else:
flips.append('T')
#print(flips, end='\n\n')
# Find a streak of 6 of either H or T.
for i in range(len(flips)):
count = 0
for x in range(6):
try: # at item 95, Python will report error Index out of range which can be ignored.
if flips[i] == flips[i + x]:
count += 1
else:
break
except IndexError:
break
if count == 6:
streak += 1
#print("Found a streak!")
repeat += 1
print("Repeats: " + str(repeat))
print("Streaks: " + str(streak))
print("flips: " + str(repeat * 100))
print("The odds are " + str((streak / (10000 * 100 / 100))) + '%')
Upvotes: 1
Reputation: 51037
An exact answer to the problem can be computed using dynamic programming; reframe the problem from calculating the probability, into counting the number of sequences of length n
which don't contain any streak of k
in a row. The probability of getting no streaks of length k
or more is that number divided by 2**n
; of course, if you want the probability of getting at least one streak, you can subtract that result from 1. This gives an exact probability (subject to floating point precision), rather than an estimate by sampling.
The algorithm works by maintaining a "state" which is a list of the current number of sequences ending with a streak of length r
, where r
is the index in the list, ranging from 0 to k - 1
where k
is the forbidden streak length. To update the state, each current streak can either be broken by a "different" flip, resulting in a new streak of length 1, or it can be continued by a "same" flip, resulting in a new streak of length r + 1
. We should only count "continued" streaks if the resulting streak length is less than k
. The initial state has a single streak of length 0, because no flips have been made yet.
Here's an implementation:
def probability_of_no_runs(n, k):
state = [1] + [0] * (k-1)
for i in range(n):
new_state = [0] * k
for r, c in enumerate(state):
new_state[1] += c
if r < k - 1:
new_state[r + 1] += c
state = new_state
return sum(state) / 2**n
Example:
>>> probability_of_no_runs(10, 3)
0.173828125
>>> probability_of_no_runs(100, 6)
0.19317945128367534
>>> probability_of_no_runs(100, 10)
0.9133409556516383
By viewing the state transition as a linear transformation, it's possible to improve on this algorithm by writing the whole thing as a matrix product A**n * s
where A
is the transition matrix and s
is the initial state. This could be more efficient because the matrix power can be computed in log n
steps instead of n
steps as this loop uses.
The algorithm above could also be adapted to count the distribution of how many streaks occur; in that case, the state should be a two-dimensional grid where one index is the current streak length and the other index is the number of streaks so far. You would need to decide what to do about overlapping streaks.
Upvotes: 1