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()
|