You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 satır
2.6KB

  1. def render(graph, default='.'):
  2. xmin, *_, xmax = sorted(int(p.real) for p in graph)
  3. ymin, *_, ymax = sorted(int(p.imag) for p in graph)
  4. out = ''
  5. for y in range(ymin, ymax + 1):
  6. for x in range(xmin, xmax + 1):
  7. out += graph.get(complex(x, y), default)
  8. out += '\n'
  9. return out
  10. def connected_components(graph):
  11. groups = []
  12. while graph:
  13. seen = set()
  14. edge = {graph.pop()}
  15. while edge:
  16. seen |= edge
  17. edge = {pp + ss for pp in edge for ss in [1, -1, 1j, -1j] if pp + ss in graph if pp + ss not in seen}
  18. groups.append(seen)
  19. graph -= seen
  20. return groups
  21. def get_solid(walls):
  22. xmin, *_, xmax = sorted(int(p.real) for p in walls)
  23. ymin, *_, ymax = sorted(int(p.imag) for p in walls)
  24. mesh = {complex(x, y) for x in range(xmin, xmax + 1) for y in range(ymin, ymax + 1)}
  25. void = mesh - walls
  26. groups = connected_components(void)
  27. border = lambda p: p.real in {xmin, xmax} or p.imag in {ymin, ymax}
  28. inside = {p for g in groups if not any(border(p) for p in g) for p in g}
  29. solid = inside | walls
  30. return solid
  31. def solve1():
  32. pos = 0
  33. walls = {pos}
  34. for line in text.splitlines():
  35. d, n, _ = line.split()
  36. dirx = 1j ** 'RDLU'.index(d)
  37. goal = pos + dirx * int(n)
  38. while pos != goal:
  39. pos += dirx
  40. walls.add(pos)
  41. solid = get_solid(walls)
  42. print(len(solid))
  43. def solve2():
  44. points = {0}
  45. pos = 0
  46. for line in text.splitlines():
  47. _, _, rest = line.split()
  48. n, d = int(rest[1:-1][1:][:5], 16), 'RDLU'[int(rest[-2])]
  49. dirx = 1j ** 'RDLU'.index(d)
  50. pos += dirx * int(n)
  51. points.add(pos)
  52. b2s = {
  53. complex(bx, by) + dx + dy: 3 * complex(sx, sy) + dx + dy
  54. for sx, bx in enumerate(sorted({p.real for p in points}))
  55. for sy, by in enumerate(sorted({p.imag for p in points}))
  56. for dx in [-1, 0, 1] for dy in [-1j, 0, 1j]
  57. }
  58. s2b = {v: k for k, v in b2s.items()}
  59. pos, smallpos = 0, b2s[0]
  60. walls = {smallpos}
  61. for line in text.splitlines():
  62. d, n, rest = line.split()
  63. n, d = int(rest[1:-1][1:][:5], 16), 'RDLU'[int(rest[-2])]
  64. dirx = 1j ** 'RDLU'.index(d)
  65. pos += dirx * int(n)
  66. goal = b2s[pos]
  67. while smallpos != goal:
  68. smallpos += dirx
  69. walls.add(smallpos)
  70. solid = get_solid(walls)
  71. out = 0
  72. for smallpos in solid:
  73. c1, c2 = s2b[smallpos], s2b[smallpos + 1 + 1j]
  74. w, h = (c2 - c1).real, (c2 - c1).imag
  75. out += int(w * h)
  76. print(out)
  77. text = open(0).read()
  78. solve1()
  79. solve2()