adventofcode/2022/12/part2.js

95 lines
2.0 KiB
JavaScript
Raw Normal View History

2022-12-12 17:33:12 +00:00
import * as R from "remeda";
2022-12-14 14:25:59 +00:00
import Victor from "@a-robu/victor";
2022-12-12 17:33:12 +00:00
2022-12-14 14:25:59 +00:00
import { readFile } from "../05/part1.js";
2022-12-12 17:33:12 +00:00
2022-12-14 15:40:27 +00:00
const V = (x, y) => new Victor(x, y);
2022-12-14 14:25:59 +00:00
export const findAs = (topoMap) => {
const locations = [];
2022-12-14 15:40:27 +00:00
topoMap.forEach((line, x) =>
line.forEach((v, y) => {
if (v === "a") locations.push([x, y]);
})
);
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
return locations;
2022-12-14 14:25:59 +00:00
};
export const findEnd = (topoMap) => {
let y;
let x = R.findIndex(topoMap, (row) => {
let z = row.indexOf("E");
if (z === -1) return false;
y = z;
return true;
});
2022-12-14 15:40:27 +00:00
return V(x, y);
2022-12-14 14:25:59 +00:00
};
2022-12-14 15:40:27 +00:00
const directions = [
[0, 1],
[0, -1],
[1, 0],
[-1, 0],
].map((d) => V(...d));
const outOfMap = (maxX, maxY) => (loc) => {
if (Math.min(loc.x, loc.y) < 0) return true;
if (loc.x >= maxX) return true;
if (loc.y >= maxY) return true;
return false;
};
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
const isReachable = (topoMap, pos) => {
const baseline = topoMap[pos.x][pos.y].charCodeAt(0);
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
return (next) => {
return baseline - topoMap[next.x][next.y].charCodeAt(0) <= 1;
};
};
2022-12-14 14:25:59 +00:00
function findShortestPath(topoMap) {
2022-12-14 15:40:27 +00:00
const final = findEnd(topoMap);
final.steps = 0;
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
topoMap = topoMap.map((line) =>
line.map((c) => c.replace("S", "a").replace("E", "z"))
);
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
const initial = findAs(topoMap);
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
const potentials = [final];
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
const beenThere = topoMap.map((line) => line.map(() => 9999));
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
const oom = outOfMap(topoMap.length, topoMap[0].length);
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
let failsafe = 10; //topoMap.length*topoMap[0].length ;
while (potentials.length > 0) {
2022-12-14 14:25:59 +00:00
// if(! failsafe--) return;
2022-12-14 15:40:27 +00:00
const pos = potentials.shift(); // depth-first
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
if (beenThere[pos.x][pos.y] <= pos.steps) continue;
beenThere[pos.x][pos.y] = pos.steps;
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
const next = directions
.map((d) => d.clone().add(pos))
.filter(R.isNot(oom))
.filter(isReachable(topoMap, pos));
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
next.forEach((n) => (n.steps = pos.steps + 1));
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
potentials.push(...next);
}
2022-12-14 14:25:59 +00:00
2022-12-14 15:40:27 +00:00
return R.pipe(
initial,
R.map(([x, y]) => beenThere[x][y]),
R.minBy(R.identity)
);
2022-12-14 14:25:59 +00:00
}
export default findShortestPath;