2022-12-12 17:33:12 +00:00
|
|
|
import * as R from "remeda";
|
|
|
|
import Victor from "@a-robu/victor";
|
|
|
|
|
|
|
|
import { readFile } from "../05/part1.js";
|
|
|
|
|
2022-12-14 15:40:27 +00:00
|
|
|
const V = (x, y) => new Victor(x, y);
|
2022-12-12 17:33:12 +00:00
|
|
|
|
|
|
|
const readInput = (...args) =>
|
|
|
|
R.pipe(
|
|
|
|
readFile(...args),
|
|
|
|
(lines) => lines.split("\n"),
|
|
|
|
R.compact, // remove last line
|
2022-12-14 15:40:27 +00:00
|
|
|
R.map((l) => l.split(""))
|
2022-12-12 17:33:12 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
export const puzzleInput = readInput(import.meta.url, "input");
|
|
|
|
export const sample = readInput(import.meta.url, "sample");
|
|
|
|
|
|
|
|
export const findStart = (topoMap) => {
|
|
|
|
let y;
|
|
|
|
let x = R.findIndex(topoMap, (row) => {
|
2022-12-14 14:25:59 +00:00
|
|
|
let z = row.indexOf("S");
|
2022-12-12 17:33:12 +00:00
|
|
|
if (z === -1) return false;
|
|
|
|
y = z;
|
|
|
|
return true;
|
|
|
|
});
|
2022-12-14 15:40:27 +00:00
|
|
|
return V(x, y);
|
2022-12-12 17:33:12 +00:00
|
|
|
};
|
|
|
|
|
2022-12-13 01:52:48 +00:00
|
|
|
export const findEnd = (topoMap) => {
|
|
|
|
let y;
|
|
|
|
let x = R.findIndex(topoMap, (row) => {
|
2022-12-14 14:25:59 +00:00
|
|
|
let z = row.indexOf("E");
|
2022-12-13 01:52:48 +00:00
|
|
|
if (z === -1) return false;
|
|
|
|
y = z;
|
|
|
|
return true;
|
|
|
|
});
|
2022-12-14 15:40:27 +00:00
|
|
|
return V(x, y);
|
2022-12-13 01:52:48 +00:00
|
|
|
};
|
2022-12-12 17:33:12 +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-12 17:33:12 +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-12 17:33:12 +00:00
|
|
|
|
2022-12-14 15:40:27 +00:00
|
|
|
return (next) => {
|
|
|
|
return topoMap[next.x][next.y].charCodeAt(0) - baseline <= 1;
|
|
|
|
};
|
|
|
|
};
|
2022-12-12 17:33:12 +00:00
|
|
|
|
|
|
|
function findShortestPath(topoMap) {
|
2022-12-14 15:40:27 +00:00
|
|
|
const initial = findStart(topoMap);
|
|
|
|
initial.steps = 0;
|
|
|
|
const final = findEnd(topoMap);
|
2022-12-12 17:33:12 +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-12 17:33:12 +00:00
|
|
|
|
2022-12-14 15:40:27 +00:00
|
|
|
const potentials = [initial];
|
2022-12-12 17:33:12 +00:00
|
|
|
|
2022-12-14 15:40:27 +00:00
|
|
|
const beenThere = topoMap.map((line) => line.map(() => 9999));
|
2022-12-12 17:33:12 +00:00
|
|
|
|
2022-12-14 15:40:27 +00:00
|
|
|
const oom = outOfMap(topoMap.length, topoMap[0].length);
|
2022-12-12 17:33:12 +00:00
|
|
|
|
2022-12-14 15:40:27 +00:00
|
|
|
let failsafe = 10; //topoMap.length*topoMap[0].length ;
|
|
|
|
while (potentials.length > 0) {
|
2022-12-13 01:52:48 +00:00
|
|
|
// if(! failsafe--) return;
|
2022-12-14 15:40:27 +00:00
|
|
|
const pos = potentials.shift(); // depth-first
|
2022-12-12 17:33:12 +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-12 17:33:12 +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-12 17:33:12 +00:00
|
|
|
|
2022-12-14 15:40:27 +00:00
|
|
|
next.forEach((n) => (n.steps = pos.steps + 1));
|
2022-12-12 17:33:12 +00:00
|
|
|
|
2022-12-14 15:40:27 +00:00
|
|
|
potentials.push(...next);
|
|
|
|
}
|
2022-12-12 17:33:12 +00:00
|
|
|
|
2022-12-14 15:40:27 +00:00
|
|
|
return beenThere[final.x][final.y];
|
2022-12-12 17:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export default findShortestPath;
|