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.

57 line
1.5KB

  1. import re
  2. order = ['ore', 'clay', 'obsidian', 'geode']
  3. blueprints = []
  4. for ln in open(0).read().split('Blueprint')[1:]:
  5. costs = []
  6. for ln in [re.findall(r'(\d+) (\w+)', part) for part in ln.split('Each')[1:]]:
  7. cost = [0, 0, 0, 0]
  8. for qty, kind in ln:
  9. cost[order.index(kind)] = int(qty)
  10. costs.append(tuple(cost))
  11. blueprints.append(tuple(costs))
  12. def evolve(bots, ores, choice, blueprint, lims):
  13. if all(o >= b for o, b in zip(ores, blueprint[3])) and choice != 3:
  14. return
  15. if choice != -1:
  16. ores = tuple(a - b for a, b in zip(ores, blueprint[choice]))
  17. if any(a < 0 for a in ores):
  18. return
  19. ores = tuple(a + b for a, b in zip(ores, bots))
  20. if choice != -1:
  21. bots = tuple(a + (choice == i) for i, a in enumerate(bots))
  22. if any(q > l for q, l in zip(bots, lims[:-1])):
  23. return
  24. yield (bots, ores)
  25. def solve(blueprint):
  26. states = {((1, 0, 0, 0), (0, 0, 0, 0))}
  27. lims = list(map(max, zip(*blueprint)))
  28. for _ in range(24):
  29. print('.', end='')
  30. states = {new for old in states for choice in [-1, 0, 1, 2, 3] for new in evolve(*old, choice, blueprint, lims)}
  31. best = max(s[0][-1] for s in states)
  32. states = {s for s in states if best - s[0][-1] < 2}
  33. print()
  34. return max(states, key=lambda state: state[-1][-1])
  35. ans1 = 0
  36. ans2 = 1
  37. for idx, bp in enumerate(blueprints, 1):
  38. state = solve(bp)
  39. ans1 += idx * state[-1][-1]
  40. ans2 *= state[-1][-1]
  41. print(idx, ans1, state[-1][-1])
  42. print(ans1)
  43. print(ans2)