Books · The Fiddler: Solutions
Chapter 23
Can You Brighten Up the Room?
A lamp is a point light source at the centre of a spherical bulb of radius foot. The top half of the bulb is opaque; the bottom half is semi-transparent, letting light out (to illuminate the table) but not back in. The source sits feet off the ground and feet below the ceiling. What is the radius of the circular shadow cast on the ceiling?
The Fiddler, Zach Wissner-Gross, January 16, 2026(original post)
Solution
The opaque top blocks every ray the source aims upward, so no direct light reaches the ceiling. The ceiling is lit only by light that escapes downward through the transparent base, reflects off the table, and travels back up. That reflected light behaves exactly as if it came from a virtual source, the mirror image of the real one, sitting feet below the floor. The opaque top hemisphere now casts a shadow of this upward-bound reflected light, and the edge of the shadow is the ray from the virtual source that just grazes the rim of the opaque dome (the bulb’s equator, radius at the source’s height).
Put the floor at , the source at (so the ceiling is at and the virtual source at ). The grazing ray leaves , passes the rim at , and reaches the ceiling where So the shadow radius is and, neatly, the height cancels: the radius is for any symmetric placement (source midway between floor and ceiling).
The computation
Ray-trace the geometry: from the virtual source below the floor, scan outward along the ceiling and mark each point whose ray to the source passes through the opaque upper half of the bulb. The last blocked point is the shadow edge, at .
import numpy as np
def shadow_R(r, h):
S = np.array([0, 0, -h]) # virtual source below the floor
C = np.array([0, 0, h]) # bulb centre
def blocked(X):
d = np.array([X, 0, 2*h]) - S # ray to a ceiling point
a = d@d; b = 2*((S - C)@d); c = (S - C)@(S - C) - r*r
disc = b*b - 4*a*c
if disc <= 0: return False
t1, t2 = sorted(((-b - np.sqrt(disc))/(2*a), (-b + np.sqrt(disc))/(2*a)))
ts = np.linspace(max(0, t1), min(1, t2), 200); pts = S + np.outer(ts, d)
return np.any(pts[:, 2] > h + 1e-9) # passes through the opaque dome
edge = 0
for X in np.linspace(0, 2*r, 4000):
if blocked(X): edge = X
else: break
return edge
print(round(shadow_R(1, 5), 4), "vs 3r/2 =", 1.5) # 1.4998 ~ 1.5
Extra Credit
The lamp has radius and hangs at height in a room of height . The architect wants , , and to all be whole numbers of feet. What is the smallest possible ?
Solution
Since regardless of , the radius is a whole number exactly when is even. The smallest even radius is , giving Any whole height works (so the bulb fits between floor and ceiling), for instance , , in a -foot room. The height is a decoy: only the parity of matters.
The computation
Scan radii in increasing order and keep the first whose shadow comes out a whole number.
from fractions import Fraction as F
print(min(F(3, 2)*r for r in range(1, 12) if (F(3, 2)*r).denominator == 1)) # 3