Skip to content
Vamshi Jandhyala

Books · The Fiddler: Solutions

Chapter 96

Can You Solve a High Schooler’s Favorite Puzzle?

You have an unlimited supply of 3×33\times3 tiles and 5×55\times5 tiles. You want to tile a square of integer side length exactly, with no overlaps and no overhang, using at least one tile of each kind. What is the smallest square you can tile this way?

The Fiddler, Zach Wissner-Gross, May 10, 2024(original post)

Solution

Matching areas is necessary but nowhere near sufficient. A side nn needs n2=9a+25bn^2=9a+25b with a,b1a,b\ge1, and the smallest sides clearing that hurdle are 13,14,16,1713,14,16,17, and 1818. Yet the area can balance while the tiles refuse to fit: a complete search (cover the first empty cell with a 55 or a 33, recurse, backtrack) shows that 13,14,1613,14,16, and 1717 admit no tiling at all, the 33s and 55s never reconciling along the edges. The first side that genuinely tiles with both sizes present is 18,\boxed{18}, which packs as a border of 33s around a central block of 55s.

The computation

The search is exact, not heuristic: because the first empty cell (scanning top to bottom, left to right) must be the top-left corner of whatever tile covers it, trying both tiles there and backtracking enumerates every tiling. Returning to the smallest side that admits one with both kinds present gives 1818.

def tileable_mixed(n):
    grid = [[0] * n for _ in range(n)]
    def first_empty():
        for r in range(n):
            for c in range(n):
                if not grid[r][c]: return r, c
        return None
    def fits(r, c, s):
        return r + s <= n and c + s <= n and all(
            not grid[i][j] for i in range(r, r+s) for j in range(c, c+s))
    def fill(r, c, s, v):
        for i in range(r, r+s):
            for j in range(c, c+s): grid[i][j] = v
    def solve(n3, n5):
        p = first_empty()
        if p is None: return n3 >= 1 and n5 >= 1
        r, c = p
        for s, nxt in [(5, (n3, n5+1)), (3, (n3+1, n5))]:
            if fits(r, c, s):
                fill(r, c, s, s)
                if solve(*nxt): return True
                fill(r, c, s, 0)
        return False
    return solve(0, 0)
print(next(n for n in range(3, 30) if tileable_mixed(n)))    # 18

Extra Credit

Now you have tiles of every odd side length greater than 11 (3,5,7,9,3,5,7,9,\dots). What is the largest NN for which an N×NN\times N square cannot be tiled?

Solution

Any odd N3N\ge3 is a single tile, so only even sides are ever in doubt. Searching each even side in turn, the ones that cannot be broken into odd squares at all are exactly 1,2,4,81,2,4,8, and 1616, while 6,10,12,146,10,12,14 and every side from 1818 upward can. The largest impossible square therefore has side 16.\boxed{16}. It is the last even side too cramped to split into odd squares; 1818 and every larger even side go through.

The computation

The same exact backtracking search, now with every odd tile up to side nn, lists the sides that admit no tiling.

def tileable(n):
    grid = [[0] * n for _ in range(n)]
    odds = [s for s in range(n, 2, -1) if s % 2]      # odd sizes, largest first
    def solve():
        p = next(((r, c) for r in range(n) for c in range(n) if not grid[r][c]), None)
        if p is None: return True
        r, c = p
        for s in odds:
            if r+s <= n and c+s <= n and all(not grid[i][j]
                    for i in range(r, r+s) for j in range(c, c+s)):
                for i in range(r, r+s):
                    for j in range(c, c+s): grid[i][j] = s
                if solve(): return True
                for i in range(r, r+s):
                    for j in range(c, c+s): grid[i][j] = 0
        return False
    return solve()
print([n for n in range(1, 33) if not tileable(n)])          # [1, 2, 4, 8, 16]