Chapter 29
The Eternal Question: How Much Do These Apricots Weigh?
Riddler Express
You load a drying shed with 1,000 kilograms of apricots that are 99 percent water. After a day they are 98 percent water. How much do the apricots weigh now?
Solution
The trick is to follow the part that does not change. The apricots start at water, so the non-water solids weigh kg, and drying removes only water, leaving those kg untouched. Afterwards the apricots are water, so the solids are of the new total. Ten kilograms making up means the whole now weighs Dropping the water content by a single percentage point halves the weight, which is the surprise.
The computation
The solids are fixed at kg; solve for the new total from the new water fraction.
solids = 0.01 * 1000 # 10 kg, unchanged by drying
print(solids / (1 - 0.98)) # solids are 2% of the new weight -> 500.0
Riddler Classic
I flip a coin. Heads, I win. Tails, I flip again, now needing two heads in a row. Each additional tails raises the run of heads I need by one: after cumulative tails I must flip heads in a row to win. What are my chances of winning?
Solution
At any moment the task is “flip heads in a row,” where is one more than the number of tails so far, and a tails both increases and wipes out any partial run. So picture a ladder of states: in state you need a clean run of heads. From state you either flip those heads straightaway and win, with probability , or a tails interrupts first and you drop to state .
Let be the probability of never winning starting from state . Losing means the tails always arrives before the run completes, at this state and every state after it, so Winning from a very high state needs an ever-longer run of heads and becomes impossible, so , and unwinding from leaves the infinite product The game starts in state , so the chance of winning is That infinite product is a known constant (the Euler function at ), so the answer has the tidy closed form quoted above.
The computation
Two checks: play the game many times (track the required run, growing it by one on every tails, and win when the run is met), and evaluate the product directly.
import numpy as np
rng = np.random.default_rng(0)
runs = 2_000_000; wins = 0
for _ in range(runs):
need = 1; run = 0
while True:
if rng.random() < 0.5: # heads
run += 1
if run == need:
wins += 1; break
else: # tails: longer target, reset the run
need += 1; run = 0
if need > 60: break # essentially certain loss
print(wins / runs) # ~0.7112
prod = 1.0
for n in range(1, 100):
prod *= 1 - 2.0**-n
print(1 - prod) # 0.71121...