84 lines
2.3 KiB
Python
84 lines
2.3 KiB
Python
from lib import get_data
|
|
from math import ceil
|
|
|
|
|
|
def ore_for_fuel(fuel_n, reactions_store):
|
|
ore_qty = 0
|
|
required = [(fuel_n, "FUEL")]
|
|
store = {}
|
|
while required:
|
|
required_qty, required_code = required.pop()
|
|
if required_code == "ORE":
|
|
ore_qty += required_qty
|
|
continue
|
|
|
|
if required_code in store:
|
|
if store[required_code] == required_qty:
|
|
del store[required_code]
|
|
continue
|
|
elif store[required_code] > required_qty:
|
|
store[required_code] -= required_qty
|
|
continue
|
|
elif store[required_code] < required_qty:
|
|
required_qty -= store[required_code]
|
|
del store[required_code]
|
|
|
|
inputs, output = reactions_store[required_code]
|
|
output_qty, output_code = output
|
|
assert required_code == output_code
|
|
|
|
# how often must this process be executed
|
|
n = ceil(required_qty / output_qty)
|
|
|
|
leftover_output_qty = n * output_qty - required_qty
|
|
assert leftover_output_qty >= 0
|
|
|
|
if leftover_output_qty > 0:
|
|
store[output_code] = leftover_output_qty
|
|
|
|
for qty_input, input_code in inputs:
|
|
required.append((qty_input * n, input_code))
|
|
return ore_qty
|
|
|
|
|
|
def part_1(data):
|
|
reactions = []
|
|
to_get = {}
|
|
for line in data.splitlines():
|
|
left, right = line.split(" => ")
|
|
inputs = left.split(", ")
|
|
inputs = [(int(i.split()[0]), i.split()[1]) for i in inputs]
|
|
output = (int(right.split()[0]), right.split()[1])
|
|
reactions.append((inputs, output))
|
|
if output[1] in to_get:
|
|
assert False
|
|
else:
|
|
to_get[output[1]] = (inputs, output)
|
|
|
|
ore_qty = ore_for_fuel(1, to_get)
|
|
print(ore_qty)
|
|
|
|
min_fuel, max_fuel = 1, 100_000_000
|
|
target = 10**12 # trillion
|
|
while max_fuel - min_fuel > 1:
|
|
half_fuel = min_fuel + (max_fuel - min_fuel) // 2
|
|
ore_qty = ore_for_fuel(half_fuel, to_get)
|
|
if ore_qty < target:
|
|
min_fuel = half_fuel
|
|
elif ore_qty > target:
|
|
max_fuel = half_fuel
|
|
else:
|
|
min_fuel = half_fuel
|
|
max_fuel = half_fuel
|
|
|
|
print(min_fuel)
|
|
|
|
|
|
def main():
|
|
data = get_data(__file__)
|
|
part_1(data)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|