1

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.

13
  • What are the different results? What did you expect the results to be? Given the nature of randomness, why did you expect them to be the same? Commented Sep 29, 2021 at 17:41
  • 1
    Not related to the problem, but you could just use random.choice(('H', 'T')) instead of random.randint(0, 1) and then converting the numbers to letters. Commented Sep 29, 2021 at 17:41
  • 2
    What problem does the code need to solve? You haven't described the problem, only shown two solutions, one of which "is clearly false". Commented Sep 29, 2021 at 17:42
  • 1
    Is your indentation exactly as you have it in your script? Your second for loop is indented one level too deep. Commented Sep 29, 2021 at 17:43
  • 1
    The second for loop shouldn't be inside the first for loop. Commented Sep 29, 2021 at 17:43

5 Answers 5

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Just be aware that appending to a string is an O(len(string)) operation since Python will copy the string to a new memory location and add the next character to it, and doing it in a loop will make the inefficiency even more apparent. It would be more efficient to create the string by appending the coin flip results to a list then using "".join() to build the string.
0

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) 

Comments

0

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.

Comments

0
#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)) 

Comments

0

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) + '%') 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.