-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
121 lines (98 loc) · 2.66 KB
/
index.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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* eslint-disable no-constant-condition */
import {
debugGrid,
findGridPos,
getGrid,
INPUT_PATH,
directions,
runner,
SAMPLE_PATH,
splitLines,
} from '../../../lib/utils';
const path = `${__dirname}/${INPUT_PATH}`;
type Grid = string[][];
type Point = [number, number];
const START = 'S';
const END = 'E';
function dijkstra(
grid: Grid,
[sx, sy]: Point,
[ex, ey]: Point,
wallChar = '#',
) {
const rows = grid.length;
const cols = grid[0].length;
const distances = getGrid(rows, cols, Infinity);
const previous = getGrid<Point | null>(rows, cols, null);
const prevDirections = getGrid<Point | null>(rows, cols, null);
const visited = getGrid(rows, cols, false);
distances[sy][sx] = 0;
while (true) {
let minDistance = Infinity;
let current: Point | null = null;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (!visited[i][j] && distances[i][j] < minDistance) {
minDistance = distances[i][j];
current = [j, i];
}
}
}
if (!current || (current[1] === ey && current[0] === ex)) break;
const [x, y] = current || [];
visited[y][x] = true;
for (const [idx, [dx, dy]] of directions.entries()) {
const newRow = y + dx;
const newCol = x + dy;
if (
newRow >= 0 &&
newRow < rows &&
newCol >= 0 &&
newCol < cols &&
grid[newRow][newCol] !== wallChar
) {
const currentDirection = prevDirections[y][x];
let distance = distances[y][x] + 1;
if (
currentDirection !== null &&
(currentDirection[1] !== dy || currentDirection[0] !== dx)
) {
distance += 1000;
}
if (distance < distances[newRow][newCol]) {
distances[newRow][newCol] = distance;
previous[newRow][newCol] = current;
prevDirections[newRow][newCol] = [dx, dy];
}
}
}
}
const path: Point[] = [];
let current: Point | null = [ex, ey];
if (distances[ey][ex] === Infinity) {
return { distance: -1, path: [] };
}
while (current !== null) {
path.unshift(current);
current = previous[current[1]][current[0]];
}
return {
distance: distances[ey][ex],
path: path,
};
}
const solution = (input: string) => {
const grid = splitLines(input).map((line) => line.split(''));
const start = findGridPos(grid, START);
const end = findGridPos(grid, END);
const result = dijkstra(grid, [start.x, start.y], [end.x, end.y]);
result.path.forEach(([x, y]) => {
grid[y][x] = 'O';
});
// debugGrid(grid);
return result.distance + 1000;
};
runner({
path,
solution: (input) => solution(input),
});