78 lines
2.1 KiB
Python
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)
|