21_steps.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. #!/usr/bin/env python3
  2. import sys
  3. from collections import deque
  4. def bfs(grid):
  5. h = len(grid)
  6. w = len(grid[0])
  7. start = next((x, y) for y in range(h) for x in range(w) if grid[y][x] == 'S')
  8. visited = {start: 0}
  9. work = deque([(start, 0)])
  10. while work:
  11. (x, y), steps = work.popleft()
  12. for nb in ((x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)):
  13. nx, ny = nb
  14. if 0 <= nx < w and 0 <= ny < h:
  15. if grid[ny][nx] != '#' and nb not in visited:
  16. visited[nb] = steps + 1
  17. work.append((nb, steps + 1))
  18. return list(visited.values())
  19. def reachable_in_26501365_steps(min_dists):
  20. # https://github.com/villuna/aoc23/wiki/A-Geometric-solution-to-advent-of-code-2023,-day-21
  21. n = (26501365 - 131 // 2) // 131 # w = h = 131
  22. even = odd = even_corners = odd_corners = 0
  23. for dist in min_dists:
  24. is_odd = dist % 2
  25. even += 1 - is_odd
  26. odd += is_odd
  27. if dist > 65:
  28. even_corners += 1 - is_odd
  29. odd_corners += is_odd
  30. whole_squares = (n + 1) ** 2 * odd + n * n * even
  31. corners = (n + 1) * odd_corners + n * even_corners
  32. return whole_squares - corners
  33. min_dists = bfs([line.rstrip() for line in sys.stdin])
  34. print(sum(dist <= 64 and dist % 2 == 0 for dist in min_dists))
  35. print(reachable_in_26501365_steps(min_dists))