File size: 3,008 Bytes
a4da721
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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)