Implement day 13 solver
This commit is contained in:
96
puzzles/13.py
Normal file
96
puzzles/13.py
Normal 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)
|
Reference in New Issue
Block a user