Spaces:
Running
Running
| from collections import deque | |
| def parse_input(file): | |
| with open(file, 'r') as f: | |
| grid = [list(line.strip()) for line in f] | |
| start = end = None | |
| for r, row in enumerate(grid): | |
| for c, val in enumerate(row): | |
| if val == 'S': | |
| start = (r, c) | |
| elif val == 'E': | |
| end = (r, c) | |
| return grid, start, end | |
| def bfs(grid, start, end, max_cheat_time): | |
| rows, cols = len(grid), len(grid[0]) | |
| directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] | |
| queue = deque([(start[0], start[1], 0, 0)]) # (row, col, time, cheat_time) | |
| visited = set() | |
| visited.add((start[0], start[1], 0)) # (row, col, cheat_time) | |
| min_time = float('inf') | |
| cheats = [] | |
| while queue: | |
| r, c, time, cheat_time = queue.popleft() | |
| if (r, c) == end: | |
| if time < min_time: | |
| min_time = time | |
| continue | |
| for dr, dc in directions: | |
| nr, nc = r + dr, c + dc | |
| if 0 <= nr < rows and 0 <= nc < cols: | |
| if grid[nr][nc] == '.' or grid[nr][nc] == 'E': | |
| if (nr, nc, cheat_time) not in visited: | |
| visited.add((nr, nc, cheat_time)) | |
| queue.append((nr, nc, time + 1, cheat_time)) | |
| elif grid[nr][nc] == '#' and cheat_time < max_cheat_time: | |
| if (nr, nc, cheat_time + 1) not in visited: | |
| visited.add((nr, nc, cheat_time + 1)) | |
| queue.append((nr, nc, time + 1, cheat_time + 1)) | |
| return min_time | |
| def count_cheats(grid, start, end, max_cheat_time, baseline_time): | |
| rows, cols = len(grid), len(grid[0]) | |
| directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] | |
| queue = deque([(start[0], start[1], 0, 0)]) # (row, col, time, cheat_time) | |
| visited = set() | |
| visited.add((start[0], start[1], 0)) # (row, col, cheat_time) | |
| cheat_savings = [] | |
| while queue: | |
| r, c, time, cheat_time = queue.popleft() | |
| if (r, c) == end: | |
| savings = baseline_time - time | |
| if savings >= 100: | |
| cheat_savings.append(savings) | |
| continue | |
| for dr, dc in directions: | |
| nr, nc = r + dr, c + dc | |
| if 0 <= nr < rows and 0 <= nc < cols: | |
| if grid[nr][nc] == '.' or grid[nr][nc] == 'E': | |
| if (nr, nc, cheat_time) not in visited: | |
| visited.add((nr, nc, cheat_time)) | |
| queue.append((nr, nc, time + 1, cheat_time)) | |
| elif grid[nr][nc] == '#' and cheat_time < max_cheat_time: | |
| if (nr, nc, cheat_time + 1) not in visited: | |
| visited.add((nr, nc, cheat_time + 1)) | |
| queue.append((nr, nc, time + 1, cheat_time + 1)) | |
| return len(cheat_savings) | |
| file = "input.txt" | |
| grid, start, end = parse_input(file) | |
| baseline_time = bfs(grid, start, end, 0) | |
| cheat_count = count_cheats(grid, start, end, 20, baseline_time) | |
| print(cheat_count) |