23.py 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. from queue import deque
  2. from itertools import product
  3. lines = [line.strip() for line in open("23.input")]
  4. elves = set()
  5. for y, line in enumerate(lines):
  6. for x, c in enumerate(line):
  7. if c == "#":
  8. elves.add((x, y))
  9. SURROUND = set(product([-1, 0, 1], repeat=2)) - set([(0, 0)])
  10. DIRS = deque([(0, -1), (0, 1), (-1, 0), (1, 0)])
  11. def add(a, b):
  12. return (a[0] + b[0], a[1] + b[1])
  13. def show(elves):
  14. xs = [a[0] for a in elves]
  15. ys = [a[1] for a in elves]
  16. for y in range(min(ys), max(ys)+1):
  17. for x in range(min(xs), max(xs)+1):
  18. if (x, y) in elves:
  19. print("#", end="")
  20. else:
  21. print(".", end="")
  22. print("")
  23. print("-" * 20)
  24. print("Empty space:", (max(ys) + 1 - min(ys)) * (max(xs) + 1 - min(xs)) - len(elves))
  25. for i in range(1000000):
  26. proposals = {}
  27. for elf in elves:
  28. for d in SURROUND:
  29. if add(elf, d) in elves:
  30. break
  31. else:
  32. proposals[elf] = [elf]
  33. continue
  34. for d in DIRS:
  35. zero_axis = 0 if d[0] == 0 else 1
  36. for dz in [-1, 0, 1]:
  37. xd = list(d)
  38. xd[zero_axis] = dz
  39. if add(elf, xd) in elves:
  40. break
  41. else:
  42. prop = add(d, elf)
  43. total = proposals.get(prop, [])
  44. proposals[prop] = total + [elf]
  45. break
  46. else:
  47. proposals[elf] = [elf]
  48. continue
  49. new_elves = set()
  50. for pos, candidates in proposals.items():
  51. if len(candidates) > 1:
  52. for c in candidates:
  53. new_elves.add(c)
  54. else:
  55. new_elves.add(pos)
  56. if i == 9:
  57. print("Part 1:")
  58. show(new_elves)
  59. assert len(elves) == len(new_elves)
  60. if new_elves == elves:
  61. print("Part 2:", i + 1)
  62. break
  63. head = DIRS.popleft()
  64. DIRS.append(head)
  65. elves = new_elves