'Automate the boring stuff - Chapter 4: Coin Flip Solution
I am struggling with the solution of the 'Coin Flip' practice project at the end of chapter 4 in 'Automate the boring stuff' for python programming.
I have two solutions, both yielding a totally different result (first one is clearly false). I am not sure, what is the right solution to the answer.
Solution 1:
import random
nextFlip = []
numberOfStreaks = 0
# Code that creates a list of 10000 'heads' or 'tails' values.
for expNum in range(10000):
select = random.randint(0,1)
if select == 0:
nextFlip.append('H')
elif select == 1:
nextFlip.append('T')
# Code that checks if there is a streak of 6 heads or tails in a row.
for i in range(0,(len(nextFlip)-6)):
if nextFlip[i] == nextFlip[i+1] == nextFlip[i+2] == nextFlip[i+3] == nextFlip[i+4] == nextFlip[i+5] != nextFlip[i+6]:
numberOfStreaks +=1
print('Chance of streak: %s%%' % ((numberOfStreaks / 10000)*100))
Solution 2:
import random
nextFlip = []
hlist = 0
tlist = 0
numberOfStreaks = 0
# Code that creates a list of 10000 'heads' or 'tails' values.
for expNum in range(10000):
select = random.randint(0,1)
if select == 0:
nextFlip.append('H')
elif select == 1:
nextFlip.append('T')
# Code that checks if there is a streak of 6 heads or tails in a row.
for i in range(0,(len(nextFlip)-6)):
if nextFlip[i] == 'H':
hlist += 1
if hlist == 6:
numberOfStreaks +=1
elif nextFlip[i] == 'T':
tlist += 1
if tlist == 6:
numberOfStreaks +=1
print('Chance of streak: %s%%' % ((numberOfStreaks / 10000)*100))
Maybe someone can help me and tell me what I did wrong.
Solution 1:[1]
I'm just learning with the same book too. I found this easier to treat as a string, rather than a list. I believe that the problem is asking you to find whether a streak of 6 or more consecutive heads or a streak of 6 or more consecutive tails occurs in 100 tosses of a coin. For each 100 tosses, the result is 0 or 1 (I don't think you count multiple streaks). The 10,000 runs is to gain a reasonable accuracy and avoid sampling error.
import random
number_of_streaks = 0
for experiment_number in range(10000):
# Code that creates a list of 100 'heads' or 'tails' values
coin_list = ''
for i in range(100):
if random.randint(0, 1) == 0:
coin_list = coin_list + 'H' # heads
else:
coin_list = coin_list + 'T' # tails
# Code that checks if there is a streak of 6 heads or tails in a row
if 'HHHHHH' in coin_list or 'TTTTTT' in coin_list:
number_of_streaks +=1
print('Chance of streak: %s%%' % (number_of_streaks / 100))
Further to advice in comments from @rchome, I added a simple timer to this original code (https://stackoverflow.com/a/1557584/17555691) and it gave the following response:
Chance of streak: 80.06% --- 0.8480644226074219 seconds ---
Next, I made a small change, using append to a list and then converting to a string:
# Code that creates a list of 100 'heads' or 'tails' values
coin_list = []
for i in range(100):
if random.randint(0, 1) == 0:
coin_list.append('H') # heads
else:
coin_list.append('T') # tails
# Code that checks if there is a streak of 6 heads or tails in a row
coin_string = ''.join(coin_list)
if 'HHHHHH' in coin_string or 'TTTTTT' in coin_string:
number_of_streaks +=1
Output from this version:
Chance of streak: 80.26% --- 0.739051342010498 seconds ---
Then made a change, using recommendation from @Alain T:
# Code that creates a list of 100 'heads' or 'tails' values
flips = "".join(random.choice('HT') for _ in range(100))
# Code that checks if there is a streak of 6 heads or tails in a row
if 'HHHHHH' in flips or 'TTTTTT' in flips:
number_of_streaks +=1
Output from this version: Chance of streak: 80.74% --- 0.4248924255371094 seconds ---
The above results were quite typical on repeated executions.
Solution 2:[2]
This seems to work:-
import random
N = 10_000
S = 6
HEAD = 'H'
TAIL = 'T'
T = [HEAD if random.randint(0, 1) else TAIL for _ in range(N)]
c = T[0]
s = 1
STREAKS = 0
for t in T[1:]:
if t == c:
s += 1
if s == S:
STREAKS += 1
s = 0
else:
c = t
s = 1
print(STREAKS)
Solution 3:[3]
You could generate the random flips using a comprehension and store it in a string to make processing of the streaks easier. Since streaks can overlap, you need to examine subranges starting at every position:
flips = "".join(random.choice("HT") for _ in range(1000))
streaks = sum(flips[i:i+6] in ('HHHHHH','TTTTTT') for i in range(1000))
The sum() function will convert boolean values to 1 or zero (True is 1), so adding up the result of the streak conditions produces the total.
Solution 4:[4]
#Defining Inputs and importing modules
import random
numberOfStreaks = 0
mylist=[]
countH=0
countT=0
conuterTail=[]
conuterHead=[]
for experimentNumber in range(10000):
# Code that creates a list of 10000 'heads' or 'tails' values.
rndnum=random.randint(0,1);
if rndnum==0:
countH=0 # if the random number is "0" then "HEAD" counts will be reset
mylist.append(['T'])
countT+=1
else:
countT=0 # if the random number is "1" then "TAIL" counts will be reset
mylist.append(['H'])
countH+=1
# Code that checks if there is a streak of 6 heads or tails in a row.
if countT==6:
conuterTail.append(countT)
elif countH==6:
conuterHead.append(countH);
numberOfStreaks=len(conuterHead)+len(conuterTail)
print('Chance of streak: %s%%' % (numberOfStreaks / 100))
Solution 5:[5]
I understood the question to be asking: what is the chance that a streak of 6 consecutive like coin tosses would be contained within a set of 100 random coin tosses. I thought this should include instances of multiple streaks within the same set of tosses. Whenever a streak of values reached six in a row, the count was reset to zero, in order to capture the next streak. Some iterations contained no streaks, while others contained multiple. A large number of iterations were averaged to smooth variances. The average value returned was 158-160%, meaning very likely.
import random
numberOfStreaks = 0
countH = 0
countT = 0
iterations_of_experiment = 10000
for experimentNumber in range(iterations_of_experiment):
#Code that creates a list of 100 'heads' or 'tails' values
setOfHundred = [] #set list to empty each iteration
for i in range(100):
if random.randint(0, 1) == 0:
countT = 0 #Set Tails count to zero on head flip
setOfHundred.append('H')
countH += 1
if countH == 6:
numberOfStreaks += 1
countH = 0 #Reset counter to zero to capture -
else: #multiple streaks
countH = 0
setOfHundred.append('T')
countT += 1
if countT == 6:
numberOfStreaks += 1
countT = 0
print('In ' + str(iterations_of_experiment) + \
' iterations of 100 coin tosses, there were ' + str(numberOfStreaks) + \
' streaks of 6 consecutive like coin flips.')
print('Chance of streak: ' + str(numberOfStreaks / iterations_of_experiment * 100) + '%')
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Alain T. |
Solution 4 | Farshid Ghobadzadeh |
Solution 5 | geanakuch |