Advertisement
hhoppe

Advent of code 2024 day 6 jit fast 7 ms

Dec 7th, 2024
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.05 KB | None | 0 0
  1. # For Part 2, (1) precompute a jump map and (2) march along the path and look for
  2. # a possible loop only when encountering an empty space for the first time.
  3. @numba.njit
  4. def day6_jit(grid: np.ndarray, y0: int, x0: int, part2: bool) -> int:
  5.   big = max(grid.shape)
  6.   dydx_from_dir = [(0, -1), (-1, 0), (0, 1), (1, 0)]
  7.   jump_steps = np.empty((4, *grid.shape), np.int32)
  8.   if part2:
  9.     for dir in range(4):
  10.       rotated_grid = np.rot90(grid, k=dir)
  11.       rotated_jump_steps = np.rot90(jump_steps[dir], k=dir)
  12.       for y, row in enumerate(rotated_grid):
  13.         num = big
  14.         for x, ch in enumerate(row):
  15.           num = -1 if ch == '#' else num + 1
  16.           rotated_jump_steps[y, x] = num
  17.  
  18.   def adding_obstacle_would_create_loop(y, x, dir, obstacle_y, obstacle_x):
  19.     visited = set()
  20.     while True:
  21.       dy, dx = dydx_from_dir[dir]
  22.       steps = jump_steps[dir, y, x]
  23.       if obstacle_y == y:
  24.         d = obstacle_x - x
  25.         if d * dx > 0:
  26.           steps = min(steps, abs(d) - 1)
  27.       if obstacle_x == x:
  28.         d = obstacle_y - y
  29.         if d * dy > 0:
  30.           steps = min(steps, abs(d) - 1)
  31.       if steps >= big:
  32.         return False
  33.       y, x = y + dy * steps, x + dx * steps
  34.       state = y, x, dir
  35.       if state in visited:
  36.         return True
  37.       visited.add(state)
  38.       dir = (dir + 1) % 4  # Rotate clockwise.
  39.  
  40.   y, x, dir = y0, x0, 1
  41.   count = 0
  42.   while True:
  43.     if not part2 and grid[y, x] != 'X':
  44.       grid[y, x] = 'X'
  45.       count += 1
  46.     dy, dx = dydx_from_dir[dir]
  47.     y1, x1 = y + dy, x + dx
  48.     if not (0 <= y1 < grid.shape[0] and 0 <= x1 < grid.shape[1]):
  49.       break
  50.     if grid[y1, x1] == '#':
  51.       dir = (dir + 1) % 4  # Rotate clockwise.
  52.     else:
  53.       if part2 and grid[y1, x1] == '.':
  54.         grid[y1, x1] = 'Y'
  55.         count += adding_obstacle_would_create_loop(y, x, dir, y1, x1)
  56.       y, x = y1, x1
  57.  
  58.   return count
  59.  
  60.  
  61. def day6(s, part2=False):
  62.   grid = np.array([list(line) for line in s.splitlines()])
  63.   ((y0, x0),) = np.argwhere(grid == '^')
  64.   return day6_jit(grid, y0, x0, part2)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement