2022-12-15 19:35:55 +00:00
|
|
|
import * as R from "remeda";
|
|
|
|
|
2022-12-18 16:57:22 +00:00
|
|
|
import { passthru } from "../08/part1.js";
|
2022-12-15 19:35:55 +00:00
|
|
|
import { readFile } from "../05/part1.js";
|
|
|
|
|
2023-11-30 15:13:16 +00:00
|
|
|
import V from "@yanick/vyktor";
|
2022-12-18 16:57:22 +00:00
|
|
|
import { createLogger } from "vite";
|
2022-12-15 19:35:55 +00:00
|
|
|
|
|
|
|
const readInput = (...args) =>
|
2023-11-30 15:13:16 +00:00
|
|
|
R.pipe(
|
|
|
|
readFile(...args),
|
|
|
|
(lines) => lines.split("\n"),
|
|
|
|
R.compact, // remove last line
|
|
|
|
R.map((line) =>
|
|
|
|
line
|
|
|
|
.match(/x=-?.*?y=-?\d+/g)
|
|
|
|
.map((str) => str.match(/-?\d+/g).map((x) => parseInt(x)))
|
|
|
|
.map((coords) => V(coords))
|
|
|
|
)
|
|
|
|
);
|
2022-12-15 19:35:55 +00:00
|
|
|
|
|
|
|
export const puzzleInput = readInput(import.meta.url, "input");
|
|
|
|
export const sample = readInput(import.meta.url, "sample");
|
|
|
|
|
2022-12-18 16:57:22 +00:00
|
|
|
/** @returns [number,number][] */
|
2023-11-30 15:13:16 +00:00
|
|
|
export const mergeRanges = (ranges) => {
|
|
|
|
return ranges.reduce((accum, range) => {
|
|
|
|
if (accum.length === 0) return [range];
|
|
|
|
if (R.last(accum)[1] < range[0]) {
|
|
|
|
accum.push(range);
|
|
|
|
} else {
|
|
|
|
R.last(accum)[1] = Math.max(R.last(accum)[1], range[1]);
|
|
|
|
}
|
|
|
|
return accum;
|
|
|
|
}, []);
|
|
|
|
};
|
2022-12-18 16:57:22 +00:00
|
|
|
|
2023-11-30 15:13:16 +00:00
|
|
|
export const spy = passthru((x) => console.log(x));
|
2022-12-18 16:57:22 +00:00
|
|
|
|
2023-11-30 15:13:16 +00:00
|
|
|
const entriesInRange = (targetLine, entries) => {
|
|
|
|
entries = R.uniqBy(
|
|
|
|
entries
|
|
|
|
.map(([_, beacon]) => beacon)
|
|
|
|
.filter((beacon) => beacon?.y === targetLine),
|
|
|
|
(x) => x.toString()
|
|
|
|
);
|
2022-12-18 16:57:22 +00:00
|
|
|
|
2023-11-30 15:13:16 +00:00
|
|
|
return (range) => {
|
|
|
|
return entries.filter((entry) => entry.x >= range[0] && entry.x <= range[1])
|
|
|
|
.length;
|
|
|
|
};
|
2022-12-18 16:57:22 +00:00
|
|
|
};
|
|
|
|
|
2023-11-30 15:13:16 +00:00
|
|
|
export const unbeaconAtLine = (targetLine) => (entries) =>
|
|
|
|
R.pipe(
|
2022-12-18 16:57:22 +00:00
|
|
|
entries,
|
2023-11-30 15:13:16 +00:00
|
|
|
R.map(([x, y]) => [x, x.manhattanDistance(y)]),
|
|
|
|
R.filter((e) => e[0].y - e[1] <= targetLine && e[0].y + e[1] >= targetLine),
|
|
|
|
R.map((e) => {
|
|
|
|
const l = e[1] - Math.abs(targetLine - e[0].y);
|
2022-12-15 19:35:55 +00:00
|
|
|
|
2023-11-30 15:13:16 +00:00
|
|
|
return [e[0].x - l, e[0].x + l];
|
|
|
|
}),
|
2022-12-18 16:57:22 +00:00
|
|
|
spy,
|
2023-11-30 15:13:16 +00:00
|
|
|
(ranges) =>
|
|
|
|
ranges.sort((a, b) => {
|
|
|
|
return a[0] - b[0] || a[1] - b[1];
|
|
|
|
}),
|
2022-12-18 16:57:22 +00:00
|
|
|
spy,
|
|
|
|
mergeRanges,
|
|
|
|
spy,
|
2023-11-30 15:13:16 +00:00
|
|
|
R.sumBy(
|
|
|
|
(range) =>
|
|
|
|
range[1] - range[0] + 1 - entriesInRange(targetLine, entries)(range)
|
|
|
|
)
|
|
|
|
);
|
2022-12-15 19:35:55 +00:00
|
|
|
|
|
|
|
export default unbeaconAtLine(2000000);
|