Skip to content

Commit 4a7305d

Browse files
committed
Implement 2024 day 14
1 parent c8ab67d commit 4a7305d

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

2024/src/aoc/days/day14.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import itertools
2+
import math
3+
import re
4+
5+
import numpy
6+
7+
from . import SeparateRunner
8+
9+
NASTY_REGEX = re.compile(r"p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)")
10+
11+
12+
class DayRunner(SeparateRunner):
13+
@classmethod
14+
def part1(cls, input: str, width: int = 101, height: int = 103) -> int:
15+
points = NASTY_REGEX.findall(input)
16+
17+
quadrants = [0] * 4
18+
19+
x_middle = width // 2
20+
y_middle = height // 2
21+
22+
for point in points:
23+
x, y, dx, dy = map(int, point)
24+
25+
rx = ((x + dx * 100) % width + width) % width
26+
ry = ((y + dy * 100) % height + height) % height
27+
28+
match rx:
29+
case _ if rx < x_middle:
30+
xq = 0
31+
case _ if rx > x_middle:
32+
xq = 1
33+
case _:
34+
continue
35+
36+
match ry:
37+
case _ if ry < y_middle:
38+
yq = 0
39+
case _ if ry > y_middle:
40+
yq = 1
41+
case _:
42+
continue
43+
44+
quadrants[2 * yq + xq] += 1
45+
46+
return math.prod(quadrants)
47+
48+
@classmethod
49+
def part2(cls, input: str) -> int:
50+
width = 101
51+
height = 103
52+
53+
points = NASTY_REGEX.findall(input)
54+
points_fast = numpy.array([list(map(int, point)) for point in points])
55+
56+
positions = points_fast[:, 0:2]
57+
velocities = points_fast[:, 2:]
58+
59+
target = len(velocities)
60+
61+
# Assumption: when the easter egg happens, no robots overlap, and this is the
62+
# only time this happens. There is no reason this should work but it does.
63+
mod_base = numpy.array([width, height])
64+
for i in itertools.count(1):
65+
positions += velocities
66+
67+
positions %= mod_base
68+
positions += mod_base
69+
positions %= mod_base
70+
71+
if len(numpy.unique(positions, axis=0)) == target:
72+
# TODO: print the Christmas tree, Eric prepared it for us so nicely
73+
return i

2024/tests/samples/14.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
p=0,4 v=3,-3
2+
p=6,3 v=-1,-3
3+
p=10,3 v=-1,2
4+
p=2,0 v=2,-1
5+
p=0,0 v=1,3
6+
p=3,0 v=-2,-2
7+
p=7,6 v=-1,-3
8+
p=3,0 v=-1,-2
9+
p=9,3 v=2,3
10+
p=7,3 v=-1,2
11+
p=2,4 v=2,-3
12+
p=9,5 v=-3,-3

2024/tests/test_day14.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from aoc.days.day14 import DayRunner
2+
3+
from . import get_data
4+
5+
6+
def test_sample_part1() -> None:
7+
assert DayRunner.part1(get_data(14), width=11, height=7) == 12

0 commit comments

Comments
 (0)