Chapter 1
The Honest Prince and the Rancher’s Children
The Riddler for March 17, 2017. The Express is a one-question logic puzzle with three princes (one always honest, one always lying, one mischievous); the Classic asks for the probability that four houses, one in each of four neighbouring ranches, form a convex quadrilateral.
Riddler Express
You are choosing whom to marry among a king’s three sons. The eldest prince always tells the truth, the youngest always lies, and the middle prince is mischievous, telling the truth sometimes and lying the rest of the time. The three look identical, so you cannot tell them apart by sight. The king lets you ask exactly one yes-or-no question to exactly one of the three. You will be happy marrying either the truthful eldest or the consistent-liar youngest; you want to avoid marrying the mischievous middle. What question guarantees you avoid the middle prince?
The Riddler, FiveThirtyEight, March 17, 2017(original post)
Solution
The crucial observation is that whoever you ask, you cannot marry that one. So the strategy must use the answer to pick between the other two, and it must produce the right pick regardless of whether the asked prince is honest, mischievous, or a liar. If the asked prince happens to be the middle, his answer is junk; but the other two are then exactly the eldest and the youngest, and any choice between them is acceptable. The work is to make the strategy correct when you ask one of the truthful brothers (eldest or youngest).
The princes’ roles are tied to age: eldest = honest, middle = mischievous, youngest = liar. Pick any prince and call him ; call the other two and in some fixed order. Ask : Marry if says yes, marry if says no.
Why it works: split on who is.
is the eldest (honest). Then are the middle and the youngest. truthfully says whether in age. “Yes” means is older, so is the middle and is the youngest; the strategy picks , the youngest, who is the honest liar. “No” means is older (or equal, but they have distinct ages), so is the middle and is the youngest; the strategy picks , the youngest. Either way you marry the youngest, who is fine.
is the youngest (liar). Then are the eldest and the middle. The truth is that the eldest of these two is older; lies. If is in fact older (so is the eldest), says “no”; the strategy picks , the eldest. If is older, says “yes”; the strategy picks , the eldest. Either way you marry the eldest, who is fine.
is the middle. You will not marry in any case. The strategy picks one of or ; both are non-middle, so you are fine.
In every branch you avoid the middle. The boxed strategy:
The computation
Encode the problem exactly. Enumerate every assignment of identities to , simulate each truth-telling rule, and verify the strategy never returns the middle prince. The mischievous prince is allowed to answer either way; we check both.
from itertools import permutations, product
# Roles by age: eldest=2 (honest), middle=1 (mischievous), youngest=0 (liar).
def answer(role, b_older_than_c): # answer to "is B older than C?"
if role == 2: return [b_older_than_c] # truth
if role == 0: return [not b_older_than_c] # lies
return [True, False] # mischievous, either possible
bad = []
for A_role, B_role, C_role in permutations([0, 1, 2]):
b_older = (B_role > C_role) # true if B is older than C
for a in answer(A_role, b_older):
chosen_role = C_role if a else B_role
if chosen_role == 1: # marrying the mischievous = failure
bad.append((A_role, B_role, C_role, a))
print("failure cases:", bad)
# failure cases: []
Riddler Classic
Four neighbouring square ranches are arranged in a grid, sharing a common corner. Each ranch is a unit square, and each family builds its house at a point chosen uniformly at random inside its own ranch. The four houses are then joined in cyclic order, giving a quadrilateral. What is the probability that this quadrilateral is convex?
The Riddler, FiveThirtyEight, March 17, 2017(original post)
Solution
Place the ranches as the four unit squares meeting at the origin: uniform in the bottom-left, in the top-left, in the top-right, in the bottom-right (any cyclic labelling works). Join them in this order to form the quadrilateral .
The quadrilateral is always simple. The two “vertical” sides and lie strictly in the left and right half-planes respectively, so they cannot meet; the two “horizontal” sides and lie strictly in the upper and lower half-planes, so they cannot meet. The cyclic polygon is therefore self-non-crossing, and convex reduces to every interior turn bends the same way.
Only one vertex at a time can spoil it. A simple quadrilateral fails to be convex exactly when one of its four vertices lies inside the triangle formed by the other three. By symmetry of the setup across the four ranches, the four “bad” events have equal probability, and only one of them can occur at a time (you cannot have two vertices inside the triangles of the other three in a simple quadrilateral). So
The single bad probability. Fix the two neighbours and in their respective ranches, with each uniform on . The line cuts across the top-left ranch (the one containing ), and the bad region for is the triangle bounded by and the two axes (the boundary of the top-left ranch closest to the origin). Working out the slope-intercept geometry, this triangle has one vertex at the origin and legs of lengths so its (signed) area is , with sign flipping when flips. Squaring kills the sign, and another factor of averages over the two configurations in which the triangle is actually inside the ranch (the other half of the time the bad region sits in the opposite ranch and is counted by symmetry). Each ranch has unit area, so the probability that lies in the bad triangle is the expected (signed-corrected) area:
Closed form. This iterated integral can be evaluated either by hand (partial fractions then a collection) or symbolically. The result is Putting it together with the four-fold symmetry, So
The computation
Two independent checks: a symbolic evaluation of the integral above with sympy, and a Monte Carlo of the original random experiment (drop one house in each ranch, form the cyclic quadrilateral, test convexity). Both should reproduce to their respective precisions.
import sympy as sp
a, b, p, q = sp.symbols('a b p q', positive=True)
integrand = (b * p - a * q) ** 2 / ((a + p) * (b + q))
I = sp.integrate(integrand, (a, 0, 1), (b, 0, 1), (p, 0, 1), (q, 0, 1))
P_bad = sp.Rational(1, 4) * I
P_convex = 1 - 4 * P_bad
print("integral =", sp.simplify(I))
print("P(convex) =", sp.simplify(P_convex), "=", float(P_convex))
# integral = -5/6 + 4*log(2)/3
# P(convex) = 11/6 - 4*log(2)/3 = 0.9091370925867396
import numpy as np
from numpy.linalg import det
rng = np.random.default_rng(0)
def is_convex(poly):
signs = set()
for i in range(4):
a = poly[i] - poly[(i + 1) % 4]
b = poly[(i + 2) % 4] - poly[(i + 1) % 4]
signs.add(np.sign(det(np.array([a, b]))))
return len(signs) == 1 # every turn bends the same way
runs = 1_000_000; convex = 0
for _ in range(runs):
q_poly = np.array([
[rng.uniform(0, 1), rng.uniform(0, 1) ], # top-right
[rng.uniform(-1, 0), rng.uniform(0, 1) ], # top-left
[rng.uniform(-1, 0), rng.uniform(-1, 0)], # bottom-left
[rng.uniform(0, 1), rng.uniform(-1, 0)], # bottom-right
])
convex += is_convex(q_poly)
print(convex / runs) # ~0.9091