In a famous experiment, a group of volunteers are asked to toss a fair coin 100 times and note down the results of each toss (heads, H
, or tails, T
). It is generally easy to spot the participants who fake the results by writing down what they think is a random sequence of H
s and T
s instead of actually tossing the coin because they tend not to include as many "streaks'' of repeated results as would be expected by chance.
If they had access to a Python interpreter, here's how they could a more plausibly random set of results:
In [x]: res = ['H', 'T']
In [37]: tosses = ''.join([res[i] for i in np.random.randint(2, size=100)])
In [38]: tosses
Out[38]: 'TTHHTHHTTHHHTHTTHHHTHHTHTTHHTHHTTTTHHHHHHHHTTTHTTHHHHHHHTHHHTHHHH
THTTTHTTHHHHTHTTTTHTTTHTHHTTHHHHHHH'
This virtual experiment features a run of 8 heads in a row, and two runs of 7 heads in a row:
TAILS | i | HEADS
---------------------------
| 8 | *
| 7 | **
| 6 |
| 5 |
** | 4 | **
*** | 3 | ***
******* | 2 | ******
********** | 1 | ********
(This figure was produced by the following code.)
import numpy as np
toss_results = ['H', 'T']
tosses = ''.join([toss_results[i] for i in np.random.randint(2, size=100)])
head_seq = [len(s) for s in tosses.split('T') if s]
tail_seq = [len(s) for s in tosses.split('H') if s]
max_streak_len = max(max(head_seq), max(tail_seq))
head_seq_counts = [head_seq.count(i) for i in range(1,max_streak_len+1)]
tail_seq_counts = [tail_seq.count(i) for i in range(1,max_streak_len+1)]
max_streak_count = max(max(head_seq_counts), max(tail_seq_counts))
print(tosses)
print('{t:^{flen}} | i | {h:^{flen}}'.format(t='TAILS', h='HEADS',
flen=max_streak_count))
print('-'*(max_streak_count*2+7))
for i in range(max_streak_len,0,-1):
print('{tstreak:>{flen}s} |{i:^3d}| {hstreak:<{flen}s}'.format(
tstreak='*'*tail_seq_counts[i-1], hstreak='*'*head_seq_counts[i-1],
flen=max_streak_count, i=i))