Books · The Fiddler: Solutions
Chapter 92
Can You Pack the Circles?
You want to pack four rows of unit circles into a rectangle with a base of width . In square packing the four rows each hold four circles, stacked directly on top of one another. In hexagonal packing the bottom row holds four circles and the rows above alternate three and four, each nestled into the dimples of the row below. Which packing fits more circles per unit of area?
The Fiddler, Zach Wissner-Gross, June 14, 2024(original post)
Solution
Square packing puts circles in an box, a density of circles per unit area. Hexagonal packing buys height: a circle nestled into a dimple sits a horizontal half-step (offset ) from the circle below, and the two touch at centre-distance , so the rows are only apart instead of . Four rows then reach height , but they hold only circles, for a density of At just four rows the two circles lost from the short rows outweigh the height saved, so to .
The computation
Count circles over bounding area directly for each packing.
import math
sq = 16 / (8 * 8) # 0.2500
hx = 14 / (8 * (2 + 3 * math.sqrt(3))) # 0.2432
print(sq, hx) # 0.25 0.2432
Extra Credit
Hexagonal packing must eventually win as the stack grows. From what height on is it strictly more efficient?
Solution
Square packing holds its density at exactly : rows give circles in height . Hexagonal density oscillates, higher when the top row is a full four and lower when it is a three, but both cases climb toward The last stack where square still matches or beats hexagonal is rows; from (a height of ) hexagonal packing is strictly more efficient at every larger height.
The computation
Compute the hexagonal density row by row and find the first row count beyond which it stays above for good.
def hex_density(n): # n rows, alternating 4, 3, 4, 3, ...
circles = 4 * ((n + 1) // 2) + 3 * (n // 2)
return circles / (8 * (2 + (n - 1) * math.sqrt(3)))
print(next(n for n in range(1, 100)
if all(hex_density(m) > 0.25 for m in range(n, 100)))) # 15