aoc2019/day14.py
2021-12-27 17:31:33 +01:00

78 lines
2.1 KiB
Python

from math import ceil
from tools.aoc import AOCDay
from typing import Any
class Day(AOCDay):
inputs = [
[
(165, "test_input14_1_0"),
(13312, "test_input14_1_1"),
(180697, "test_input14_1_2"),
(2210736, "test_input14_1_3"),
(720484, "input14")
],
[
(82892753, "test_input14_1_1"),
(5586022, "test_input14_1_2"),
(460664, "test_input14_1_3"),
(1993284, "input14")
]
]
conversions = {}
rest = {}
def buildConversionDict(self):
self.rest = {}
conv_input = self.getInputAsArraySplit(" => ")
for need_str, give_str in conv_input:
tar_amt, tar = give_str.split()
self.conversions[tar] = {'amount': int(tar_amt), 'need': {}}
for r in need_str.split(", "):
a, n = r.split()
self.conversions[tar]['need'][n] = int(a)
def getOreNeed(self, what: str, amount: int) -> int:
amount -= self.rest.get(what, 0)
if amount < 0:
self.rest[what] = abs(amount)
return 0
if what == 'ORE':
return amount
ore_need = 0
count = ceil(amount / self.conversions[what]['amount'])
for need, need_amt in self.conversions[what]['need'].items():
ore_need += self.getOreNeed(need, need_amt * count)
self.rest[what] = self.conversions[what]['amount'] * count - amount
return ore_need
def part1(self) -> Any:
self.buildConversionDict()
return self.getOreNeed('FUEL', 1)
def part2(self) -> Any:
self.buildConversionDict()
got_ore = 1_000_000_000_000
min_fuel = got_ore // self.getOreNeed('FUEL', 1)
factor = 100_000
while factor >= 1:
ore_need = self.getOreNeed('FUEL', min_fuel + factor)
if ore_need > got_ore:
factor //= 10
else:
min_fuel += factor
return min_fuel if self.getOreNeed('FUEL', min_fuel) < got_ore else min_fuel - 1
if __name__ == '__main__':
day = Day(2019, 14)
day.run(verbose=True)