You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

50 lines
1.2KB

  1. import collections
  2. import math
  3. import re
  4. import sys
  5. text = sys.stdin.read()
  6. to_get = {}
  7. for line in text.strip().splitlines():
  8. for i, (qty, name) in enumerate(re.findall(r'(\d+) ([A-Z]+)', line)[::-1]):
  9. if i == 0:
  10. output = name
  11. to_get[output] = {output: -int(qty)}
  12. else:
  13. to_get[output][name] = int(qty)
  14. def fuel_to_ore(wanted):
  15. required = collections.Counter({'FUEL': wanted})
  16. pending = required.copy()
  17. while pending:
  18. pending = {k: v for k, v in required.items() if k != 'ORE' and v > 0}
  19. for out, out_qty in pending.items():
  20. min_qty = -to_get[out][out]
  21. n_times = math.ceil(out_qty / min_qty)
  22. required.update({k: v * n_times for k, v in to_get[out].items()})
  23. return required['ORE']
  24. print(fuel_to_ore(1))
  25. def bsearch(fn, goal, lo, hi):
  26. while hi - lo > 1:
  27. mid = lo + (hi - lo) // 2
  28. if goal < fn(mid):
  29. lo, hi = lo, mid
  30. else:
  31. lo, hi = mid, hi
  32. # check
  33. a, b = fn(lo), fn(hi)
  34. assert a <= goal, 'lower bound too high'
  35. assert goal <= b, 'higher bound too low'
  36. return lo
  37. print(bsearch(fuel_to_ore, 1E12, 1, 10_000_000))