from misc.helper import verify_answer
= "../inputs/example_day_18.txt"
example_input_file = "../inputs/day_18.txt" input_file
Day 18
We have fallen into RAM of the big North Pole computer. Read the whole story on the official Day 17 of Advent of Code 2024 website.
Here’s a ChatGPT negotiated illustration of the setup:
Part 1: Escape the falling bits
Another grid problem! We are in a 2D grid where we need to figure out which positions of the grid are free from the falling bytes.
from pathlib import Path
import numpy as np
def parse_input(input, grid_size=7, n_bytes=12):
if Path(input).exists():
with open(input) as file:
input = file.read()
input = input.strip().split("\n")
= np.zeros((grid_size, grid_size), dtype=int)
grid = [(int(y), int(x)) for row in input for x, y in [row.split(",")]]
coord
if n_bytes > len(coord):
raise ValueError("n_bytes is larger than the number of coordinates")
if (
max(coord, key=lambda x: x[0])[0] >= grid_size
or max(coord, key=lambda x: x[1])[1] >= grid_size
):raise ValueError("Coordinates are out of bounds of the grid")
tuple(zip(*coord[:n_bytes]))] = 1
grid[return grid
parse_input(example_input_file)
def print_grid_as_str(grid):
# print 0 as ., 1 as # and 2 as O
= {0: ".", 1: "#", 2: "O"}
match_dict print("\n".join("".join(match_dict[elem] for elem in row) for row in grid))
print_grid_as_str(parse_input(example_input_file))
...#...
..#..#.
....#..
...#..#
..#..#.
.#..#..
#.#....
Our task is to find the shortest path in the grid from the top left corner to the bottom right corner. We can only move up, down, left, or right, and we can’t move diagonally. We can only move to a position if it is free from the falling bytes. And then we need to report the number of steps we need to take to reach the bottom right corner.
from collections import deque
def find_shortest_path(grid):
= grid.shape
n, m = (0, 0)
start = (n - 1, m - 1)
end
def bfs(grid, start, end):
= deque([(start, [start])])
queue = set()
visited
while queue:
= queue.popleft()
node, path if node == end:
return path
if node in visited:
continue
visited.add(node)= node
x, y
for dx, dy in (
1, 0),
(-1, 0),
(0, 1),
(0, -1),
(
):= x + dx, y + dy
new_x, new_y if (
0 <= new_x < n
and 0 <= new_y < m
and grid[new_x, new_y] != 1
):= (new_x, new_y)
next_node if next_node not in visited:
+ [next_node]))
queue.append((next_node, path
return None
return bfs(grid, start, end)
def part_one(input, grid_size=7, n_bytes=12):
= parse_input(input, grid_size=grid_size, n_bytes=n_bytes)
grid = find_shortest_path(grid)
path return len(path) - 1
22) verify_answer(part_one, example_input_file,
✔️ That's right! The answer is 22.
%time part_one(input_file, grid_size=71, n_bytes=1024)
CPU times: user 8.45 ms, sys: 1.14 ms, total: 9.59 ms
Wall time: 9.91 ms
290
That’s the right answer! You are one gold star ⭐ closer to finding the Chief Historian.
Part 2: When there is no escape!
Now we need to figure out at what point there is no escape. I’m going to try the simplest approach with just gradually reading in the new bytes and checking if there is a path from the top left corner to the bottom right corner.
def check_if_path_exist(grid):
= grid.shape
n, m = (0, 0)
start = (n - 1, m - 1)
end
def bfs(grid, start, end):
= deque([start])
queue = set()
visited while queue:
= queue.popleft()
node if node == end:
return True
if node in visited:
continue
visited.add(node)= node
x, y
for dx, dy in (
1, 0),
(-1, 0),
(0, 1),
(0, -1),
(
):= x + dx, y + dy
new_x, new_y if (
0 <= new_x < n
and 0 <= new_y < m
and grid[new_x, new_y] != 1
):= (new_x, new_y)
next_node if next_node not in visited:
queue.append(next_node)
return None
return bfs(grid, start, end)
def part_two(input, grid_size=7, first_n_bytes=12):
= parse_input(input, grid_size=grid_size, n_bytes=first_n_bytes)
grid if Path(input).exists():
with open(input, "r") as file:
= file.readlines()
coords else:
= input.strip().split("\n")
coords = len(coords)
n_lines = first_n_bytes + 1
new_byte while new_byte < n_lines:
= coords[new_byte].strip()
coord_str = [(y, x) for x, y in [map(int, coord_str.split(","))]][0]
coord
= 1
grid[coord] if check_if_path_exist(grid):
+= 1
new_byte else:
return coord_str
"6,1") verify_answer(part_two, example_input_file,
✔️ That's right! The answer is 6,1.
%time part_two(input_file, grid_size=71, first_n_bytes=1024)
CPU times: user 3.62 s, sys: 14.7 ms, total: 3.64 s
Wall time: 3.67 s
'64,54'
That’s the right answer! You are one gold star ⭐ closer to finding the Chief Historian.