Which rectangles hold three, four or five unit squares, if the squares may be turned to any angle? The boundaries have been on record since 2010, as constructions in a problem posed by Erich Friedman. Here they are proved: the constructions cannot be beaten. All three theorems are checked in Lean 4 with no hypotheses.
Call the rectangle's sides s ≤ ℓ (short and long). The squares are closed unit squares at any positions and angles, inside the rectangle, with disjoint interiors. Every square needs s ≥ 1, and two squares need ℓ ≥ 2, since otherwise every unit square in the box contains the box's centre in its interior. For three squares or more, tilting starts to pay.
Theorem (rect3_iff, rect4_iff, rect5_iff). With 1 ≤ s ≤ ℓ:
At s = ℓ the five-square case is s(5) = 2 + 1/√2 (Göbel 1979). The tilted pieces live in thin slivers: 1.9142 ≤ s < 2 for three squares ((1 + 2√2)/2 ≤ s), 1.8816489 ≤ s < 2 for four, 1.8713 ≤ s < 2 ((6√2 − 1)/4 ≤ s) and 1 + √2 ≤ s ≤ 2 + 1/√2 for five.
In the plot, a point is a rectangle: short side across, long side up. The shaded region is the set of rectangles that hold n squares; its lower edge is the boundary, with the tilted pieces in gold. Click or drag along the boundary, or use the slider, to see the packing that sits exactly on it. Every packing is drawn from the construction proved in Lean.
Each boundary point is attained: the packings drawn are in the closed rectangle, touching where they look as if they touch. Inside the shaded region more room is to spare; below the boundary, the theorem says no packing exists at all, at any angles. The vertical pieces at s = 2 are where the short side reaches 2 and the squares can be stacked two high.
All three boundaries, and every packing on them, are in Erich Friedman's Math Magic problem of the month for June 2010. Friedman asks for the region Sn of rectangles that hold at most n unit squares, so the boundary of Sn−1 is the boundary we want for n; his x is our long side ℓ and his y our short side s. The page names that month's solvers as Maurizio Morandi, Evert Stenlund, David W. Cantrell and Hiroaki Hosono, and gives an author for some of the pieces in its table:
| n here | Friedman | pieces of the boundary | author column |
|---|---|---|---|
| 3 | S₂ | x = 3; x + 2y = 4 + 2√2 (the 45° wedge); y = 2 | empty for all three |
| 4 | S₃ | x = 4; a parametric curve (the tilted pair); y = 2 | MM for the curve, empty for the other two |
| 5 | S₄ | x = 5; x + 4y = 4 + 6√2 (the zigzag); y = 2; x = 3; x + y = 4 + √2 | MM for all five |
The table gives authors by initials only. MM matches Maurizio Morandi, the only named solver with those initials. The page was last updated in February 2019 and gives constructions, not proofs.
Other earlier work bears on these three cases:
Our part. We came to the three-square case by a numerical search, found the 45° wedge, and took it for new; a day later we learned it was in Friedman's table (posted in 2010, last updated in 2019). We then used his tables as the target for four and five. What is new here is the other direction: the proof that nothing below the boundary can be packed. As far as we know these are the first proofs of these lower bounds, for n = 3, 4 and 5, and the first theorems about squares in non-square rectangles in any proof assistant.
When the short side is 2 or more, all three answers are easy for n = 3 and 4: two rows fit. The work is in strips [0, L] × [0, H] with H < 2. There the squares cannot be stacked: each centre lies between heights ½ and H − ½, so any two centres differ in height by less than H − 1 < 1. That makes the squares a chain, left to right.
Three squares. Now b sits alone between two shelves, and the whole question is how short L can be. Which point of b a shelf stops is one of three: the corner of b that points at the shelf, if it is at a height inside the band, or else the point of an adjacent edge at the band's top or bottom. That gives 3 × 3 cases, each a real inequality in b's angle. Seven give L ≥ 3 outright. The two where b stands on the floor or hangs from the ceiling with an edge on each shelf give L + 2H ≥ 4 + 2√2, with equality only at 45°: Friedman's wedge.
The step that makes this short is the shelf: once the neighbours may be taken upright, a single square against two shelves carries the whole boundary. The Lean proof of rect3_iff is 171 lines, on top of 418 lines of chain tools reused below.
Four squares. Sort a, b, c, d. Square b has a shelf on its left (from a), c a shelf on its right (from d), and a line at some angle t separates b from c. Two more steps:
So the minimum of L(t, H) over t is exactly the boundary, and rect4_friedman shows that the packing exists for every t with L(t, H) < 4. The tilted piece runs from H = 1.8816489, where it meets the row of four, up to H = 2, where t = 45° and L = 4√2 − 2 ≈ 3.657. Lean: 592 lines.
With both sides at least 2 the chain breaks: squares can stack. For five squares this part of the boundary contains the square 2 + 1/√2, and we use the method that proves s(5): unavoidable points, here with weights.
The principle. Put points with weights in the a × b box so that every closed unit square inside the box contains points of total weight at least 1. Five closed unit squares that do not even touch contain disjoint sets of points, so if the total weight is less than 5, they cannot all be in the box.
Packed squares may touch, and a point on a shared edge would be counted twice. But the covers have to count points on a square's edge: at the boundary they are tight. Scaling resolves both. A packing in a box below the boundary is ruled out by scaling it up: enlarge the box onto the boundary line a + b = 4 + √2 by a factor λ > 1, together with the squares. The enlarged squares have disjoint interiors, so the unit squares at their centres are disjoint even as closed sets, and each contains weight at least 1. Boxes with a ≤ 1 + √2 and b < 3 are first widened to a = 1 + √2, which handles the flat piece ℓ = 3.
Four points (for 4 − √2 ≤ a ≤ 2 + 1/√2 on the line). The points (1, 1), (a − 1, 1), (1, b − 1), (a − 1, b − 1), weight 1 each. Split the possible centres into nine cells: near a corner the corner point is caught; along a wall, one of the two points on that wall (the side-strip lemma of Friedman's survey, which needs the gap between them at most 2√2 − 2); in the middle, a new lemma: a unit square whose centre lies in an X × Y rectangle with X, Y ≤ 1 and X + Y ≤ √2 contains one of the rectangle's corners. At a = b this gives s(5) = 2 + 1/√2, by essentially the classical argument with the centre handled by the rectangle lemma.
Cover C (for 1 + √2 ≤ a ≤ 4 − √2). Here the side-strip lemma fails: a square at 45° sitting against a long wall slips between the two points on it, and a numerical search found no set of four points that works. A linear program over fractional weights found covers, and one simplifies to ten points:
Total 14/3 < 5. Every closed unit square in the box contains a whole block of weight exactly 1: a row pair {(0.91, 1), (1, 1)}, a wall pair {(0.91, 1 or b − 1), (1, b/2)}, or a centre triple {(1, 1 or b − 1), (1, b/2), (a − 1, b/2)}, up to mirror images. The Lean proof splits the centres into three cells, each closed by short lemmas of the same kinds as above (corner, side strip, and a variant of the centre lemma).
Drag the square, turn it with the slider (or the mouse wheel), and try to catch less than weight 1. The small map shows the weight caught for every centre at the current angle; gold is exactly 1, where the cover is tight. The box follows the boundary line a + b = 4 + √2 (for cover C and the four points) or the strip 5 × H (§05). The page samples; the Lean proof covers every position and angle.
Low strips, H < 2√2 − 1 ≈ 1.828. Four points on the midline, (1, H/2), …, (4, H/2), in the 5 × H box: every unit square in it contains one (select "low strip" above). Between two midline points this is the side-strip lemma again, with gap 1 at height H/2, and its condition 1/2 + H/2 ≤ √2 is exactly H ≤ 2√2 − 1. So in low strips five squares need length 5. Lean: 98 lines.
High strips, 2√2 − 1 ≤ H < 2. This contains the zigzag, Friedman's piece ℓ + 4s = 4 + 6√2 for s ≥ (6√2 − 1)/4 ≈ 1.8713.
The chain applies as before: shelves on b and d, lines between b and c and between c and d. A concavity argument (in Lean) shows that the middle square is narrowest between the two lines when it is upright or parallel to one of them. What is left is one real inequality in the two lines' angles and the height. But the two halves now see different lines, coupled through the middle square, and the natural ways to decouple them lose (numerically, by 0.1 or more); one split that loses nothing has not been turned into a proof yet. We proved the remaining inequality by machine:
That is 14,411 lines of generated Lean, about 5 minutes to build on 16 cores (70 CPU-minutes). It was not a surprise to need certificates at n = 5, though we had hoped to put them off to larger n. A structured proof of this step is open.
git clone https://github.com/evand/square-packing && cd square-packing/lean
lake exe cache get # Mathlib
lake build Sqpack.Rect3 # rect3_iff ~15 s
lake build Sqpack.Rect4 # rect4_iff ~15 s
lake build Sqpack.Rect5Thm # rect5_iff ~5 min on 16 cores, mostly the generated files
lake build && lake env lean Axioms.lean
Axioms.lean prints the axioms of every theorem in the library (it imports all of it; the rectangle theorems are near the end) and must show only propext, Classical.choice and Quot.sound: no sorry, no native_decide. To check only these three, put import Sqpack.Rect5Thm and #print axioms SquarePacking.rect5_iff (and the same for rect3_iff, rect4_iff) in a file and run lake env lean on it. The build times are wall times on a 16-core machine; the generated files build one at a time, each Lean process using about 5 cores. A full lake build also builds unrelated parts of the library, one of which needs about 23 GB of memory.
The statements use one definition, RectPacks n w h: n closed unit squares, at any centres and angles, each inside [0, w] × [0, h], with pairwise disjoint interiors.
| file (lean/Sqpack/) | what |
|---|---|
| Rect.lean | RectPacks; two squares (rect2_iff); the wedge |
| RectChain.lean | the chain: separation, upright replacement, shelves, witnesses |
| Rect3.lean | rect3_iff |
| Rect4.lean, Rect4Core.lean | one-square lemma, half turn, Friedman's packing; rect4_iff |
| Rect5Pack.lean | the five-square constructions: row, grid, zigzag, stretched s(5) |
| Rect5Pts.lean, Rect5Line.lean | the four points and cover C; both sides ≥ 2 |
| Rect5Low.lean | midline points, low strips |
| Rect5.lean, Rect5Mid.lean, Rect5Final.lean, Rect5Hi*.lean | high strips: the chain for five squares and the generated certificates |
| Rect5Iff.lean, Rect5Thm.lean | Fits5; rect5_iff |
Research notes: search/rectfront/RECTFRONT.md (the log), LESSONS.md (techniques, what failed), r5pts/R5PTS.md (point covers, with paper proofs), r5strip/FINAL5.md (the certificates).