Chapter 202
So You Want To Tether Your Goat. Now What?
Riddler Express
A father can sing the Unbirthday Song to his daughter on any day that is not her birthday, so the probability of being able to sing it to her on a random day is . She enjoys singing it to other people too, and stops only when she meets someone whose birthday it is today. What is the expected length of her singing streak? More precisely: how many random people can she expect to sing to before it becomes more likely than not that the next person is a birthday match?
The Riddler, FiveThirtyEight, October 12, 2018(original post)
Solution
Assume independent uniform birthdays across days. The probability that a particular random person does not share today’s date is . After singing to independent strangers, the probability that none of them was the birthday person today is The puzzle asks for the largest such that this probability still exceeds , that is, the streak length over which a no-match is still more likely than a match: Taking logarithms, At the survival probability is , and at it drops to . So the streak can carry on for before a birthday encounter becomes more likely than not. The continuous threshold explains the value: at one-event-per-day with rate , a half-life lasts roughly trials.
The computation
Evaluate exactly for around the crossing and read off the last above .
from fractions import Fraction
import math
p_no = Fraction(364, 365)
for N in [250, 251, 252, 253, 254]:
val = float(p_no ** N)
print(f"N={N}: (364/365)^N = {val:.6f}")
crossing = math.log(0.5) / math.log(364 / 365)
print(f"continuous crossing at N = {crossing:.4f}")
print(f"largest N with survival > 1/2: {math.floor(crossing)}")
The script prints at and at , with continuous crossing at , confirming the answer.
Riddler Classic
A farmer owns a circular field of radius . He ties his goat to the fence (a point on the circle’s boundary) with a tether of length . For what tether length does the goat graze exactly half the field by area?
The Riddler, FiveThirtyEight, October 12, 2018(original post)
Solution
Place the field as the unit disc (radius ) centred at the origin. Anchor the goat at on the boundary. The grazing region is the intersection of the unit disc and the disc of radius centred at . Call this intersection a circular lens. We want
Setting up the lens. The two circles intersect at points where and . Subtracting gives , and the chord runs vertically at this . Call this chord . Each circle’s contribution to the lens is the circular segment of that circle cut off by on the side containing the other circle’s centre.
Segment formula. For a circle of radius whose centre lies at horizontal distance from a vertical chord, the segment area on the far side of the chord (the smaller piece if ) is
Both contributions. For the unit field circle (centre at ), the chord sits at horizontal distance , so its segment area on the goat side is For the goat circle (centre at with radius ), the chord sits at horizontal distance from , so its segment area on the field side is The lens is the sum . Setting this equal to gives the implicit equation There is no clean closed form. Numerical solution gives The qualitative picture is right: because the field’s curvature pinches the lens, the tether has to be slightly longer than the radius of the field to enclose half the area. The shortfall, compared to a flat fence (which would need for a half-disc), is the extra .
The computation
Encode the lens area directly from the two circles and solve numerically.
Write the lens area as a function of , with .
Bisect on between and to find the root of .
Report and verify the lens area against a Monte Carlo sample.
from math import acos, sqrt, pi
import random
def lens_area(r, R=1.0):
d = R # anchor on the fence
a = (R*R*acos((d*d + R*R - r*r) / (2*d*R))
+ r*r*acos((d*d + r*r - R*R) / (2*d*r))
- 0.5*sqrt((-d+r+R)*(d+r-R)*(d-r+R)*(d+r+R)))
return a
lo, hi = 0.5, 1.9
for _ in range(80):
mid = 0.5 * (lo + hi)
if lens_area(mid) < pi / 2:
lo = mid
else:
hi = mid
r_star = 0.5 * (lo + hi)
print(f"tether length r/R = {r_star:.6f}")
print(f"lens area at r* = {lens_area(r_star):.6f} (target {pi/2:.6f})")
# Monte Carlo cross-check
random.seed(0)
N = 1_000_000
inside_field = 0
inside_lens = 0
for _ in range(N):
x = random.uniform(-1, 1)
y = random.uniform(-1, 1)
if x*x + y*y <= 1:
inside_field += 1
if (x - 1)**2 + y*y <= r_star*r_star:
inside_lens += 1
print(f"MC lens / field = {inside_lens / inside_field:.4f} (target 0.5)")
The bisection converges to , the lens area equals to machine precision, and the Monte Carlo sample reports to four decimals.