Skip to content
Vamshi Jandhyala

Books · The Riddler

Chapter 59

Who Betrayed Dune’s Duke Leto?

Riddler Express

Exactly two of Jessica, Wellington, Gurney and Duncan are traitors. Traitors lie; the loyal tell the truth. Jessica says “I am not the traitor”; Wellington says the same of himself; Gurney says “Jessica or Wellington is a traitor”; Duncan says “Jessica or Gurney is a traitor” (where “or” allows both). One traitor’s name can be deduced. Who?

Solution

The two “I am not the traitor” claims carry no information: a loyal speaker truthfully denies it, and a traitor lies about it, so either way the statement is consistent. The work is done by Gurney and Duncan.

Suppose Gurney were a traitor. Then his statement is false, so neither Jessica nor Wellington is a traitor; the two traitors would have to be Gurney and Duncan. But then Duncan is also a traitor, making his statement false, so neither Jessica nor Gurney is a traitor, contradicting that Gurney is one. So Gurney is loyal, and his true statement forces at least one of Jessica, Wellington to be a traitor.

Now split on Duncan. If Duncan is loyal, his statement is true, so Jessica or Gurney is a traitor; since Gurney is loyal, Jessica is a traitor, and the second traitor (not Gurney, not Duncan) must be Wellington. If Duncan is a traitor, his statement is false, so neither Jessica nor Gurney is a traitor; the two traitors are then Duncan and, to satisfy Gurney’s statement, Wellington. Both cases share one name: Wellington is a traitor.\boxed{\text{Wellington is a traitor.}}

The computation

Try every pair of traitors, mark each speaker as liar or truth-teller accordingly, and keep the assignments where all four statements hold.

from itertools import combinations
who = ['J', 'W', 'G', 'D']
sols = []
for traitors in combinations(who, 2):
    t = {p: (p in traitors) for p in who}
    says = {                            # what each speaker claims
        'J': not t['J'], 'W': not t['W'],
        'G': t['J'] or t['W'], 'D': t['J'] or t['G']}
    # traitor's claim must be false, loyal's claim must be true
    if all(says[p] != t[p] for p in who):
        sols.append(traitors)
common = set(who).intersection(*[set(s) for s in sols])
print(sols, common)            # [('J','W'),('W','D')], {'W'}

Riddler Classic

On an equilateral triangle, pick one point uniformly at random on each edge and join them into a smaller triangle. What is the probability that the centre (centroid) of the original triangle lies inside this smaller one?

Solution

The smaller triangle is the original with three corner triangles trimmed off, one at each vertex. The centre lies in the small triangle exactly when it lands in none of those corners, and since the corners are disjoint, by the threefold symmetry of the construction Pr(centre inside)=13Pr(centre in the corner at vertex A).\Pr(\text{centre inside}) = 1 - 3\,\Pr(\text{centre in the corner at vertex }A). Use AA as origin with the two edges from AA as axes; the random points on those edges are D=(u,0)D = (u, 0) and F=(0,w)F = (0, w) with u,wu, w uniform on [0,1][0,1], and the centroid sits at (13,13)(\tfrac13, \tfrac13). It lies in the corner triangle ADF={s/u+t/w1}A\,D\,F = \{s/u + t/w \le 1\} precisely when 13u+13w1,i.e.1u+1w3.\frac{1}{3u} + \frac{1}{3w} \le 1, \quad\text{i.e.}\quad \frac1u + \frac1w \le 3. That region needs u12u \ge \tfrac12, and integrating its area, Pr(corner at A)=1/21 ⁣(1u3u1)du=1329ln2.\Pr(\text{corner at }A) = \int_{1/2}^{1}\!\Big(1 - \frac{u}{3u-1}\Big) du = \frac13 - \frac29\ln 2. Therefore Pr(centre inside)=13 ⁣(1329ln2)=23ln20.462.\Pr(\text{centre inside}) = 1 - 3\!\left(\tfrac13 - \tfrac29\ln 2\right) = \frac{2}{3}\ln 2 \approx \boxed{0.462}. That is ln43\ln\sqrt[3]{4}: a simple-looking question with a logarithm for an answer, so the tidy rational one expects never appears.

The computation

Run the experiment: drop a uniform point on each edge, build the small triangle, and test whether the centroid is inside it.

import numpy as np
rng = np.random.default_rng(0)
A = np.array([-0.5, -np.sqrt(3)/6]); B = np.array([0.5, -np.sqrt(3)/6])
C = np.array([0.0, np.sqrt(3)/3]);   G = np.array([0.0, 0.0])
N = 20_000_000
x, y, z = rng.random(N), rng.random(N), rng.random(N)
D = A + np.outer(x, B - A)
E = B + np.outer(y, C - B)
Fp = C + np.outer(z, A - C)
cr = lambda P, Q: P[:, 0]*Q[:, 1] - P[:, 1]*Q[:, 0]
s1, s2, s3 = cr(G - D, E - D), cr(G - E, Fp - E), cr(G - Fp, D - Fp)
neg = (s1 < 0) | (s2 < 0) | (s3 < 0)
pos = (s1 > 0) | (s2 > 0) | (s3 > 0)
inside = ~(neg & pos)
print(inside.mean(), 2/3*np.log(2))            # ~0.462, 0.4621