Books · The Fiddler: Solutions
Chapter 77
Can You Fold the Hexagon?
From Tom Keith comes a hexagonal head-scratcher. A regular hexagon is divided by the six dotted lines running from its centre to each corner, cutting it into six triangular sections labelled to counterclockwise. You may fold only along the dotted lines, with no cutting or tearing, and the hexagon must stay intact throughout. The aim is to fold it into a flat triangular packet the size of a single section, with section on top in its original orientation and every other section stacked behind it.
How many distinct folded packets can you make?
The Fiddler, Zach Wissner-Gross, November 22, 2024(original post)
Solution
The six sections form a closed ring, each joined to its two neighbours along a radial crease. When the whole thing collapses onto one section, every crease lands on one of the two straight edges of the final triangle, and walking around the ring the creases must alternate between the two edges: even-numbered creases pile onto one edge, odd-numbered onto the other. A packet is then just a stacking order of the six layers, with section fixed on top.
The one thing that can go wrong is paper passing through paper. On each edge the creases are hinges joining pairs of layers, and two hinges on the same edge may not interleave: if one joins heights and another , the order is forbidden, because the loops would have to cross. Demanding that the three hinges on each edge nest without crossing, with section on top, leaves exactly distinct packets. They come in four mirror pairs, the simplest being the rolled-up spiral and its reverse.
The computation
Encode the model: place the creases alternately on the two edges, run through every stacking with section on top, and keep those where no two hinges on either edge interleave.
from itertools import permutations
def crossing(pairs, pos): # two hinges interleave on one edge?
arcs = [tuple(sorted((pos[a], pos[b]))) for a, b in pairs]
for i in range(len(arcs)):
a, b = arcs[i]
for c, d in arcs[i + 1:]:
if a < c < b < d or c < a < d < b: return True
return False
def count(n): # n sections in a ring
L = [((k - 1) % n, k % n) for k in range(0, n, 2)] # even creases, one edge
R = [((k - 1) % n, k % n) for k in range(1, n, 2)] # odd creases, other edge
total = 0
for perm in permutations(range(1, n)): # section 0 fixed on top
pos = {s: i for i, s in enumerate((0,) + perm)}
if not crossing(L, pos) and not crossing(R, pos): total += 1
return total
print(count(6)) # 8
Extra Credit
How many distinct packets can you make by folding a regular octagon the same way?
Solution
The same model applies to a ring of eight sections, four creases alternating onto each edge. Counting non-crossing stackings with section on top gives distinct packets.
The computation
The same routine, run on eight sections.
print(count(8)) # 42