solution.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #!/usr/bin/python3
  2. import sys
  3. import re
  4. from dataclasses import dataclass
  5. import os
  6. @dataclass(frozen=True)
  7. class Pos:
  8. x: int
  9. y: int
  10. def walk(self, dpos, steps):
  11. return Pos(self.x + dpos.x * steps, self.y + dpos.y * steps)
  12. def add_x(self, x):
  13. return Pos(self.x + x, self.y)
  14. def add_y(self, y):
  15. return Pos(self.x, self.y + y)
  16. def minimize(self, pos):
  17. return Pos(min(self.x, pos.x), min(self.y, pos.y))
  18. def maximize(self, pos):
  19. return Pos(max(self.x, pos.x), max(self.y, pos.y))
  20. def grid_str(points, upperleft, lowerright):
  21. chars = [['#' if Pos(x, y) in points else ' ' for x in range(upperleft.x, lowerright.x + 1)] for y in range(upperleft.y, lowerright.y + 1)]
  22. return '\n'.join([''.join(line) for line in chars])
  23. def generate_directions(pos):
  24. yield pos.add_x(-1)
  25. yield pos.add_x(1)
  26. yield pos.add_y(-1)
  27. yield pos.add_y(1)
  28. def flood(boundary, upperleft, lowerright):
  29. count = 0
  30. start = Pos((upperleft.x + lowerright.x) // 2, (upperleft.y + lowerright.y) // 2)
  31. last = set()
  32. seen = set([start])
  33. considered = boundary.copy()
  34. #n = 0
  35. while last != seen:
  36. last = seen.copy()
  37. for p in last:
  38. for np in generate_directions(p):
  39. if np in considered:
  40. continue
  41. seen.add(np)
  42. considered.add(p)
  43. seen.remove(p)
  44. #n += 1
  45. #if n % 32 == 0:
  46. #n = 0
  47. #os.system('clear')
  48. #print(grid_str(considered, upperleft, lowerright))
  49. print(len(considered))
  50. def part12(swapped=False):
  51. print('part 1')
  52. corners = set()
  53. boundary = set()
  54. pos = Pos(0, 0)
  55. upperleft = Pos(0, 0)
  56. lowerright = Pos(0, 0)
  57. directions = { 'U': Pos(0, -1) , 'R': Pos(1, 0), 'D': Pos(0, 1), 'L': Pos(-1, 0) }
  58. for line in map(str.strip, sys.stdin):
  59. found = re.findall(r'([UDRL]) ([0-9]+) \(#([0-9a-f]+)\)', line)[0]
  60. if swapped:
  61. direction = {'0': 'R', '1': 'D', '2': 'L', '3': 'U'}[found[2][-1]]
  62. steps = int(found[2][:-1], 16)
  63. else:
  64. direction, steps = found[0], int(found[1])
  65. print(direction, steps)
  66. last = pos
  67. pos = pos.walk(directions[direction], steps)
  68. upperleft = upperleft.minimize(pos)
  69. lowerright = lowerright.maximize(pos)
  70. for x in range(min(last.x, pos.x), max(last.x, pos.x) + 1):
  71. for y in range(min(last.y, pos.y), max(last.y, pos.y) + 1):
  72. boundary.add(Pos(x, y))
  73. corners.add(pos)
  74. print(grid_str(boundary, upperleft, lowerright))
  75. flood(boundary, upperleft, lowerright)
  76. if sys.argv[1] in '1':
  77. part12()
  78. else:
  79. part12(swapped=True)