84 lines
1.8 KiB
JavaScript
84 lines
1.8 KiB
JavaScript
import * as R from "remeda";
|
|
import Victor from "@a-robu/victor";
|
|
|
|
import { readFile } from "../05/part1.js";
|
|
|
|
export const V = (...args) => new Victor(...args);
|
|
const parseLine = (line) => line.match(/[\d,]+/g).map((x) => eval(`[${x}]`));
|
|
|
|
const readInput = (...args) =>
|
|
R.pipe(
|
|
readFile(...args),
|
|
(lines) => lines.split("\n"),
|
|
R.compact, // remove last line
|
|
R.map(parseLine)
|
|
);
|
|
|
|
export const puzzleInput = readInput(import.meta.url, "input");
|
|
export const sample = readInput(import.meta.url, "sample");
|
|
|
|
export function genCave(rocks) {
|
|
const cave = {};
|
|
for (const rock of rocks) {
|
|
const points = rock.map(Victor.fromArray);
|
|
let from = points.shift();
|
|
|
|
while (points.length) {
|
|
/** @type Victor */
|
|
const to = points.shift();
|
|
const direction = to.clone().subtract(from).normalize();
|
|
|
|
R.times(to.clone().subtract(from).length() + 1, () => {
|
|
if (!cave[from.y]) cave[from.y] = {};
|
|
cave[from.y][from.x] = "#";
|
|
from.add(direction);
|
|
});
|
|
|
|
from = to;
|
|
}
|
|
}
|
|
return cave;
|
|
}
|
|
|
|
function pourSand(cave) {
|
|
cave = R.clone(cave);
|
|
|
|
let sand = 0;
|
|
|
|
/** @type Victor */
|
|
let current;
|
|
|
|
const maxDepth = R.pipe(
|
|
cave,
|
|
R.keys,
|
|
R.map((x) => parseInt(x)),
|
|
R.maxBy(R.identity)
|
|
);
|
|
|
|
console.log({ maxDepth });
|
|
|
|
while (true) {
|
|
if (!current) current = V(500, 0);
|
|
if (current.y > maxDepth) return sand;
|
|
|
|
const next = [
|
|
[0, 1],
|
|
[-1, 1],
|
|
[1, 1],
|
|
]
|
|
.map((args) => V(...args))
|
|
.map((v) => v.add(current))
|
|
.find((v) => !(cave[v.y] && cave[v.y][v.x]));
|
|
if (next) {
|
|
current = next;
|
|
} else {
|
|
if (!cave[current.y]) cave[current.y] = {};
|
|
cave[current.y][current.x] = "o";
|
|
sand++;
|
|
current = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
export default R.createPipe(genCave, pourSand);
|