mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 12:50:32 +01:00
Implement 2024 day 12
This commit is contained in:
101
2024/src/aoc/days/day12.py
Normal file
101
2024/src/aoc/days/day12.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import numpy
|
||||
|
||||
from . import CombinedRunner
|
||||
|
||||
DIRECTIONS = [
|
||||
(-1, 0),
|
||||
(1, 0),
|
||||
(0, -1),
|
||||
(0, 1),
|
||||
]
|
||||
|
||||
|
||||
class DayRunner(CombinedRunner):
|
||||
@classmethod
|
||||
def run_both(cls, input: str) -> tuple[int, int]:
|
||||
grid = numpy.array(list(map(list, input.strip().split("\n"))))
|
||||
|
||||
score = 0
|
||||
score2 = 0
|
||||
|
||||
for y in range(grid.shape[0]):
|
||||
for x in range(grid.shape[1]):
|
||||
if grid[y, x] == ".":
|
||||
continue
|
||||
|
||||
search = grid[y, x]
|
||||
grid[y, x] = "."
|
||||
|
||||
todo = [(y, x)]
|
||||
cluster = {(y, x)}
|
||||
|
||||
def enqueue(y, x):
|
||||
if grid[y, x] == search:
|
||||
grid[y, x] = "."
|
||||
todo.append((y, x))
|
||||
cluster.add((y, x))
|
||||
|
||||
while todo:
|
||||
cy, cx = todo.pop()
|
||||
|
||||
if cx > 0:
|
||||
enqueue(cy, cx - 1)
|
||||
if cy > 0:
|
||||
enqueue(cy - 1, cx)
|
||||
|
||||
if cx < grid.shape[1] - 1:
|
||||
enqueue(cy, cx + 1)
|
||||
if cy < grid.shape[0] - 1:
|
||||
enqueue(cy + 1, cx)
|
||||
|
||||
side_length = sum(
|
||||
sum((cy + dy, cx + dx) not in cluster for dy, dx in DIRECTIONS)
|
||||
for cy, cx in cluster
|
||||
)
|
||||
|
||||
corners = 0
|
||||
|
||||
for cy, cx in cluster:
|
||||
# Outer corners
|
||||
corners += (cy, cx - 1) not in cluster and (
|
||||
cy - 1,
|
||||
cx,
|
||||
) not in cluster
|
||||
corners += (cy, cx + 1) not in cluster and (
|
||||
cy - 1,
|
||||
cx,
|
||||
) not in cluster
|
||||
corners += (cy, cx - 1) not in cluster and (
|
||||
cy + 1,
|
||||
cx,
|
||||
) not in cluster
|
||||
corners += (cy, cx + 1) not in cluster and (
|
||||
cy + 1,
|
||||
cx,
|
||||
) not in cluster
|
||||
# Inner corners
|
||||
corners += (
|
||||
(cy, cx - 1) in cluster
|
||||
and (cy - 1, cx) in cluster
|
||||
and (cy - 1, cx - 1) not in cluster
|
||||
)
|
||||
corners += (
|
||||
(cy, cx + 1) in cluster
|
||||
and (cy - 1, cx) in cluster
|
||||
and (cy - 1, cx + 1) not in cluster
|
||||
)
|
||||
corners += (
|
||||
(cy, cx - 1) in cluster
|
||||
and (cy + 1, cx) in cluster
|
||||
and (cy + 1, cx - 1) not in cluster
|
||||
)
|
||||
corners += (
|
||||
(cy, cx + 1) in cluster
|
||||
and (cy + 1, cx) in cluster
|
||||
and (cy + 1, cx + 1) not in cluster
|
||||
)
|
||||
|
||||
score += side_length * len(cluster)
|
||||
score2 += corners * len(cluster)
|
||||
|
||||
return (score, score2)
|
||||
4
2024/tests/samples/12.1.txt
Normal file
4
2024/tests/samples/12.1.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
AAAA
|
||||
BBCD
|
||||
BBCC
|
||||
EEEC
|
||||
5
2024/tests/samples/12.2.txt
Normal file
5
2024/tests/samples/12.2.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
OOOOO
|
||||
OXOXO
|
||||
OOOOO
|
||||
OXOXO
|
||||
OOOOO
|
||||
10
2024/tests/samples/12.3.txt
Normal file
10
2024/tests/samples/12.3.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
RRRRIICCFF
|
||||
RRRRIICCCF
|
||||
VVRRRCCFFF
|
||||
VVRCCCJFFF
|
||||
VVVVCJJCFE
|
||||
VVIVCCJJEE
|
||||
VVIIICJJEE
|
||||
MIIIIIJJEE
|
||||
MIIISIJEEE
|
||||
MMMISSJEEE
|
||||
21
2024/tests/test_day12.py
Normal file
21
2024/tests/test_day12.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import pytest
|
||||
|
||||
from aoc.days.day12 import DayRunner
|
||||
|
||||
from . import get_data
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"data,result",
|
||||
[(get_data(12, 1), 140), (get_data(12, 2), 772), (get_data(12, 3), 1930)],
|
||||
)
|
||||
def test_sample_part1(data: str, result: int) -> None:
|
||||
assert DayRunner.part1(data) == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"data,result",
|
||||
[(get_data(12, 1), 80), (get_data(12, 2), 436), (get_data(12, 3), 1206)],
|
||||
)
|
||||
def test_sample_part2(data: str, result: int) -> None:
|
||||
assert DayRunner.part2(data) == result
|
||||
Reference in New Issue
Block a user