Skip to content

Commit

Permalink
Merge pull request #107 from ephemient/py/day14
Browse files Browse the repository at this point in the history
Day 14: Restroom Redoubt
  • Loading branch information
ephemient authored Dec 17, 2024
2 parents 2b5c069 + 799276a commit 09fe89f
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Development occurs in language-specific directories:
|[Day11.hs](hs/src/Day11.hs)|[Day11.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day11.kt)|[day11.py](py/aoc2024/day11.py)|[day11.rs](rs/src/day11.rs)|
|[Day12.hs](hs/src/Day12.hs)|[Day12.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day12.kt)|[day12.py](py/aoc2024/day12.py)|[day12.rs](rs/src/day12.rs)|
|[Day13.hs](hs/src/Day13.hs)|[Day13.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day13.kt)|[day13.py](py/aoc2024/day13.py)|[day13.rs](rs/src/day13.rs)|
|[Day14.hs](hs/src/Day14.hs)|[Day14.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day14.kt)|||
|[Day14.hs](hs/src/Day14.hs)|[Day14.kt](kt/aoc2024-lib/src/commonMain/kotlin/com/github/ephemient/aoc2024/Day14.kt)|[day14.py](py/aoc2024/day14.py)||
|[Day15.hs](hs/src/Day15.hs)||||
|[Day16.hs](hs/src/Day16.hs)||||
|[Day17.hs](hs/src/Day17.hs)||||
10 changes: 9 additions & 1 deletion py/aoc2024/day13.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@

_pattern = re.compile(r"\d+")


def _parse(data: str) -> Generator[tuple[int, int, int, int, int, int]]:
return zip(*((int(match.group(0)) for match in _pattern.finditer(data)),) * 6)


def _solve(ax: int, ay: int, bx: int, by: int, x: int, y: int) -> int:
anumerator = x * by - y * bx
adenominator = ax * by - bx * ay
Expand All @@ -39,14 +41,20 @@ def _solve(ax: int, ay: int, bx: int, by: int, x: int, y: int) -> int:
b = bnumerator // bdenominator
return 3 * a + b


def part1(data: str) -> int:
"""
>>> part1(SAMPLE_INPUT)
480
"""
return sum(_solve(ax, ay, bx, by, x, y) for ax, ay, bx, by, x, y in _parse(data))


def part2(data: str) -> int:
return sum(_solve(ax, ay, bx, by, x + 10000000000000, y + 10000000000000) for ax, ay, bx, by, x, y in _parse(data))
return sum(
_solve(ax, ay, bx, by, x + 10000000000000, y + 10000000000000)
for ax, ay, bx, by, x, y in _parse(data)
)


parts = (part1, part2)
84 changes: 84 additions & 0 deletions py/aoc2024/day14.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""
Day 14: Restroom Redoubt
"""

from collections import namedtuple
from functools import partial
from itertools import zip_longest
from math import lcm
from typing import Generator

SAMPLE_INPUT = """
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
"""

WIDTH, HEIGHT = 101, 103


class _Robot(namedtuple("Robot", ("x0", "y0", "vx", "vy"))):
def __getitem__(
self, t: int, width: int = WIDTH, height: int = HEIGHT
) -> tuple[int, int]:
return (self.x0 + t * self.vx) % width, (self.y0 + t * self.vy) % height


def _parse(data: str) -> Generator[_Robot]:
for line in filter(None, data.splitlines()):
p, v = line.split(maxsplit=1)
p = p[p.index("=") + 1 :]
v = v[v.index("=") + 1 :]
yield _Robot(
int(p[: p.index(",")]),
int(p[p.index(",") + 1 :]),
int(v[: v.index(",")]),
int(v[v.index(",") + 1 :]),
)


def part1(data: str, width: int = WIDTH, height: int = HEIGHT) -> int:
"""
>>> part1(SAMPLE_INPUT, width=11, height=7)
12
"""
midpoint_x, midpoint_y = width // 2, height // 2
q1, q2, q3, q4 = 0, 0, 0, 0
for robot in _parse(data):
x, y = robot.__getitem__(100, width=width, height=height)
if x > midpoint_x and y > midpoint_y:
q1 += 1
if x < midpoint_x and y > midpoint_y:
q2 += 1
if x > midpoint_x and y < midpoint_y:
q3 += 1
if x < midpoint_x and y < midpoint_y:
q4 += 1
return q1 * q2 * q3 * q4


def _part2_key(robots: tuple[_Robot], t: int) -> int:
positions = sorted((robot[t] for robot in robots))
line, max_line = 1, 0
for (x, y), next in zip_longest(positions, positions[1:]):
if (x, y + 1) == next:
line += 1
else:
line, max_line = 1, max(line, max_line)
return -max_line, t


def part2(data: str) -> int:
return min(range(lcm(WIDTH * HEIGHT)), key=partial(_part2_key, tuple(_parse(data))))


parts = (part1, part2)
1 change: 1 addition & 0 deletions py/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ day10 = "aoc2024.day10:parts"
day11 = "aoc2024.day11:parts"
day12 = "aoc2024.day12:parts"
day13 = "aoc2024.day13:parts"
day14 = "aoc2024.day14:parts"

[build-system]
requires = ["poetry-core"]
Expand Down

0 comments on commit 09fe89f

Please sign in to comment.