No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

hace 5 años
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import collections
  2. import itertools
  3. import sys
  4. from toolkit import read_image, render
  5. def read_in(text):
  6. grid = read_image(text)
  7. elements = {v: k for k, v in grid.items()}
  8. keys = frozenset(k for k in elements if 'a' <= k <= 'z')
  9. return dict(grid), elements, keys
  10. def move(pos):
  11. for ori in [1, -1, 1j, -1j]:
  12. if grid[pos + ori] != '#':
  13. yield pos + ori
  14. def shortest_path(start, end, move):
  15. seen = {}
  16. edge = {start: None}
  17. while end not in seen:
  18. edge = {
  19. adj: pos
  20. for pos in edge
  21. for adj in move(pos)
  22. if adj not in seen
  23. }
  24. seen.update(edge)
  25. if not edge:
  26. raise RuntimeError('No path found')
  27. path = []
  28. while end != start:
  29. path.append(end)
  30. end = seen[end]
  31. return path
  32. def trim(states):
  33. groups = collections.defaultdict(list)
  34. for state in states:
  35. tips = frozenset(seq[-1] for seq in state)
  36. bulk = frozenset(' '.join(state))
  37. groups[bulk, tips].append(state)
  38. return [min(groups[k], key=calc_total) for k in groups]
  39. def precalc_moves(entrances):
  40. requirements = collections.defaultdict(dict)
  41. lengths = collections.defaultdict(dict)
  42. for a, b in itertools.permutations(keys.union(entrances), 2):
  43. try:
  44. path = shortest_path(elements[a], elements[b], move)
  45. except RuntimeError:
  46. continue
  47. lengths[a][b] = len(path)
  48. requirements[a][b] = {
  49. e.lower()
  50. for e, v in elements.items()
  51. if e.isupper()
  52. and v in path
  53. }
  54. return requirements, lengths
  55. def calc_total(state):
  56. return sum(sum(
  57. lengths[a][b]
  58. for a, b in zip(s, s[1:])
  59. if {a, b} < set(lengths)
  60. ) for s in state)
  61. def mod_grid(text):
  62. grid, elements, keys = read_in(text)
  63. pos = elements['@']
  64. grid[pos] = '#'
  65. for char, ori in zip('*&^@', [1, -1, 1j, -1j]):
  66. grid[pos + ori] = '#'
  67. grid[pos + ori + ori * 1j] = char
  68. return render(grid, {k: k for k in grid.values()})
  69. def solve(text):
  70. global grid, elements, keys, lengths
  71. grid, elements, keys = read_in(text)
  72. stacks = {k for k in elements if not k.isalnum()} - {'#', '.'}
  73. requirements, lengths = precalc_moves(stacks)
  74. states = [stacks]
  75. for _ in range(len(keys)):
  76. states = trim(
  77. state - {seq} | {seq + b}
  78. for state in states
  79. for seq in state
  80. for b, reqs in requirements[seq[-1]].items()
  81. if b not in seq and reqs.issubset(''.join(state))
  82. )
  83. final = min(states, key=calc_total)
  84. print(' '.join(sorted(final)))
  85. print(calc_total(final))
  86. text = sys.stdin.read()
  87. text = '''
  88. #############
  89. #g#f.D#..h#l#
  90. #F###e#E###.#
  91. #dCba...BcIJ#
  92. #####.@.#####
  93. #nK.L...G...#
  94. #M###N#H###.#
  95. #o#m..#i#jk.#
  96. #############
  97. '''
  98. solve(text)
  99. text = mod_grid(text)
  100. solve(text)