Skip to content
advent of code 2023

day 17

clumsy crucible

approach

both parts run dijkstra with a heap whose states are position, last direction and how many steps have been taken in that direction. reversing is not allowed, and states are marked as seen when pushed.

part 1 caps a straight run at 3 steps. part 2 needs at least 4 steps before turning (or stopping at the end) and at most 10; the start has an infinite run length so it can set off in any direction. part 2 also records each state's parent, used by commented-out code that drew the path.

the trick

put the direction and run length in the dijkstra state, so the movement rules are just filters on neighbours.

python
for nr, nc, dr, dc in neighbors(grid, r, c):
    nn = cn + 1 if (pdr,pdc) == (dr,dc) else 1
    if dr == -pdr and dc == -pdc:
        continue
    if (cn < 4 and nn == 1) or nn > 10:
        continue
    if (nr, nc, dr, dc, nn) in seen:
        continue

    # can use the same object if it is too slow
    #seen.add((nr, nc, dr, dc, nn))
    seen[(nr, nc, dr, dc, nn)] = (r, c, pdr, pdc, cn)
    heappush(h, (w + grid[nr][nc], nr, nc, dr, dc, nn))