Skip to content
advent of code 2020

day 20

jurassic jigsaw

approach

each tile is a character grid. rotations yields all eight orientations (four in-place rotations, each also flipped), and every edge is hashed into an integer by reading its # cells as bits. for each tile, the code stores all eight orientations keyed by their (up, right, down, left) edge hashes, and two tiles are adjacent if they share any edge hash.

tiles with exactly two neighbours are corners, which is enough for part 1. to place the full image, reconstruct picks any corner, finds the orientation where it has both a right and a down neighbour, fills the first column by matching down edges and then each row by matching right edges. a comment notes this relies on no two tiles sharing an edge by accident.

part 2 strips the tile borders, stitches the image together, and slides the monster pattern (stored as a list of # offsets) over every orientation of the image, marking matches with O. the answer is the # count from the orientation with the fewest left over.

the trick

hash each edge as a bitmask and precompute all eight orientations, so assembling the image is just looking up the neighbour whose edge hash matches.

python
def hash_list(l):
    return sum(1 << i for i,v in enumerate(l) if v == "#")

def hash_tile(tile):
    up = hash_list(tile[0])
    down = hash_list(tile[-1])
    left = hash_list([tile[i][0] for i in range(len(tile))])
    right = hash_list([tile[i][-1] for i in range(len(tile))])
    return (up, right, down, left)