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.

62 lines
1.4KB

  1. import collections
  2. import itertools
  3. import re
  4. text = open(0).read()
  5. graph = collections.defaultdict(dict)
  6. rates = {}
  7. for ln in text.splitlines():
  8. source, rate, *leads_to = re.findall(r'[A-Z]{2}|\d+', ln)
  9. for out in leads_to:
  10. graph[out][source] = 1
  11. graph[source][out] = 1
  12. rates[source] = int(rate)
  13. costs = {}
  14. for k in graph:
  15. edge = set(graph[k])
  16. seen = set()
  17. cost = 1
  18. while True:
  19. for e in edge:
  20. if (k, e) in costs:
  21. costs[k, e] = min(costs[k, e], cost)
  22. else:
  23. costs[k, e] = cost
  24. cost += 1
  25. edge = {n for e in edge for n in graph[e]} - seen
  26. if seen == set(graph):
  27. break
  28. seen |= edge
  29. def for_one(combo, lim):
  30. tt = 0
  31. bob = [0]
  32. for a, b in zip(('AA',) + combo, combo):
  33. tt = costs[a, b]
  34. for _ in range(tt):
  35. bob.append(bob[-1])
  36. bob.append(bob[-1] + rates[b])
  37. pending = max(0, lim - len(bob))
  38. bob += [bob[-1]] * pending
  39. return sum(bob[:lim])
  40. def generate_combos(pending, left, carry=('AA',)):
  41. if left < 0 or not pending:
  42. yield carry[1:]
  43. else:
  44. for k in pending:
  45. yield from generate_combos(pending - {k}, left - costs[carry[-1], k], carry + (k,))
  46. combos = generate_combos({k for k, v in rates.items() if v}, lim=30)
  47. best = max(combos, key=for_one)
  48. print(best)
  49. print(for_one(best))
  50. # 2615