2 Commits

Author SHA1 Message Date
f0556c6afe Implement 2024 day 16 part 1 2024-12-16 08:58:42 +01:00
da7ee96b93 Slihghtly simplify 2024-12-16 08:33:02 +01:00
5 changed files with 120 additions and 22 deletions

View File

@@ -15,6 +15,20 @@ def parse_input(data: str) -> tuple[numpy.array, str]:
return grid_split, steps
def convert_dir(c: str) -> tuple[int, int]:
match c:
case "^":
return 0, -1
case ">":
return 1, 0
case "<":
return -1, 0
case "v":
return 0, 1
case other:
raise ValueError(f"Invalid movement: {other}")
class DayRunner(SeparateRunner):
@classmethod
def part1(cls, input: str) -> None:
@@ -24,17 +38,7 @@ class DayRunner(SeparateRunner):
x, y = x[0], y[0]
for c in steps:
match c:
case "^":
dx, dy = 0, -1
case ">":
dx, dy = 1, 0
case "<":
dx, dy = -1, 0
case "v":
dx, dy = 0, 1
case other:
raise ValueError(f"Invalid movement: {other}")
dx, dy = convert_dir(c)
match grid[y + dy, x + dx]:
case "#":
@@ -81,17 +85,7 @@ class DayRunner(SeparateRunner):
x, y = x[0], y[0]
for c in steps:
match c:
case "^":
dx, dy = 0, -1
case ">":
dx, dy = 1, 0
case "<":
dx, dy = -1, 0
case "v":
dx, dy = 0, 1
case other:
raise ValueError(f"Invalid movement: {other}")
dx, dy = convert_dir(c)
match grid[y + dy, x + dx]:
case "#":

View File

@@ -0,0 +1,56 @@
import heapq
import numpy
from . import SeparateRunner
TURNS = (
(-1, 1),
(1, -1),
)
class DayRunner(SeparateRunner):
@classmethod
def part1(cls, input: str) -> int:
grid = numpy.array([list(line) for line in input.strip().split("\n")])
y, x = numpy.where(grid == "S")
x, y = x[0], y[0]
todo = [(0, x, y, 1, 0)]
best = {
(x, y, 1, 0): 0,
}
def enqueue(dist, x, y, dx, dy):
if grid[y, x] == "#":
return
if (x, y, dx, dy) not in best or best[x, y, dx, dy] > dist:
best[x, y, dx, dy] = dist
heapq.heappush(todo, (dist, x, y, dx, dy))
while todo:
dist, x, y, dx, dy = heapq.heappop(todo)
if best[x, y, dx, dy] < dist:
continue
if grid[y, x] == "E":
return dist
enqueue(dist + 1, x + dx, y + dy, dx, dy)
enqueue(dist + 2001, x - dx, y - dy, dx, dy)
for tx, ty in TURNS:
ndx = dy * ty
ndy = dx * ty
enqueue(dist + 1001, x + ndx, y + ndy, ndx, ndy)
raise ValueError("Did not find path to exit")
@classmethod
def part2(cls, input: str) -> int:
pass

View File

@@ -0,0 +1,15 @@
###############
#.......#....E#
#.#.###.#.###.#
#.....#.#...#.#
#.###.#####.#.#
#.#.#.......#.#
#.#.#####.###.#
#...........#.#
###.#.#####.#.#
#...#.....#.#.#
#.#.#.###.#.#.#
#.....#...#.#.#
#.###.#.#.#.#.#
#S..#.....#...#
###############

View File

@@ -0,0 +1,17 @@
#################
#...#...#...#..E#
#.#.#.#.#.#.#.#.#
#.#.#.#...#...#.#
#.#.#.#.###.#.#.#
#...#.#.#.....#.#
#.#.#.#.#.#####.#
#.#...#.#.#.....#
#.#.#####.#.###.#
#.#.#.......#...#
#.#.###.#####.###
#.#.#...#.....#.#
#.#.#.#####.###.#
#.#.#.........#.#
#.#.#.#########.#
#S#.............#
#################

16
2024/tests/test_day16.py Normal file
View File

@@ -0,0 +1,16 @@
import pytest
from aoc.days.day16 import DayRunner
from . import get_data
@pytest.mark.parametrize(
"data,result",
[
(get_data(16, 1), 7036),
(get_data(16, 2), 11048),
],
)
def test_sample_part1(data: str, result: int) -> None:
assert DayRunner.part1(data) == result