Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

67 lines
1.9KB

  1. import itertools
  2. import sys
  3. from toolkit import read_image, shortest_path
  4. def move(pos):
  5. for ori in [1, -1, 1j, -1j]:
  6. adj = pos + ori
  7. if adj in grid:
  8. yield adj
  9. if adj in duals:
  10. yield from move(duals[adj])
  11. def move_with_depth(state):
  12. pos, level = state
  13. for ori in [1, -1, 1j, -1j]:
  14. adj = pos + ori
  15. if adj in grid:
  16. yield adj, level
  17. if adj in duals:
  18. name = grid[adj]
  19. if adj in inner:
  20. yield from move_with_depth((duals[adj], level + 1))
  21. elif (level > 0) and (name not in {'AA', 'ZZ'}):
  22. yield from move_with_depth((duals[adj], level - 1))
  23. # base
  24. text = sys.stdin.read()
  25. grid = {pos: val for pos, val in read_image(text).items() if val not in ' #'}
  26. for pos, val in grid.copy().items():
  27. if val.isupper():
  28. for im in [1, 1j]:
  29. A, B, C = [pos - im, pos, pos + im]
  30. seq = ''.join(grid.get(p, ' ') for p in [A, B, C])
  31. if seq.endswith('.'):
  32. grid[B] = grid.pop(A) + grid.pop(B)
  33. if seq.startswith('.'):
  34. grid[B] = grid.pop(B) + grid.pop(C)
  35. elements = {v: k for k, v in grid.items()}
  36. # matrix
  37. duals = {}
  38. portals = {pos for pos, cell in grid.items() if cell.isupper()}
  39. for pA, pB in itertools.combinations(portals, 2):
  40. if grid[pA] == grid[pB]:
  41. duals[pA] = pB
  42. duals[pB] = pA
  43. # part1
  44. start, end = elements['AA'], elements['ZZ']
  45. path = shortest_path(start, end, move)
  46. print(len(path) - 3)
  47. # categorize portals
  48. _, *xmid, _ = sorted({p.real for p in portals})
  49. _, *ymid, _ = sorted({p.imag for p in portals})
  50. inner = {pos for pos in portals if pos.real in xmid and pos.imag in ymid}
  51. outer = set(portals) - inner
  52. # part2
  53. start, end = (elements['AA'], 0), (elements['ZZ'], 0)
  54. path = shortest_path(start, end, move_with_depth)
  55. print(len(path) - 3)