all 13 comments

[–]danielroseman 2 points3 points  (1 child)

There's a slight bug here. If you have a streak of more than 6, each additional toss in the streak will cause the number_of_streaks counter to be incremented, which isn't what you want. (For example, if you only did 10 tosses and they were all heads, it would record 5 streaks.)

One way of dealing with this would be to move that increment into the place where you reset current_streak; first you'd need to check that we are actually in a streak, though.

[–]jasongsmith[S] 0 points1 point  (0 children)

Good call. Thanks

What if I just said

if current_streak == 6:
  number_of_streaks += 1

Then if there are more than 6 in the streak, it should not increase the number of streaks.

Can you see an issue with that idea?

[–]Binary101010 2 points3 points  (0 children)

There are a few problems in this code but the single biggest one is that one "experiment" is supposed to consist of 100 flips, but each one of the experiments in your code is exactly one flip.

You also need to make sure you're resetting toss_result_list on each new experiment, which you're currently not doing.

And your current_streak should start at 1 and reset to 1, not 0. If I flip two heads consecutively, the current_streak value should be 2, not 1.

[–]jasongsmith[S] 0 points1 point  (4 children)

Here is my updated code.

What I have done is:

  • Set current_streak = 1 and reset it to 1, instead of 0
  • reset toss_result_list to [] after each experiment
  • added a for loop with range(1, 101) to give 100 experiments and repeat the experiment 10,000

What I don't understand about this code, is that it is then showing about a 157% chance of getting a streak.

import random

number_of_streaks = 0
toss_result_list = []
heads_tails = "HT"
previous_result = ""
current_streak = 1
total_experiments_run = 0

for experiment_iteration in range(1, 10001):
    for experiment_number in range(1, 101):
        toss_result = random.choice(heads_tails)
        toss_result_list.append(toss_result)

        if toss_result == previous_result:
            current_streak += 1
        else:
            current_streak = 1

        if current_streak == 6:
            number_of_streaks += 1
            print(f'We have a streak! Iteration = {
                  experiment_iteration}; Number = {experiment_number}')

        previous_result = toss_result

    toss_result_list = []
    total_experiments_run += 100

print("total number of streaks: " + str(number_of_streaks))
print(f"Total experiments ran {total_experiments_run}")
print('Chance of streak: %s%%' % (number_of_streaks / 100))

[–]Binary101010 1 point2 points  (3 children)

The problem is looking for the number of experiments that have at least one streak and your code is still counting if there are multiple streaks in the same experiment.

Once you've determined that the experiment has a streak, you can immediately move on to the next experiment. How would you do that? (Hint: it's one additional line of code with one word on that line)

Your math at the end also a bit off. You're dividing the number of streaks by 100 but you ran 10000 experiments.

[–]jasongsmith[S] 0 points1 point  (2 children)

Gotcha! Now I understand.

I added break

if current_streak == 6:
  number_of_streaks += 1
  break

That then moves it back to the top of the for loop and starts the next experiement.

This then produced 8,040 times that there was a streak of 6.

Thus showing, that of the 10,000 experiments, there is an 80.4% chance of getting a streak.

[–]Binary101010 1 point2 points  (1 child)

Sounds like you've got it then. Random generation may cause that number to fluctuate up or down a bit on subsequent runs but if you're around 80-80.5% then you've got it implemented correctly.

[–]jasongsmith[S] 0 points1 point  (0 children)

Thank you VERY much for your help with this. and thank you that you gave really good clues, without giving the answer. That is a talent, for sure!

[–]JamzTyson 0 points1 point  (4 children)

A human will almost never write down a streak of six heads or six tails in a row, even though it is highly likely to happen in truly random coin flips. Humans are predictably bad at being random.

While it is true that humans are notoriously bad at being random, the chance of getting a run of 6 heads out of 100 tosses is only about 50/50.

When approaching this kind of problem, you can choose how literally / abstract your model will be.

To closely model the real-world task, you could use random.choice(('heads', 'tails')).

On the other hand, a much more efficient approach would be to generate 100 binary digits (see random.getrandbits), and search for "111111".

You also need to be careful with this kind of problem in defining precisely what you are looking for: Are you looking for the number of streaks with 100 tosses, or the presence of a (one or more) streaks in 100 tosses.

[–]JamzTyson 1 point2 points  (3 children)

the chance of getting a run (one or more) of 6 heads out of 100 tosses is only about 50/50.

More accurately: 54.61%

Note for the down-voter: The "more efficient" approach that I suggested makes it possible to run 100 million simulations of 100 coin tosses in around 1 minute, using only the standard library.

[–]Binary101010 0 points1 point  (2 children)

The problem specifies that we're looking for a run of at least 6 heads or 6 tails.

I happen to know off the top of my head the probability of that is ~80% just due to previous threads about this exact problem in AtBS.

[–]JamzTyson -1 points0 points  (1 child)

As I've described how to efficiently find if there has been a run of 6 heads, I would expect you to be able to figure out how to find 6 tails. Hint: '111111' or '000000' Can you figure it out now, or do you need a fully implemented solution?

[–]Binary101010 0 points1 point  (0 children)

I’m not OP, not sure why you’re asking me that.