Spaces:
Running
Running
| from collections import deque | |
| def parse_input(file): | |
| with open(file, 'r') as f: | |
| maze = [list(line.strip()) for line in f] | |
| return maze | |
| def find_start_end(maze): | |
| start = end = None | |
| for r, row in enumerate(maze): | |
| for c, val in enumerate(row): | |
| if val == 'S': | |
| start = (r, c) | |
| elif val == 'E': | |
| end = (r, c) | |
| return start, end | |
| def get_neighbors(pos, direction, maze): | |
| directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # East, South, West, North | |
| r, c = pos | |
| neighbors = [] | |
| # Move forward | |
| dr, dc = directions[direction] | |
| if maze[r + dr][c + dc] != '#': | |
| neighbors.append(((r + dr, c + dc), direction, 1)) # 1 point for moving forward | |
| # Turn clockwise | |
| neighbors.append((pos, (direction + 1) % 4, 1000)) # 1000 points for turning | |
| # Turn counterclockwise | |
| neighbors.append((pos, (direction - 1) % 4, 1000)) # 1000 points for turning | |
| return neighbors | |
| def find_best_paths(maze, start, end): | |
| directions = [(0, 1), (1, 0), (0, -1), (-1, 0)] # East, South, West, North | |
| start_direction = 0 # Start facing East | |
| queue = deque([(start, start_direction, 0)]) # (position, direction, score) | |
| visited = set() | |
| best_score = float('inf') | |
| best_paths = set() | |
| while queue: | |
| pos, direction, score = queue.popleft() | |
| if (pos, direction) in visited: | |
| continue | |
| visited.add((pos, direction)) | |
| if pos == end: | |
| if score < best_score: | |
| best_score = score | |
| best_paths = {pos} | |
| elif score == best_score: | |
| best_paths.add(pos) | |
| continue | |
| for neighbor, new_direction, cost in get_neighbors(pos, direction, maze): | |
| new_score = score + cost | |
| if new_score <= best_score: | |
| queue.append((neighbor, new_direction, new_score)) | |
| if new_score == best_score: | |
| best_paths.add(neighbor) | |
| return best_paths | |
| def count_best_path_tiles(maze, best_paths): | |
| count = 0 | |
| for r, row in enumerate(maze): | |
| for c, val in enumerate(row): | |
| if (r, c) in best_paths and val != '#': | |
| count += 1 | |
| return count | |
| def main(): | |
| file = "input.txt" | |
| maze = parse_input(file) | |
| start, end = find_start_end(maze) | |
| best_paths = find_best_paths(maze, start, end) | |
| result = count_best_path_tiles(maze, best_paths) | |
| print(result) | |
| main() |