Chapter 268
How Long Will The Bacterial Colony Last?
Riddler Express
In “bowling” a die you pinch two opposite faces, so the die lands on one of the other four faces, each with probability . You want to roll a or with two dice (standard rolling wins ). Bowling the dice one at a time, knowing the first result before the second, what is your best chance of a or ? Extra credit: now score for a or and for a , or ; bowling to maximise the expected score, what is that average?
The Riddler, FiveThirtyEight, June 12, 2020(original post)
Solution
Opposite faces of a die sum to , so a bowl pinches one of the pairs , or and leaves the other four faces equally likely. Bowl the first die to keep your options open: pinching leaves , so half the time you roll a or . That matters because a first roll of can be completed to (with a ) or to (with a ), and a to or likewise, doubling the ways to win, whereas a first roll of can only reach .
Given the first result, bowl the second die to keep the faces you need. Working through the four equally likely first outcomes and choosing the best second pinch each time, the chance of finishing on or is a big jump from . For the scoring version, the penalty faces change which first pinch is best (now ), and the optimal expected score works out to about three times the of ordinary rolling.
The computation
Encode the bowl as a choice of which opposite pair to pinch (leaving four equiprobable faces). Optimise the second pinch for each first outcome, then the first pinch, for both the win-probability objective and the scoring objective.
from fractions import Fraction as F
pairs = [(1, 6), (2, 5), (3, 4)]
strats = [[f for f in range(1, 7) if f not in p] for p in pairs]
def best(score):
return max(sum(max(sum(score(d1 + d2) for d2 in s2) / 4 for s2 in strats)
for d1 in s1) / 4 for s1 in strats)
win = best(lambda t: 1 if t in (7, 11) else 0)
ec = best(lambda t: 1 if t in (7, 11) else (-1 if t in (2, 3, 12) else 0))
print(F(win).limit_denominator(), F(ec).limit_denominator()) # 3/8 5/16
Riddler Classic
Each bacterium of Riddlerium classicum either splits into two copies (probability ) or dies (probability ). Starting from a single bacterium, what is the probability the colony lasts forever? Extra credit: with split probability in general?
The Riddler, FiveThirtyEight, June 12, 2020(original post)
Solution
This is a branching process. Let be the probability that the colony dies out, starting from one bacterium. That first bacterium either dies at once (probability ) or splits into two independent colonies, each of which must itself die out (probability ). So This quadratic has roots and . Extinction takes the smaller root. For that is : extinction is certain. For it is , so the colony survives with probability .
At , , so the everlasting probability is In general,
The computation
Encode the process directly: simulate colonies generation by generation and measure how often one survives past a deep cutoff. Compare with the closed form .
import random
def survives(p, gens=200, trials=200000, seed=0):
rng = random.Random(seed); lived = 0
for _ in range(trials):
pop = 1
for _ in range(gens):
pop = sum(2 if rng.random() < p else 0 for _ in range(pop))
if pop == 0: break
if pop > 5000: break # treat as everlasting (runaway)
lived += pop > 0
return lived / trials
for p in (0.8, 0.6, 0.5):
print(p, round(survives(p), 3), round(max(0, (2 * p - 1) / p), 3))
# 0.8 ~0.75 0.75 | 0.6 ~0.333 0.333 | 0.5 ~0.01 0.0 (critical: ~0 over a finite horizon)