-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday12.js
executable file
·93 lines (91 loc) · 2.72 KB
/
day12.js
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
#!/usr/bin/env node
// https://adventofcode.com/2022/day/12
const input =
`Sabqponm
abcryxxl
accszExk
acctuvwj
abdefghi`;
// Part 1 - Navigating a heightmap
const grid = input.split("\n").map(row => row.split(""));
function elevation(value) {
if ("S" === value) {
return 0;
}
if ("E" === value) {
return 25;
}
return "abcdefghijklmnopqrstuvwxyz".indexOf(value);
}
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
neighbors() {
// Can't travel diagonally
const result = new Array();
if (0 <= this.x - 1) {
result.push(new Point(this.x - 1, this.y));
}
if (this.x + 1 < grid[0].length) {
result.push(new Point(this.x + 1, this.y));
}
if (0 <= this.y - 1) {
result.push(new Point(this.x, this.y - 1));
}
if (this.y + 1 < grid.length) {
result.push(new Point(this.x, this.y + 1));
}
return result;
}
canReach(other) {
const thisElevation = elevation(grid[this.y][this.x]);
const otherElevation = elevation(grid[other.y][other.x]);
return otherElevation - thisElevation <= 1
}
}
function findPath(start, end) {
let paths = new Array(new Array(start));
let visited = new Map();
for (let x = 0; x < grid[0].length; x++) {
visited[x] = new Map();
for (let y = 0; y < grid.length; y++) {
visited[x][y] = false;
}
}
while (paths.length) {
const path = paths.shift();
const here = path[path.length - 1];
for (const neighbor of here.neighbors()) {
if (here.canReach(neighbor) && !visited[neighbor.x][neighbor.y]) {
if (neighbor.x === end.x && neighbor.y === end.y) {
return path;
}
paths.push(path.concat(neighbor));
visited[neighbor.x][neighbor.y] = true;
}
}
}
return Infinity;
}
const startY = grid.findIndex(row => -1 !== row.indexOf("S"));
const startX = grid[startY].indexOf("S");
const endY = grid.findIndex(row => -1 !== row.indexOf("E"));
const endX = grid[endY].indexOf("E");
console.log(findPath(new Point(startX, startY), new Point(endX, endY)).length);
// Part 2 - Navigating a heightmap from multiple start locations
let startLocations = new Array();
for (let x = 0; x < grid[0].length; x++) {
for (let y = 0; y < grid.length; y++) {
if ("a" === grid[y][x]) {
startLocations.push(new Point(x, y));
}
}
}
const shortestPath = startLocations
.map(start => findPath(start, new Point(endX, endY)))
.map(path => path.length)
.sort((x, y) => x - y)
.at(0);
console.log(shortestPath);