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