23_spread.py 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. #!/usr/bin/env python3
  2. import sys
  3. from collections import Counter, deque
  4. def add(a, b):
  5. xa, ya = a
  6. xb, yb = b
  7. return xa + xb, ya + yb
  8. def spread(elves):
  9. directions = deque([
  10. ((-1, -1), (0, -1), (1, -1)),
  11. ((-1, 1), (0, 1), (1, 1)),
  12. ((-1, -1), (-1, 0), (-1, 1)),
  13. ((1, -1), (1, 0), (1, 1)),
  14. ])
  15. while True:
  16. proposals = {}
  17. for xy in elves:
  18. accessible = [all(add(xy, d) not in elves for d in deltas)
  19. for deltas in directions]
  20. proposals[xy] = xy if sum(accessible) in (0, 4) \
  21. else add(xy, directions[accessible.index(True)][1])
  22. if all(src == dst for src, dst in proposals.items()):
  23. break
  24. counts = Counter(proposals.values())
  25. elves = {b if counts[b] == 1 else a for a, b in proposals.items()}
  26. yield elves
  27. directions.append(directions.popleft())
  28. def progress(elves):
  29. minx = min(x for x, y in elves)
  30. maxx = max(x for x, y in elves)
  31. miny = min(y for x, y in elves)
  32. maxy = max(y for x, y in elves)
  33. return (maxx - minx + 1) * (maxy - miny + 1) - len(elves)
  34. elves = {(x, y)
  35. for y, line in enumerate(sys.stdin)
  36. for x, c in enumerate(line.strip())
  37. if c == '#'}
  38. seq = spread(elves)
  39. for i in range(10): elves = next(seq)
  40. print(progress(elves))
  41. for i, elves in enumerate(seq): pass
  42. print(i + 12)