Skip to content

Commit

Permalink
Implement 2024 day 18
Browse files Browse the repository at this point in the history
  • Loading branch information
bertptrs committed Dec 18, 2024
1 parent 4a8b9f9 commit caa2c9b
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
70 changes: 70 additions & 0 deletions 2024/src/aoc/days/day18.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from collections import deque

from . import SeparateRunner


def parse_input(data: str) -> list[tuple[int, int]]:
return [tuple(map(int, line.split(","))) for line in data.strip().split("\n")]


def find_exit(fallen: set[tuple[int, int]], width: int, height: int) -> int | None:
todo = deque([(0, 0, 0)])

best = {(0, 0): 0}

def enqueue(dist: int, x: int, y: int):
# print(f"trying {x},{y}")
if (x, y) in fallen:
return

if (x, y) not in best or best[x, y] > dist:
best[x, y] = dist
todo.append((dist, x, y))

while todo:
dist, x, y = todo.popleft()
# print(x, y)

if x == width - 1 and y == height - 1:
return dist

if x > 0:
enqueue(dist + 1, x - 1, y)

if x + 1 < width:
enqueue(dist + 1, x + 1, y)

if y > 0:
enqueue(dist + 1, x, y - 1)

if y + 1 < height:
enqueue(dist + 1, x, y + 1)


class DayRunner(SeparateRunner):
@classmethod
def part1(
cls, input: str, width: int = 71, height: int = 71, limit: int = 1024
) -> int:
falling = parse_input(input)

return find_exit(set(falling[:limit]), width, height)

@classmethod
def part2(cls, input: str, width: int = 71, height: int = 71) -> str:
falling = parse_input(input)

lower = 0
upper = len(falling)

while lower < upper:
mid = lower + (upper - lower) // 2

if find_exit(set(falling[:mid]), width, height) is not None:
lower = mid + 1
else:
upper = mid

first_blocker = falling[lower - 1]

return f"{first_blocker[0]},{first_blocker[1]}"
25 changes: 25 additions & 0 deletions 2024/tests/samples/18.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
5,4
4,2
4,5
3,0
2,1
6,3
2,4
1,5
0,6
3,3
2,6
5,1
1,2
5,5
2,5
6,5
1,4
0,4
6,4
1,1
6,1
1,0
0,5
1,6
2,0
11 changes: 11 additions & 0 deletions 2024/tests/test_day18.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from aoc.days.day18 import DayRunner

from . import get_data


def test_sample_part1() -> None:
assert DayRunner.part1(get_data(18), width=7, height=7, limit=12) == 22


def test_sample_part2() -> None:
assert DayRunner.part2(get_data(18), width=7, height=7) == "6,1"

0 comments on commit caa2c9b

Please sign in to comment.