Implement 2024 day 14

This commit is contained in:
2024-12-14 09:07:45 +01:00
parent c8ab67d145
commit 4a7305d7eb
3 changed files with 92 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
import itertools
import math
import re
import numpy
from . import SeparateRunner
NASTY_REGEX = re.compile(r"p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)")
class DayRunner(SeparateRunner):
@classmethod
def part1(cls, input: str, width: int = 101, height: int = 103) -> int:
points = NASTY_REGEX.findall(input)
quadrants = [0] * 4
x_middle = width // 2
y_middle = height // 2
for point in points:
x, y, dx, dy = map(int, point)
rx = ((x + dx * 100) % width + width) % width
ry = ((y + dy * 100) % height + height) % height
match rx:
case _ if rx < x_middle:
xq = 0
case _ if rx > x_middle:
xq = 1
case _:
continue
match ry:
case _ if ry < y_middle:
yq = 0
case _ if ry > y_middle:
yq = 1
case _:
continue
quadrants[2 * yq + xq] += 1
return math.prod(quadrants)
@classmethod
def part2(cls, input: str) -> int:
width = 101
height = 103
points = NASTY_REGEX.findall(input)
points_fast = numpy.array([list(map(int, point)) for point in points])
positions = points_fast[:, 0:2]
velocities = points_fast[:, 2:]
target = len(velocities)
# Assumption: when the easter egg happens, no robots overlap, and this is the
# only time this happens. There is no reason this should work but it does.
mod_base = numpy.array([width, height])
for i in itertools.count(1):
positions += velocities
positions %= mod_base
positions += mod_base
positions %= mod_base
if len(numpy.unique(positions, axis=0)) == target:
# TODO: print the Christmas tree, Eric prepared it for us so nicely
return i

12
2024/tests/samples/14.txt Normal file
View File

@@ -0,0 +1,12 @@
p=0,4 v=3,-3
p=6,3 v=-1,-3
p=10,3 v=-1,2
p=2,0 v=2,-1
p=0,0 v=1,3
p=3,0 v=-2,-2
p=7,6 v=-1,-3
p=3,0 v=-1,-2
p=9,3 v=2,3
p=7,3 v=-1,2
p=2,4 v=2,-3
p=9,5 v=-3,-3

7
2024/tests/test_day14.py Normal file
View File

@@ -0,0 +1,7 @@
from aoc.days.day14 import DayRunner
from . import get_data
def test_sample_part1() -> None:
assert DayRunner.part1(get_data(14), width=11, height=7) == 12