Files
Dmitry Fedotov 135f574e7a add day 13 part 2
2025-01-04 13:53:30 +03:00

131 lines
3.0 KiB
Python

import sys
sys.path.append('../aoclib')
from aoclib import Input
import re
class Button:
def __init__(self, cost, x, y):
self.cost = cost
self.x = x
self.y = y
def __str__(self):
return f'x: {self.x}, y: {self.y}, cost: {self.cost}'
class Prize:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f'x: {self.x}, y: {self.y}'
class Machine:
def __init__(self, a, b: Button, p: Prize):
self.a = a
self.b = b
self.prize = p
def __str__(self):
s = ''
s += 'B_A: ' + self.a.__str__() + '\n'
s += 'B_B: ' + self.b.__str__() + '\n'
s += 'Prize: ' + self.prize.__str__() + '\n'
return s
def parse_input(lines: list[str]) -> list[Machine]:
lst = list()
brx = re.compile(r'X\+(\d+), Y\+(\d+)')
prx = re.compile(r'X=(\d+), Y=(\d+)')
b_a = None
b_b = None
m = None
for l in lines:
if l.startswith('Button A'):
m = brx.search(l)
b_a = Button(3, int(m.group(1)), int(m.group(2)))
if l.startswith('Button B'):
m = brx.search(l)
b_b = Button(1, int(m.group(1)), int(m.group(2)))
if l.startswith('Prize'):
m = prx.search(l)
p = Prize(int(m.group(1)), int(m.group(2)))
machine = Machine(b_a, b_b, p)
lst.append(machine)
return lst
def _solve1(m: Machine) -> int:
# why not brute-force? :)
max_a = min(m.prize.x // m.a.x, m.prize.y // m.a.y)+1
max_b = min(m.prize.x // m.b.x, m.prize.y // m.b.y)+1
costs = []
for _a in range(max_a):
for _b in range(max_b):
x, y, cost = m.a.x*_a + m.b.x*_b, m.a.y*_a + m.b.y*_b, m.a.cost*_a + m.b.cost*_b
if x == m.prize.x and y == m.prize.y:
costs.append(cost)
if not costs:
return None
return min(costs)
def _solve2(m: Machine) -> int:
cost = None
times_b = (m.prize.y * m.a.x - m.prize.x * m.a.y) / (m.b.y * m.a.x - m.b.x * m.a.y)
times_a = (m.prize.x - m.b.x * times_b) / m.a.x
#if 100 >= times_a >= 0 and 100 >= times_b >= 0 and times_a.is_integer() and times_b.is_integer():
if times_a.is_integer() and times_b.is_integer():
cost = int(times_a) * 3 + int(times_b)
return cost
def solve1(lines: list[str]):
machines = parse_input(lines)
cost = 0
for m in machines:
c = _solve1(m)
if not c:
continue
cost += c
return cost
def solve2(lines: list[str]):
machines = parse_input(lines)
cost = 0
for m in machines:
m.prize.x += 10000000000000
m.prize.y += 10000000000000
c = _solve2(m)
if not c:
continue
cost += c
return cost
if __name__ == '__main__':
#lines = Input('input_test.txt').lines()
lines = Input('input.txt').lines()
#part 1
print('part 1:', solve1(lines)) # 27157
#part 2
print('part 2:', solve2(lines)) # 104015411578548