day 16
the floor will be lava
approach
move uses a match statement to say which direction(s) a beam leaves a tile in: mirrors turn it clockwise or counter-clockwise depending on the mirror and the axis, and splitters hit side-on return two directions. beams follows beams with a stack and records, for each cell, the directions it has been crossed in, so a beam that repeats a cell and direction stops.
part 1 is the number of cells reached from the top-left heading right. part 2 tries every edge cell heading inward and takes the maximum.
the trick
remember (cell, direction) pairs so looping beams stop on their own.
python
while s:
r, c, dr, dc = s.pop()
for ndr, ndc in move(dr, dc, grid[r][c]):
if not 0 <= (nr := r + ndr) < len(grid):
continue
if not 0 <= (nc := c + ndc) < len(grid[0]):
continue
if (nr, nc) in d and (ndr, ndc) in d[(nr, nc)]:
continue
s.append((nr, nc, ndr, ndc))
d[(nr, nc)].append((ndr, ndc))