Library · The Fiddler: Solutions · Chapter 136
Can You Squeeze Your Quads?
Squeeze two quadrilaterals into a unit circle (a circle of radius ). They may share edges, parts of edges or corners, and their corners may sit on the circle itself, but their interiors may not overlap. Each may be convex or concave, but not “crossed” like a bowtie. What is the greatest combined area the two quadrilaterals can have?
The Fiddler, Zach Wissner-Gross, November 10, 2023(original post)
The official solution appeared in the post of November 17, 2023 and gives for the main puzzle and about for the Extra Credit. Both agree with the answers below.
Solution
Start with a good arrangement. Cut a regular hexagon inscribed in the circle along one of its long diagonals. The two halves are congruent trapezoids, each a genuine quadrilateral, and together they fill the hexagon. The hexagon is six equilateral triangles of side , each of area , so the pair covers about percent of the circle.
The real work is to show that nothing does better. Two facts about polygons in a circle carry the argument.
Fact 1: the largest polygon with a given number of corners. Take a convex polygon with corners inside the unit disk. If one of its corners is strictly inside the disk, push that corner a little further from the line through its two neighbours. The polygon stays in the disk and gains area. So a largest such polygon has all its corners on the circle. Now join the centre to each corner. Neighbouring corners whose radii make an angle cut off a triangle of area , so the polygon has area (If one angle exceeds , the centre lies outside the polygon and that triangle counts negatively, which the negative sine does automatically.) When every angle is below , the sine curve bends downwards on that range, so the sum of sines with a fixed total is largest when the angles are equal: the regular polygon, with area . When one angle reaches , its sine is at most and the others total at most , so the area is at most half their total, , which is less anyway. The values grow with , so any convex polygon with at most six corners has area at most that of the regular hexagon, .
Fact 2: the largest quadrilateral in a slice of the disk. A straight line cuts the disk into two slices. Measure each slice by the angle its arc makes at the centre, so the two slices have and . Take a largest quadrilateral inside a slice. Pushing corners outwards as before, every corner ends on the boundary of the slice. A corner on the straight edge can slide along that edge to one of its ends without losing area (the area changes at a steady rate as the corner slides, so one direction or the other does not lose). So all four corners can be taken on the arc. If they cut it at angles with total , the closing angle is and the area is with equal angles again best. The right side increases with up to (its rate of change is , which is not negative there). So for , every quadrilateral in the slice has area at most and for larger at most , the inscribed square.
Fact 2 gives a clean bound for two quadrilaterals on opposite sides of a line. If both slices have and at most , the two terms cancel, since , and with equality only when the line is a diameter. If one slice is larger than , the other is smaller than , and the total is at most . Either way, two quadrilaterals separated by a line cover at most . Equality needs two half-hexagons on a diameter, which is the arrangement we started with.
Putting it together. Let be the smallest convex region containing both quadrilaterals (stretch a rubber band around them). It is a convex polygon whose corners are some of the eight corners of the quadrilaterals, and it contains both, so the combined area is at most the area of .
If has at most six corners, Fact 1 caps its area at .
Otherwise has seven or eight corners, so at most one of the eight corners lies inside . A concave quadrilateral has its inward-pointing corner inside the triangle formed by its other three, and so inside . Hence at most one quadrilateral is concave.
If both are convex, they can be separated by a straight line: two convex shapes whose interiors do not meet always can.
If one, say , is concave, write for its corners on and for the inward one, so is the triangle with the notch removed, and , are edges of . The four corners of are all corners of , so none lies inside the triangle . If reached into that triangle, one of its edges would have to cross the triangle, entering through one side and leaving through another. A straight edge meets the side at most once, so it would cross or , and next to those sides lies the interior of . That is not allowed. So stays outside the triangle , and a straight line separates from the triangle, which contains .
In both cases a line separates the two shapes, and the triangle in the second case is a quadrilateral with a corner to spare, so the bound for separated quadrilaterals applies. Every arrangement therefore covers at most , and the two trapezoids reach it:
The computation
The program searches for good pairs directly. It describes the eight corners in polar form, clamps each radius to the disk, and scores a pair as its combined area, or as if either quadrilateral crosses itself or the two interiors overlap. From random starts it moves one corner at a time by a shrinking random step and keeps any move that does not lower the score.
import math, random
from shapely.geometry import Polygon
def point(r, a):
r = max(0.0, min(r, 1.0)) # stay inside the disk
return (r * math.cos(a), r * math.sin(a))
def score(v):
p = [point(*v[k]) for k in range(8)]
A, B = Polygon(p[:4]), Polygon(p[4:])
if not (A.is_valid and B.is_valid):
return -1 # a crossed (bowtie) shape
if A.intersection(B).area > 1e-12:
return -1 # interiors overlap
return A.area + B.area
random.seed(1)
best = 0
for start in range(8):
v = [[1.0, random.uniform(0, 2 * math.pi)]
for _ in range(8)]
s = score(v)
for it in range(20000):
step = max(0.3 * 0.9993 ** it, 1e-5)
k = random.randrange(8)
w = [q[:] for q in v]
w[k][0] += random.gauss(0, step)
w[k][1] += random.gauss(0, step)
t = score(w)
if t >= s:
v, s = w, t
best = max(best, s)
print(f"best combined area found: {best:.3f}")
It prints
best combined area found: 2.598
which is to three decimal places. A search like this can only approach the best value from below, and it gets no further than the hexagon.
Extra Credit
For four distinct points on the unit circle, let be the area of the quadrilateral they form plus the area of the largest triangle formed by any three of them. For the corners of a square, . What is the greatest possible value of ?
Solution
Label the points in order around the circle. Any three of them leave one out, so every triangle consists of one diagonal of the quadrilateral and one of the two corners off that diagonal. Call the largest triangle , with diagonal , and let be the fourth point.
Two moves can only increase . Slide along its arc to the midpoint of that arc. This takes it as far from as possible, which enlarges the triangle and with it the quadrilateral, since the quadrilateral is plus . Then slide to the midpoint of its arc, which enlarges and so the quadrilateral again. The largest triangle is still at least , so has not dropped. After both moves and sit on the perpendicular bisector of , which passes through the centre, so is a diameter and the shape is a kite.
Now one number describes everything. Let be the distance from the centre to the chord , with on the far side. The chord has half-length . Triangle has height and has height , so and is indeed the largest triangle. Therefore Setting the rate of change to zero and multiplying through by , whose root between and is At (the square) and at it is , so this turning point is the maximum. Substituting and simplifying gives : Amusingly, that is within of .
The computation
The program works from the definition of : it places four points on the circle, computes the area of the quadrilateral they form (taking the points in order round the circle) and the largest of the four triangles, and climbs from random starts as before.
from itertools import combinations
def area(ps):
n = len(ps)
return abs(sum(ps[i][0] * ps[(i + 1) % n][1]
- ps[(i + 1) % n][0] * ps[i][1]
for i in range(n))) / 2
def Z(angles):
ps = [(math.cos(a), math.sin(a))
for a in sorted(a % (2 * math.pi) for a in angles)]
return area(ps) + max(area(t) for t in combinations(ps, 3))
random.seed(1)
best = 0
for start in range(20):
v = [random.uniform(0, 2 * math.pi) for _ in range(4)]
s = Z(v)
for it in range(5000):
w = [a + random.gauss(0, 0.2 * 0.998 ** it) for a in v]
if Z(w) >= s:
v, s = w, Z(w)
best = max(best, s)
print(f"greatest Z found: {best:.4f}")
It prints
greatest Z found: 3.1488