-
Notifications
You must be signed in to change notification settings - Fork 0
/
day20.ts
75 lines (60 loc) · 2.13 KB
/
day20.ts
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
import { parse, D4 } from "./grid.ts"
const IN_SMALL = "day20small.in"
const IN_BIG = "day20.in"
let IN = IN_BIG
// IN = IN_SMALL
const inputRaw = Deno.readTextFileSync(IN)
const grid = parse(inputRaw)
const INF = 1e20
const start = grid.findFirstGrid("S")!
const end = grid.findFirstGrid("E")!
function allDists() {
const dist = grid.dupShape(INF)
let front = [[start[0], start[1]]]
dist[start[0]][start[1]] = 0
while (front.length) {
const nf: typeof front = []
for (const [r, c] of front) {
for (const [dr, dc] of D4) {
const rr = r+dr, cc = c+dc
if (grid[rr][cc] !== '#' && dist[rr][cc] > dist[r][c] + 1) {
dist[rr][cc] = dist[r][c] + 1
nf.push([rr, cc])
}
}
}
front = nf
}
return dist
}
const dist = allDists()
function countAbove(counts: Map<number, number>, threshold=100) {
const cheats = counts.entries().toArray().toSorted((a, b) => a[0] - b[0])
const above = cheats.filter(([p,]) => p >= threshold)
// above.forEach(([p, n]) => console.log(`${n} cheats saving ${p}`))
return above.reduce((s, [, n]) => s+n, 0)
}
function countCheats(cheatTime: number) {
const counts = new Map<number, number>()
grid.forEachGrid((v, r, c) => {
if (dist[r][c] < INF) {
for (let dr=-cheatTime; dr<=cheatTime; ++dr) {
// const drc = C - Math.abs(dr)
for (let dc=-cheatTime; dc<=cheatTime; ++dc) {
const rr = r + dr, cc = c + dc
const rd = Math.abs(dr) + Math.abs(dc)
const nd = dist[r][c] + rd
if (rd <= cheatTime && grid.isIn(rr, cc) && dist[rr][cc] < INF && dist[rr][cc] > nd) {
const cheatDist = dist[rr][cc] - nd
counts.set(cheatDist, 1 + (counts.get(cheatDist) ?? 0))
}
}
}
}
})
return counts
}
const part1 = () => countAbove(countCheats(2))
console.log(part1())
const part2 = () => countAbove(countCheats(20))
console.log(part2())