Library · The Fiddler: Solutions · Chapter 145
Can You Bob and Weave?
A square weaving loom has evenly spaced hooks along each side, counting the two corners. Label the hooks on one side to , those on the next side clockwise to (so and are the same corner hook), and so on for sides and . Elastic bands join to , to , and so on up to to . As grows, what is the shape of the curve formed by the edges of the bands?
The Fiddler, Zach Wissner-Gross, September 8, 2023(original post)
The official solution appeared in the post of September 15, 2023 and gives a parabola, , for the main puzzle and about percent for the Extra Credit. Both agree with the answers below.
Solution
Make the loom the unit square and put the shared corner at the origin, with side running up the -axis and side along the -axis. Hook is as far from the far end of its side as hook is from the shared corner . Calling that distance , a band joins the point on side to the point on side , for running from to . As grows the bands fill in every value of .
The band with parameter lies on the line since that line passes through both of its ends. So a point of the square is crossed by some band exactly when equals for some between and . The one idea of the solution is to ask how small can be. It shoots up to infinity at both ends of the range, so it has a smallest value, and since it changes continuously it takes every value from that minimum upwards. The point is covered exactly when that minimum is at most .
The minimum comes from a neat trick: multiply by , which is just , and expand: The last two terms multiply to whatever is, and two positive numbers with product add up to at least (because gives ), with equality when they are equal. So with equality when , that is, when . So the smallest value of is . The bands therefore cover precisely the points with , and the curve along their edges is Each band touches this curve at exactly one point, the one with , which is where just reaches . In particular the band with parameter touches it at .
What kind of curve is it? Square to get , and square again: The terms of degree two form a perfect square, , and that is the signature of a parabola. Its axis is the diagonal . There is a more striking description. The squared distance from to the centre of the square is , and the squared distance to the line is . Their difference is which is zero on the curve. So every point of the curve is equally far from the centre of the square and from the line through the shared corner at right angles to the diagonal. That is the definition of a parabola, with that point as its focus and that line as its directrix. Its focus is the centre of the square. It looks unlike a textbook parabola only because it is tilted by and we see just the piece between two corners of the square.
The computation
The check works from the bands alone. At a column it finds the tallest band crossing that column, which is the top of the covered region there. The band with parameter crosses column (for ) at height , which rises and then falls as increases, so a ternary search over finds the tallest. For columns the program then tests the parabola’s defining property directly: the top point should be as far from the centre of the square as from the line .
from math import hypot, sqrt
def height(s, x):
"""Height at column x of the band (0, 1-s) to (s, 0)."""
return (1 - s) * (1 - x / s) if x <= s else 0.0
def edge(x):
"""Top of the region the bands cover at column x: the
tallest band there. Each band's height is a concave
function of s, so a ternary search finds the tallest."""
lo, hi = x, 1.0
for _ in range(80):
a, b = lo + (hi - lo) / 3, hi - (hi - lo) / 3
if height(a, x) < height(b, x):
lo = a
else:
hi = b
return height((lo + hi) / 2, x)
gap = 0.0
for k in range(1, 100):
x = k / 100
y = edge(x)
to_focus = hypot(x - 0.5, y - 0.5)
to_line = (x + y) / sqrt(2)
gap = max(gap, abs(to_focus - to_line))
print("edge points on the parabola:", gap < 1e-9)
It prints
edge points on the parabola: True
Extra Credit
Now place bands on all four corners: as well as to , join to , to and to , for every , making bands. As grows, what fraction of the loom’s area lies between the four sets of bands?
Solution
Each family of bands covers the region between its corner and a copy of the parabola above, so the uncovered centre is the part of the square on the far side of all four parabolas. The figure shows it: a curved square, with its corners pointing at the midpoints of the loom’s sides and its sides bulging outwards.
The four families are mirror images of one another in the two lines through the centre parallel to the sides, and in the two diagonals. These four lines cut the uncovered region into eight congruent pieces. Look at the one in the bottom-left quarter of the square, below the diagonal and left of the midline . Two questions settle its shape.
Which parabola bounds it? The bottom-left corner’s parabola is . The bottom-right corner’s is its mirror image, . For we have , so is the larger of the two and the bottom-left parabola is the higher. The two corners on the top edge do not reach this piece at all. The top-left family covers the points with , but in the piece , so , which is at least because its square is . The top-right family needs , impossible when and are both at most , since each root is then at least . So the piece is bounded below by alone.
Where does it start? The parabola meets the diagonal where , that is, at .
So the piece runs from to , between the parabola below and the diagonal above. Its area is Eight such pieces make up the uncovered region, and the square has area , so
The computation
The edge-finding function from The computation above gives, at each column , how far up from the bottom edge the bottom-left family reaches. The bottom-right family reaches , and by the up–down mirror symmetry the top two families reach down by the same amounts. So the uncovered length of the column is , or nothing if that is negative. Adding these lengths over thin columns gives the area.
M = 4000 # columns, midpoint rule
white = 0.0
for k in range(M):
x = (k + 0.5) / M
low = max(edge(x), edge(1 - x)) # covered from below
white += max(0.0, 1 - 2 * low) / M # and, alike, above
print(f"extra credit: white fraction = {white:.5f}")
It prints
extra credit: white fraction = 0.43790