Implement day 13 solver

This commit is contained in:
2024-12-13 11:15:44 -08:00
parent 92b9f5ca01
commit 4cbd1c9aee

96
puzzles/13.py Normal file
View File

@@ -0,0 +1,96 @@
import re
from textwrap import dedent
from typing import Iterator, NamedTuple, override
from unittest import TestCase
from puzzles._solver import Solver
class ClawMachine(NamedTuple):
ax: int
ay: int
bx: int
by: int
px: int
py: int
a_spec_pattern = re.compile(r"Button A: X\+(\d+), Y\+(\d+)")
b_spec_pattern = re.compile(r"Button B: X\+(\d+), Y\+(\d+)")
p_spec_pattern = re.compile(r"Prize: X=(\d+), Y=(\d+)")
def solve_machine(m: ClawMachine) -> tuple[float, float]:
c = (m.px * m.by - m.py * m.bx) / (m.ax * m.by - m.ay * m.bx)
d = (m.px - m.ax * c) / m.bx
return c, d
class DayThirteenSolver(Solver):
machines: list[ClawMachine]
@override
def __init__(self, puzzle_input: str):
self.machines = []
for spec in puzzle_input.strip().split("\n\n"):
a_spec, b_spec, p_spec = spec.split("\n")
ax, ay = map(int, a_spec_pattern.match(a_spec).groups())
bx, by = map(int, b_spec_pattern.match(b_spec).groups())
px, py = map(int, p_spec_pattern.match(p_spec).groups())
self.machines.append(ClawMachine(ax, ay, bx, by, px, py))
@override
def solve_p1(self) -> int:
return sum(
int(c * 3 + d)
for c, d in map(solve_machine, self.machines)
if c.is_integer() and d.is_integer()
)
@override
def solve_p2(self) -> int:
corrected_machines = map(
lambda m: ClawMachine(
m.ax,
m.ay,
m.bx,
m.by,
m.px + 10000000000000,
m.py + 10000000000000,
),
self.machines,
)
return sum(
int(c * 3 + d)
for c, d in map(solve_machine, corrected_machines)
if c.is_integer() and d.is_integer()
)
class TestDayThirteenSolver(TestCase):
def test(self):
solver = DayThirteenSolver(
dedent(
"""
Button A: X+94, Y+34
Button B: X+22, Y+67
Prize: X=8400, Y=5400
Button A: X+26, Y+66
Button B: X+67, Y+21
Prize: X=12748, Y=12176
Button A: X+17, Y+86
Button B: X+84, Y+37
Prize: X=7870, Y=6450
Button A: X+69, Y+23
Button B: X+27, Y+71
Prize: X=18641, Y=10279
"""
)
)
self.assertEqual(
solver.machines[0],
ClawMachine(94, 34, 22, 67, 8400, 5400),
)
self.assertEqual(solver.solve_p1(), 480)