advent_of_code_2023/Day21/python/solution1.py
2023-12-21 22:02:54 +01:00

85 lines
2.8 KiB
Python

from collections import deque
def read_grid(file_path):
"""Reads the grid from a file and returns it along with the starting position."""
with open(file_path, "r") as file:
grid = [list(line.strip()) for line in file.readlines()]
start = None
for i, row in enumerate(grid):
for j, cell in enumerate(row):
if cell == "S":
start = (i, j)
break
if start:
break
assert start is not None, "Starting position 'S' not found in the grid."
print(f"Grid loaded from {file_path}. Start position: {start}")
return grid, start
def bfs(grid, start):
"""Performs BFS on the grid to track the minimum steps to each plot."""
printf("Start BFS")
steps = 64
queue = deque([(start[0], start[1], 0)])
distances = {}
while queue:
x, y, step = queue.popleft()
if step > steps:
continue # Skip plots that are more than 64 steps away
if step == steps:
distances[(x, y)] = step # Only consider plots at exactly 64 steps
else:
for dx, dy in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
nx, ny = x + dx, y + dy
if (
0 <= nx < len(grid)
and 0 <= ny < len(grid[0])
and grid[nx][ny] == "."
and (nx, ny) not in distances
):
queue.append((nx, ny, step + 1))
print(f"BFS completed. Number of plots visited: {len(distances)}")
return distances
def count_reachable_plots(distances, steps):
"""Counts the number of plots reachable in exactly the given number of steps."""
count = sum(1 for d in distances.values() if d == steps)
print(f"Number of plots reachable in exactly {steps} steps: {count}")
return count
def run_test():
"""Runs the algorithm with the test data and asserts the result."""
print("Running test...")
test_grid, test_start = read_grid("../test.txt")
distances = bfs(test_grid, test_start)
test_result = count_reachable_plots(distances, 64)
assert test_result == 16, f"Test failed: Expected 16, got {test_result}"
print("Test passed successfully.")
def main():
"""Main function to run the algorithm with the actual puzzle data."""
try:
run_test()
grid, start = read_grid("../input.txt")
distances = bfs(grid, start)
result = count_reachable_plots(distances, 64)
print(f"Final Result: Number of reachable plots in exactly 64 steps: {result}")
except AssertionError as ae:
print(f"Assertion Error: {ae}")
except FileNotFoundError as fnfe:
print(f"File not found error: {fnfe}")
except Exception as e:
print(f"Unexpected error: {e}")
if __name__ == "__main__":
main()