Advertisement
hhoppe

Advent of code 2023 day 17

Dec 17th, 2023 (edited)
829
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 1.77 KB | None | 0 0
  1. def day17(s, *, part2=False, visualize=False, rep=2):  # Dijkstra search over "larger" state node.
  2.   grid = np.array([list(line) for line in s.splitlines()], int)
  3.  
  4.   state = 0, 0, 0, 1, 0  # (y, x, dy, dx, dn).
  5.   target_yx = grid.shape[0] - 1, grid.shape[1] - 1
  6.   distances = collections.defaultdict(lambda: 10**9)
  7.   distances[state] = 0
  8.   priority_queue = [(0, state)]
  9.   prev = {}
  10.  
  11.   while priority_queue:
  12.     _, state = heapq.heappop(priority_queue)
  13.     y, x, dy, dx, dn = state
  14.     distance = distances[state]
  15.     if (y, x) == target_yx and (not part2 or dn >= 4):
  16.       break
  17.     for dy2, dx2, same_dir in [(-dx, dy, False), (dy, dx, True), (dx, -dy, False)]:
  18.       dn2 = dn + 1 if same_dir else 1
  19.       if (dn2 <= 10 and (dn == 0 or dn >= 4 or same_dir)) if part2 else (dn2 <= 3):
  20.         y2, x2 = y + dy2, x + dx2
  21.         if 0 <= y2 < grid.shape[0] and 0 <= x2 < grid.shape[1]:
  22.           state2 = y2, x2, dy2, dx2, dn2
  23.           distance2 = distance + grid[y2, x2]
  24.           if distance2 < distances[state2]:
  25.             distances[state2] = distance2
  26.             prev[state2] = state
  27.             heapq.heappush(priority_queue, (distance2, state2))
  28.   else:
  29.     raise ValueError('No solution found.')
  30.  
  31.   if visualize:
  32.     path = [state[:2]]
  33.     while state[:2] != (0, 0):
  34.       state = prev[state]
  35.       path.append(state[:2])
  36.     assert sum(grid[yx] for yx in path[:-1]) == distance
  37.  
  38.     image = media.to_rgb(grid * 0.9, cmap='gray')  # Or cmap='bwr'.
  39.     image2 = image.copy()
  40.     image2[tuple(np.array(path).T)] = 255, 255, 0
  41.     image = image.repeat(rep, 0).repeat(rep, 1)
  42.     image2 = image2.repeat(rep, 0).repeat(rep, 1)
  43.     title = 'day17b' if part2 else 'day17a'
  44.     media.show_video([image, image2], codec='gif', fps=1, title=title)
  45.  
  46.   return distance
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement