From 3e709cc86394b86b2207bf256c5b09a8a2cc4eef Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Tue, 10 Dec 2024 09:38:31 +0100 Subject: [PATCH] Implement 2024 day 10 --- 2024/src/aoc/days/day10.py | 85 ++++++++++++++++++++++++++++++++++++++ 2024/tests/samples/10.txt | 8 ++++ 2024/tests/test_day10.py | 7 ++++ 3 files changed, 100 insertions(+) create mode 100644 2024/src/aoc/days/day10.py create mode 100644 2024/tests/samples/10.txt create mode 100644 2024/tests/test_day10.py diff --git a/2024/src/aoc/days/day10.py b/2024/src/aoc/days/day10.py new file mode 100644 index 0000000..9a76c4d --- /dev/null +++ b/2024/src/aoc/days/day10.py @@ -0,0 +1,85 @@ +from collections import deque + +import numpy + +from . import SeparateRunner + + +class DayRunner(SeparateRunner): + @classmethod + def part1(cls, input: str) -> int: + grid = numpy.array( + [[int(v) for v in line] for line in input.strip().split("\n")] + ) + + width, height = grid.shape + + start_x, start_y = numpy.nonzero(grid == 0) + + todo = [] + + reachable = 0 + + for sx, sy in zip(start_x, start_y): + todo.append((sx, sy)) + ways = numpy.zeros_like(grid, dtype=bool) + + def enqueue(x: int, y: int, val: int) -> None: + if grid[x, y] == val + 1: + if not ways[x, y]: + todo.append((x, y)) + ways[x, y] += True + + while todo: + x, y = todo.pop() + val = grid[x, y] + if val == 9: + reachable += 1 + continue + + if x > 0: + enqueue(x - 1, y, val) + if y > 0: + enqueue(x, y - 1, val) + if x < width - 1: + enqueue(x + 1, y, val) + if y < height - 1: + enqueue(x, y + 1, val) + + return reachable + + @classmethod + def part2(cls, input: str) -> int: + grid = numpy.array( + [[int(v) for v in line] for line in input.strip().split("\n")] + ) + ways = numpy.zeros_like(grid) + + width, height = grid.shape + + start_x, start_y = numpy.nonzero(grid == 9) + ways[grid == 9] = 1 + + todo = deque((x, y) for x, y in zip(start_x, start_y)) + + def enqueue(x: int, y: int, val: int, cur: int) -> None: + if grid[x, y] == val - 1: + if ways[x, y] == 0: + todo.append((x, y)) + ways[x, y] += cur + + while todo: + x, y = todo.popleft() + val = grid[x, y] + cur = ways[x, y] + + if x > 0: + enqueue(x - 1, y, val, cur) + if y > 0: + enqueue(x, y - 1, val, cur) + if x < width - 1: + enqueue(x + 1, y, val, cur) + if y < height - 1: + enqueue(x, y + 1, val, cur) + + return ways[grid == 0].sum() diff --git a/2024/tests/samples/10.txt b/2024/tests/samples/10.txt new file mode 100644 index 0000000..cada9b3 --- /dev/null +++ b/2024/tests/samples/10.txt @@ -0,0 +1,8 @@ +89010123 +78121874 +87430965 +96549874 +45678903 +32019012 +01329801 +10456732 diff --git a/2024/tests/test_day10.py b/2024/tests/test_day10.py new file mode 100644 index 0000000..68fd47f --- /dev/null +++ b/2024/tests/test_day10.py @@ -0,0 +1,7 @@ +from aoc.days.day10 import DayRunner + +from . import get_data + + +def test_sample_part1() -> None: + assert DayRunner.part1(get_data(10)) == 36