-
Notifications
You must be signed in to change notification settings - Fork 0
/
14.py
86 lines (72 loc) · 2.49 KB
/
14.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from lib import *
input = read_input(2019, 14)
def ceil(a, b):
return a // b + (a % b > 0)
reactions = {}
for line in input.splitlines():
reactants, product = line.split(" => ")
reactants = [reactant.split() for reactant in reactants.split(", ")]
amount, product = product.split()
assert product not in reactions
reactions[product] = ([(reactant, int(amount)) for amount, reactant in reactants], int(amount))
ore_used = 0
chemicals = {}
Q = [("FUEL", 1)]
while Q:
chemical, prod_amount = Q.pop(0)
if chemical == "ORE":
ore_used += prod_amount
continue
chem_amount = chemicals.get(chemical, 0)
reaction_amount = prod_amount - chem_amount
if reaction_amount <= 0:
chemicals[chemical] -= prod_amount
continue
reactants, product_amount = reactions[chemical]
reaction_count = ceil(reaction_amount, product_amount)
for reactant, amount in reactants:
Q.append((reactant, amount * reaction_count))
chemicals[chemical] = chem_amount + reaction_count * product_amount - prod_amount
print(ore_used)
def ceil(a, b):
return a // b + (a % b > 0)
reactions = {}
for line in input.splitlines():
reactants, product = line.split(" => ")
reactants = [reactant.split() for reactant in reactants.split(", ")]
amount, product = product.split()
assert product not in reactions
reactions[product] = ([(reactant, int(amount)) for amount, reactant in reactants], int(amount))
def get_ore_used(amount):
ore_used = 0
chemicals = {}
Q = [("FUEL", amount)]
while Q:
chemical, prod_amount = Q.pop(0)
if chemical == "ORE":
ore_used += prod_amount
continue
chem_amount = chemicals.get(chemical, 0)
reaction_amount = prod_amount - chem_amount
if reaction_amount <= 0:
chemicals[chemical] -= prod_amount
continue
reactants, product_amount = reactions[chemical]
reaction_count = ceil(reaction_amount, product_amount)
for reactant, amount in reactants:
Q.append((reactant, amount * reaction_count))
chemicals[chemical] = chem_amount + reaction_count * product_amount - prod_amount
return ore_used
LIMIT = 1000000000000
low = 0
high = LIMIT
while low < high:
guess = (low + high) // 2
used = get_ore_used(guess)
if used <= LIMIT:
if get_ore_used(guess + 1) > LIMIT:
print(guess)
break
low = guess
elif used > LIMIT:
high = guess