advent_of_code_2023/Day10/python/solution1.py

120 lines
4.0 KiB
Python
Raw Normal View History

2023-12-10 15:01:04 +00:00
def parse_grid(file_path):
2023-12-11 08:42:32 +00:00
"""Parses the grid from a file and returns the graph and starting position."""
print(f"Parsing grid from file: {file_path}")
grid = {}
start = None
2023-12-10 15:01:04 +00:00
try:
2023-12-12 16:36:28 +00:00
with open(file_path, "r") as file:
2023-12-11 08:42:32 +00:00
for y, line in enumerate(file.read().splitlines()):
for x, char in enumerate(line):
match char:
case "|":
grid[(y, x)] = {(y - 1, x), (y + 1, x)}
case "-":
grid[(y, x)] = {(y, x - 1), (y, x + 1)}
case "L":
grid[(y, x)] = {(y - 1, x), (y, x + 1)}
case "J":
grid[(y, x)] = {(y, x - 1), (y - 1, x)}
case "7":
grid[(y, x)] = {(y, x - 1), (y + 1, x)}
case "F":
grid[(y, x)] = {(y + 1, x), (y, x + 1)}
case "S":
start = (y, x)
2023-12-12 16:36:28 +00:00
grid[(y, x)] = {
(y, x - 1),
(y, x + 1),
(y - 1, x),
(y + 1, x),
}
2023-12-11 08:42:32 +00:00
case _:
pass
if start is None:
raise ValueError("Start position 'S' not found in the grid.")
grid[start] = {dst for dst in grid[start] if start in grid.get(dst, set())}
return grid, start
except FileNotFoundError:
print(f"File not found: {file_path}")
raise
2023-12-10 15:01:04 +00:00
except Exception as e:
2023-12-11 08:42:32 +00:00
print(f"Error parsing grid: {str(e)}")
2023-12-10 15:01:04 +00:00
raise
2023-12-12 16:36:28 +00:00
2023-12-11 08:42:32 +00:00
def find_cycle(grid, start):
"""Finds all nodes in the cycle starting from the starting position."""
print(f"Finding cycle from start position: {start}")
seen = {start}
queue = [start]
while queue:
current = queue.pop(0)
for dst in grid[current]:
if dst not in seen:
seen.add(dst)
queue.append(dst)
return seen
2023-12-12 16:36:28 +00:00
2023-12-11 08:42:32 +00:00
def bfs_distance(grid, start, target):
"""Performs BFS to find distance from start to target."""
2023-12-12 16:36:28 +00:00
# print(f"Calculating BFS distance from {start} to {target}")
2023-12-10 15:01:04 +00:00
queue = [(start, 0)]
2023-12-11 08:42:32 +00:00
visited = set()
2023-12-10 15:01:04 +00:00
while queue:
2023-12-11 08:42:32 +00:00
current, distance = queue.pop(0)
if current == target:
return distance
visited.add(current)
for neighbor in grid[current]:
if neighbor not in visited:
queue.append((neighbor, distance + 1))
return -1
2023-12-12 16:36:28 +00:00
2023-12-11 08:42:32 +00:00
def find_longest_distance(grid, cycle, start):
"""Finds the longest distance from the start in the cycle."""
print("Finding longest distance from start in the cycle.")
max_distance = 0
for node in cycle:
if node != start:
distance = bfs_distance(grid, start, node)
2023-12-10 15:01:04 +00:00
max_distance = max(max_distance, distance)
return max_distance
2023-12-12 16:36:28 +00:00
2023-12-11 08:42:32 +00:00
def run(file_path):
"""Runs the entire algorithm for the given file path."""
print(f"Running algorithm for file: {file_path}")
grid, start = parse_grid(file_path)
cycle = find_cycle(grid, start)
longest_distance = find_longest_distance(grid, cycle, start)
print(f"Longest distance: {longest_distance}")
return longest_distance
2023-12-12 16:36:28 +00:00
2023-12-11 08:42:32 +00:00
def test():
"""Test function to validate the algorithm with a test file."""
print("Starting test...")
expected_result = 8 # Expected result for the test file
result = run("../test.txt")
2023-12-12 16:36:28 +00:00
assert (
result == expected_result
), f"Test failed: Expected {expected_result}, got {result}"
2023-12-11 08:42:32 +00:00
print("Test passed successfully.")
2023-12-12 16:36:28 +00:00
2023-12-11 08:42:32 +00:00
def main():
"""Main function to run the test and then the algorithm for the input file."""
try:
test()
final_result = run("../input.txt")
print(f"Final Result: {final_result}")
except Exception as e:
print(f"An error occurred: {str(e)}")
2023-12-10 16:24:14 +00:00
2023-12-12 16:36:28 +00:00
2023-12-10 15:01:04 +00:00
if __name__ == "__main__":
2023-12-11 08:42:32 +00:00
main()