BFS to get the path from start to end. pt 1 took some time to wrap around, and initial versions of the code used defaultdict() to keep counts of all cheats to check if the example puzzle input gace the right counts for the cheats. But since only 100 or more was requested, a counter do the job in the final version of the code. For pt 2, a permutation is used.
58 lines
1.4 KiB
Python
58 lines
1.4 KiB
Python
from collections import deque
|
|
|
|
from output import matrix, D, mhd
|
|
|
|
|
|
def solve(data):
|
|
grid, H, W = matrix(data)
|
|
S = next((r, c) for r in range(H) for c in range(W) if grid[r][c] == "S")
|
|
E = next((r, c) for r in range(H) for c in range(W) if grid[r][c] == "E")
|
|
seen = set()
|
|
Q = deque([(S, 0, [])])
|
|
while Q:
|
|
pos, w, path = Q.pop()
|
|
r, c = pos
|
|
if grid[r][c] == "#" or pos in seen:
|
|
continue
|
|
seen.add(pos)
|
|
if pos == E:
|
|
og = path + [(r, c)]
|
|
break
|
|
for dr, dc in D:
|
|
Q.append(((r + dr, c + dc), w + 1, path + [(r, c)]))
|
|
|
|
track = {rc: i for i, rc in enumerate(og)}
|
|
T = 100
|
|
p1 = 0
|
|
p2 = 0
|
|
|
|
cheats = set()
|
|
for r, c in track.keys():
|
|
for dr, dc in D:
|
|
rr, cc = r + dr * 2, c + dc * 2
|
|
if (
|
|
(rr, cc) not in cheats
|
|
and (rr, cc) in track
|
|
and T + 2 <= abs(track[(rr, cc)] - track[(r, c)])
|
|
):
|
|
p1 += 1
|
|
cheats.add((r, c))
|
|
|
|
tk = [k for k in track.keys()]
|
|
for b in range(T, len(tk)):
|
|
for a in range(b - T):
|
|
distance = mhd(tk[a], tk[b])
|
|
if distance <= 20 and b - a - distance >= T:
|
|
p2 += 1
|
|
|
|
return p1, p2
|
|
|
|
|
|
if __name__ == "__main__":
|
|
with open("./input/20.txt", "r") as f:
|
|
inp = f.read().strip()
|
|
|
|
p1, p2 = solve(inp)
|
|
|
|
print(p1)
|
|
print(p2)
|