Library · The Fiddler: Solutions · Chapter 111
How Many Ways Can You Tile the Tilted Square?
Consider the following array of squares, set out as a square standing on one corner, with rows of , , , , , and squares.
You fill the array with rectangles by repeating two steps. First, select one of the squares along the outer perimeter that is not yet part of a rectangle. Second, form the largest rectangle you can that includes the square you just selected and other squares not yet part of any rectangle. You repeat these steps until every square along the perimeter has been selected. How many distinct final states are possible? (States that are rotations or reflections of each other count as distinct.)
The Fiddler, Zach Wissner-Gross, June 21, 2024(original post)
The official solution appeared in the post of June 28, 2024 and gives , agreeing with the answer below. The Extra Credit half of that post is paywalled, so the count of and the general formula are my own.
Solution
Give each square the coordinates of its centre, with the middle square at . The array is then the set of squares with , and the perimeter squares are the twelve with . They are exactly the two end squares of each row.
The process looks as though it could branch wildly, since every step offers a choice. The idea that tames it is this: every rectangle the process forms cuts what is left into pieces of just two shapes, which the figure below calls pyramids and staircases, and from then on each piece fills itself in without any influence from the others. So the count can be built up from small pieces.
The first rectangle. Suppose the first square chosen is , in the lower left, where and are whole numbers with (the other three quarters are the same by symmetry). A rectangle containing this square has its lower left corner at some square with and . That corner square must lie in the array, so , which forces and . In the same way, the lower right corner must satisfy , and the upper left corner must satisfy . So every rectangle through fits inside the box of squares with and . That box lies inside the array, since its corners satisfy . It is therefore the largest rectangle, and the only one of its size. The first rectangle is always this centred box, squares wide and tall. There are four of them: , , and .
What the first rectangle leaves. Above the box sit the squares with . Their rows have , , …, , squares, a pyramid of height resting on the box. Below the box is another pyramid of height , and to the left and right are pyramids of height . No two of these four pieces touch, even at a corner: the nearest squares of the top and left pieces are and , two apart in each direction. A rectangle is a solid block of free squares, so it can never reach from one piece into another. Each piece therefore runs its own course, and any final state of the top pyramid can be combined with any final state of each of the other three. If is the number of final states of a pyramid of height , the first rectangle leads to final states.
Pyramids. Number the rows of a pyramid of height from the top, so that row has squares and row rests on the rectangle below. The ends of every row are perimeter squares of the original array, and no other squares of the pyramid are. Suppose the end square of row is chosen. The rows above row are narrower and do not reach that end’s column, so the rectangle starts at row . It can be no wider than row . The rows below are all wider, so the full width of row , carried all the way down to the bottom row, is free. That block, wide and tall, is the largest rectangle, and the only one of its size.
The block leaves a pyramid of height on top. On each side it leaves the parts of rows that stick out beyond it, with squares: a staircase of size , flat against the block and stepped on the outside. Writing for the number of final states of a staircase of size , and using the same independence as before,
Staircases. In a staircase of size , row (from the top) has squares, and only its outer end is a perimeter square. Choosing the outer end of row forms, by the same reasoning, the block of rows to that is squares wide. It leaves a staircase of size above it and a staircase of size beside it, made of the overhanging parts of the rows below. Hence which is the recurrence of the Catalan numbers: for .
Why nothing is counted twice or stranded. In every piece, different first choices give different final states, because they put a particular square (the middle of the bottom row of a pyramid, or the bottom inner square of a staircase) into different rectangles. The same holds for the whole array, where the middle square’s rectangle tells the four first rectangles apart. So the sums above add up disjoint sets of final states. And every piece that still has squares still has a perimeter square (the end of its top row), so the process never stops with a square left over.
The count. The pyramid numbers are Summing over the four first rectangles, , The two s are the official solution’s “seven ways on each half” when the first rectangle runs right down the middle.
The computation
The program plays the process exactly as stated, with no use of pyramids or staircases.
List every rectangle that fits inside the array, largest first, each as a bit mask of its squares.
From a set of free squares, try every free perimeter square in turn. For that square, take the largest listed rectangle that contains it and is wholly free, and check that no other rectangle of the same size would also do (the rule would be ambiguous otherwise).
Recurse on the squares that remain, remembering results for sets already seen, and collect the final states as sets of rectangles. When no perimeter square is free, check that no square at all is left over.
It finds final states.
from functools import lru_cache
def count_final_states(n):
span = range(-n + 1, n)
cells = [(x, y) for x in span for y in span if abs(x) + abs(y) <= n - 1]
bit = {c: 1 << i for i, c in enumerate(cells)}
rim = [bit[c] for c in cells if abs(c[0]) + abs(c[1]) == n - 1]
rects = [] # every rectangle inside the array
for a in span:
for b in span[a + n - 1:]:
for c in span:
for d in span[c + n - 1:]:
box = [(x, y) for x in range(a, b + 1) for y in range(c, d + 1)]
if all(p in bit for p in box):
rects.append((len(box), sum(bit[p] for p in box)))
rects.sort(reverse=True) # largest first
through = {r: [(s, m) for s, m in rects if m & r] for r in rim}
def biggest(free, r):
fits = [(s, m) for s, m in through[r] if m & free == m]
assert len(fits) == 1 or fits[0][0] > fits[1][0] # never a tie
return fits[0][1]
@lru_cache(maxsize=None)
def finish(free):
todo = [r for r in rim if r & free]
if not todo:
assert free == 0 # no square is left over
return {frozenset()}
out = set()
for r in todo:
box = biggest(free, r)
out |= {rest | {box} for rest in finish(free & ~box)}
return out
return len(finish(sum(bit.values())))
print(count_final_states(4))
It prints
106
Extra Credit
Now the array has five squares along each outer edge (rows of , so squares), and the same process is followed. How many distinct final states are possible? Can you find a general formula for an array with squares along each outer edge?
Solution
Nothing in the argument above used the size of the array. With squares along each edge, the array is the set of squares with . The first rectangle is again a centred box , now with , and it again leaves two pyramids of height and two of height . So with the pyramid numbers given by where is the th Catalan number. The pyramid numbers run , and the next one is For the first rectangle has or , giving The sequence for begins . Almost all of it comes from the long, thin first rectangles (with or equal to ), which leave two big pyramids: for they account for of the states.
The computation
The program from the main problem plays the process for to , and the formula is evaluated alongside it. The two agree at every size, including for . (The same simulation also gives for , matching the formula, but it takes about twenty seconds, so it is left out here.)
from math import comb
def formula(n):
catalan = [comb(2 * m, m) // (m + 1) for m in range(n)]
P = [1]
for h in range(1, n):
P.append(sum(P[r - 1] * catalan[h - r] ** 2 for r in range(1, h + 1)))
return sum(P[a] ** 2 * P[n - 1 - a] ** 2 for a in range(n))
for n in range(1, 6):
print(n, count_final_states(n), formula(n))
It prints
1 1 1
2 2 2
3 9 9
4 106 106
5 3002 3002