Advertisement
globmont

AoC 21-15

Dec 15th, 2021
722
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.48 KB | None | 0 0
  1. from typing import List, Tuple
  2. import heapq
  3. import numpy as np
  4.  
  5. file = "inputs/2021/15/data.txt"
  6. with open(file, "r") as f:
  7.     grid = f.read().split("\n")
  8.     grid = np.array([np.array(list(map(int, line))) for line in grid])
  9.    
  10. GRID_SHAPE = (len(grid), len(grid[0]))
  11.  
  12. def get_neighbors(node: Tuple[int, int], grid_shape: Tuple[int, int]) -> List[Tuple[int, int]]:
  13.     row = node[0]
  14.     col = node[1]
  15.    
  16.     return [
  17.         (row + row_delta, col + col_delta)
  18.         for row_delta in range(-1, 2)
  19.         for col_delta in range(-1, 2)
  20.         if ((row_delta == 0) ^ (col_delta == 0))
  21.         and 0 <= row + row_delta < grid_shape[0]
  22.         and 0 <= col + col_delta < grid_shape[1]
  23.     ]
  24.  
  25. def manhattan_heuristic(a: Tuple[int, int], b: Tuple[int, int]) -> int:
  26.     return abs(b[0] - a[0]) + abs(b[1] - a[1])
  27.  
  28. def a_star(start: Tuple[int, int], target: Tuple[int, int], grid: List[List[int]]):
  29.     unexplored_nodes = []
  30.     heapq.heappush(unexplored_nodes, (0, start))
  31.    
  32.     current_node = None
  33.     prev = {start: None}
  34.     g_scores = {start: 0}
  35.    
  36.     while current_node != target:
  37.         current_node = heapq.heappop(unexplored_nodes)[1]
  38.         for neighbor in get_neighbors(current_node, grid.shape):
  39.             new_g_score = g_scores[current_node] + grid[neighbor[0]][neighbor[1]]
  40.             if new_g_score < g_scores.get(neighbor, 1e10):
  41.                 # Better path to neighbor found
  42.                 prev[neighbor] = current_node
  43.                 g_scores[neighbor] = new_g_score
  44.                 heapq.heappush(unexplored_nodes, (g_scores[neighbor] + manhattan_heuristic(neighbor, target), neighbor))
  45.                
  46.    
  47.     path = [target]
  48.     while path[0] != start:
  49.         path.insert(0, prev[path[0]])
  50.    
  51.     # print(" -> ".join([str(node) for node in path]))
  52.     return g_scores[target]
  53.  
  54. part_1 = a_star(
  55.     start=(0, 0),
  56.     target=(GRID_SHAPE[0] - 1, GRID_SHAPE[1] - 1),
  57.     grid=grid
  58. )
  59. print(f"Part 1: {part_1:,d}")
  60.  
  61. # Generate bigger grid
  62. full_grid = []
  63. for rep_col_idx in range(5):
  64.     rep_row = []
  65.     for rep_row_idx in range(5):
  66.         new_subgrid = grid + rep_row_idx + rep_col_idx
  67.         new_subgrid = np.where(new_subgrid > 9, new_subgrid + 1, new_subgrid) % 10
  68.         rep_row.append(new_subgrid)
  69.     full_grid.append(np.hstack(rep_row))    
  70. full_grid = np.vstack(full_grid)
  71.  
  72. part_2 = a_star(
  73.     start=(0, 0),
  74.     target=(full_grid.shape[0] - 1, full_grid.shape[1] - 1),
  75.     grid=full_grid
  76. )
  77. print(f"Part 2: {part_2:,d}")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement