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()