mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 12:50:32 +01:00
Implement 2024 day 14
This commit is contained in:
73
2024/src/aoc/days/day14.py
Normal file
73
2024/src/aoc/days/day14.py
Normal 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
12
2024/tests/samples/14.txt
Normal 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
7
2024/tests/test_day14.py
Normal 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
|
||||
Reference in New Issue
Block a user