Books · The Fiddler: Solutions
Chapter 85
Can You Turn a Right Triangle Into an Isosceles Triangle?
Begin with a -- right triangle. By appending another triangle along one of its sides, you can extend it into a single larger triangle that is isosceles; for instance, gluing a copy along the short leg makes a -- isosceles triangle. Counting that one, in how many distinct ways can you append a triangle to a -- right triangle to make an isosceles triangle?
The Fiddler, Zach Wissner-Gross, September 6, 2024(original post)
Solution
For the original and the appended triangle to fuse into a single triangle, the shared side must be a cevian of the larger triangle, a segment from a vertex to the opposite side, with the -- as one of the two pieces it cuts. So a construction is fixed by three choices: which side of the -- is the cevian, which of its endpoints is the apex of the big triangle, and which two sides of the big triangle are made equal. Running through all cases and discarding the degenerate ones (where the appended piece shrinks to nothing) leaves seven genuine isosceles triangles, the last being the -- from the prompt. So there are ways.
The computation
Encode the construction: for each side as cevian and each apex, solve for the point along the cevian’s line that makes the big triangle satisfy each of the three isosceles conditions, keep the non-degenerate solutions, and count the distinct triangles.
import numpy as np
def count(a, b): # isosceles triangles from a right triangle, legs a, b
P = [np.array([0., 0.]), np.array([a, 0.]), np.array([0., b])]
d = lambda u, v: np.linalg.norm(u - v)
sols = set()
for i, j in [(0, 1), (0, 2), (1, 2)]: # the shared side acts as a cevian
Y = P[({0, 1, 2} - {i, j}).pop()]
for X, W in [(P[i], P[j]), (P[j], P[i])]: # apex X, cevian foot W; Z lies on ray Y->W
dirn = (W - Y) / np.linalg.norm(W - Y); YW = d(Y, W); XY = d(X, Y)
for cond in range(3): # XY=XZ, XY=YZ, XZ=YZ
f = lambda t: [XY - d(X, Y + t*dirn), XY - t, d(X, Y + t*dirn) - t][cond]
ts = np.linspace(YW + 1e-6, 80 * max(a, b), 6000); v = np.array([f(t) for t in ts])
for ii in np.where(np.diff(np.sign(v)))[0]:
lo, hi = ts[ii], ts[ii + 1]
for _ in range(60):
m = (lo + hi) / 2
lo, hi = (m, hi) if np.sign(f(lo)) == np.sign(f(m)) else (lo, m)
t = (lo + hi) / 2; Z = Y + t * dirn
s = tuple(sorted([round(XY, 3), round(t, 3), round(d(X, Z), 3)]))
if t > YW + 1e-3 and s[0] > 1e-2 and s[0] + s[1] > s[2] + 1e-4: sols.add(s)
return len(sols)
print(count(4., 3.)) # 7
Extra Credit
For a general right triangle with legs and , how many such isosceles triangles can you make? What values can take?
Solution
Running the same construction for arbitrary legs, the count is remarkably stable: every right triangle gives with one exception. When the right triangle is itself isosceles (), its mirror symmetry makes several of the seven constructions coincide and others degenerate, and the count collapses to . So the generic answer is , and the right isosceles triangle is the lone special case, giving fewer.
The computation
Reuse the same count routine, sweeping the leg ratio: it returns for every generic shape and at .
ratios = np.linspace(0.3, 4.0, 60)
print(sorted({count(r, 1.0) for r in ratios if abs(r - 1) > 1e-6})) # [7]
print(count(1., 1.)) # 2 (isosceles right)