This commit is contained in:
@@ -1,7 +1,79 @@
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Iterator
|
||||
|
||||
import parse # pyright: ignore[reportMissingTypeStubs]
|
||||
|
||||
from ..base import BaseSolver
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Machine:
|
||||
prize: tuple[int, int]
|
||||
button_a: tuple[int, int]
|
||||
button_b: tuple[int, int]
|
||||
|
||||
|
||||
def read_machine(block: str) -> Machine:
|
||||
ba = parse.parse( # type: ignore
|
||||
"""Button A: X{bax:d}, Y{bay:d}
|
||||
Button B: X{bbx:d}, Y{bby:d}
|
||||
Prize: X={px:d}, Y={py:d}""",
|
||||
block,
|
||||
)
|
||||
return Machine(
|
||||
prize=(ba["px"], ba["py"]), # type: ignore
|
||||
button_a=(ba["bax"], ba["bay"]), # type: ignore
|
||||
button_b=(ba["bbx"], ba["bby"]), # type: ignore
|
||||
)
|
||||
|
||||
|
||||
def diophantine(a: int, b: int, c: int) -> tuple[int, int]:
|
||||
q, r = divmod(a, b)
|
||||
if r == 0:
|
||||
return (0, c // b)
|
||||
else:
|
||||
u, v = diophantine(b, r, c)
|
||||
return (v, u - q * v)
|
||||
|
||||
|
||||
def solve(machine: Machine) -> int:
|
||||
(ax, ay), (bx, by), (px, py) = machine.button_a, machine.button_b, machine.prize
|
||||
dx, dy = math.gcd(ax, bx), math.gcd(ay, by)
|
||||
|
||||
if px % dx != 0 or py % dy != 0:
|
||||
return 0
|
||||
|
||||
xa, xb = diophantine(ax, bx, px)
|
||||
ya, yb = diophantine(ay, by, py)
|
||||
|
||||
# expr (x): xa - kx * bx / dx, xb + kx * ax / dx
|
||||
# expr (y): ya - ky * by / dy, yb + ky * ay / dy
|
||||
|
||||
num = ay * (ya - xa) + by * (yb - xb)
|
||||
den = (ax * by - ay * bx) // dx
|
||||
|
||||
if num % den != 0:
|
||||
return 0
|
||||
|
||||
kx = num // den
|
||||
pa, pb = xa - kx * bx // dx, xb + kx * ax // dx
|
||||
return 3 * pa + pb
|
||||
|
||||
|
||||
class Solver(BaseSolver):
|
||||
def solve(self, input: str) -> Iterator[Any]: ...
|
||||
def solve(self, input: str) -> Iterator[Any]:
|
||||
machines = [read_machine(block) for block in input.split("\n\n")]
|
||||
|
||||
yield sum(map(solve, machines))
|
||||
|
||||
shift = 10000000000000
|
||||
machines = [
|
||||
Machine(
|
||||
prize=(shift + m.prize[0], shift + m.prize[1]),
|
||||
button_a=m.button_a,
|
||||
button_b=m.button_b,
|
||||
)
|
||||
for m in machines
|
||||
]
|
||||
yield sum(map(solve, machines))
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
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
|
||||
|
Reference in New Issue
Block a user