@alexaegis/advent-of-code-lib
Version:
Advent of Code Library
852 lines (851 loc) • 16.8 kB
JavaScript
"use strict";
const array_polyfill = require("./array.polyfill-uI4B25o5.cjs");
const regex = require("./regex.cjs");
require("@alexaegis/common");
require("js-sdsl");
require("./index-ZPyfgNVR.cjs");
require("./map.cjs");
require("node:perf_hooks");
require("node:fs/promises");
require("node:path");
require("node:fs");
require("kolorist");
require("./set.cjs");
const is = (...a) => (b) => a.includes(b);
const chunksOfArray = (arr, size) => {
const matrix = [];
for (let i = 0; i < arr.length; i += size) {
matrix.push(arr.slice(i, i + size));
}
return matrix;
};
const copyMatrix = (matrix) => matrix.map((row) => [...row]);
const findCorners = (vectors) => {
let minX = Number.POSITIVE_INFINITY;
let minY = Number.POSITIVE_INFINITY;
let maxX = Number.NEGATIVE_INFINITY;
let maxY = Number.NEGATIVE_INFINITY;
for (const vector of vectors) {
if (vector.x < minX) {
minX = vector.x;
}
if (vector.x > maxX) {
maxX = vector.x;
}
if (vector.y < minY) {
minY = vector.y;
}
if (vector.y > maxY) {
maxY = vector.y;
}
}
return {
topLeft: new array_polyfill.Vec2(minX, maxY),
topRight: new array_polyfill.Vec2(maxX, maxY),
bottomLeft: new array_polyfill.Vec2(minX, minY),
bottomRight: new array_polyfill.Vec2(maxX, minY)
};
};
const generateStringTile = (width, height, base = "_") => (base.repeat(width) + "\n").repeat(height);
const createTileMatrixFromMap = (tileMap, tileToString = (t) => t.toString?.() ?? "_", emptyTileBase = "_") => {
const result = [];
const corners = findCorners([...tileMap.keys()].map((c) => new array_polyfill.Vec2(c)));
const emptyTiles = [];
let tileWidth = 0;
let tileHeight = 0;
for (let y = 0; y <= corners.topRight.y - corners.bottomLeft.y; y++) {
for (let x = 0; x <= corners.topRight.x - corners.bottomLeft.x; x++) {
const originalVector = new array_polyfill.Vec2(x + corners.bottomLeft.x, y + corners.bottomLeft.y);
const tile = tileMap.get(originalVector.toString());
if (tile) {
let row = result[y];
if (!row) {
row = [];
result[y] = row;
}
const s = tileToString(tile);
row[x] = s;
if (tileHeight === 0) {
const tileRows = s.split(regex.NEWLINE);
tileHeight = tileRows.length - 1;
tileWidth = tileRows[0]?.length ?? 0;
}
} else {
emptyTiles.push(new array_polyfill.Vec2(x, y));
}
}
}
for (const emptyTile of emptyTiles) {
const row = result[emptyTile.y];
if (row) {
row[emptyTile.x] = generateStringTile(tileWidth, tileHeight, emptyTileBase);
}
}
return result.reverse();
};
function integerLength(n) {
return Math.floor(Math.abs(n)).toString().length;
}
function integerLengthMath(n) {
return Math.ceil(Math.log10(Math.abs(n) + 1));
}
const iteratorGetUntil = (iterator, condition) => {
for (let next = iterator.next(); !next.done; next = iterator.next()) {
if (condition(next.value)) {
return next.value;
}
}
return void 0;
};
const mergeTileMatrix = (tileMatrix, separation = false) => {
const result = [];
for (const tileRow of tileMatrix) {
const rowsOfTiles = tileRow.map((rb) => rb.toString().trim().split(regex.NEWLINE));
const tileHeight = (rowsOfTiles[0]?.length ?? 0) - 1;
for (let i = 0; i <= tileHeight; i++) {
result.push(rowsOfTiles.map((rb) => rb[i]).join(separation ? " " : ""));
}
if (separation) {
result.push("".repeat(result.at(-1)?.length ?? 0));
}
}
return result.join("\n") + "\n";
};
function numAt(n, p) {
return Number.parseInt(n.toString()[p] ?? "0", 10);
}
function numStart(n, length = 1) {
const l = Math.pow(10, Math.floor(Math.log10(n)) - length + 1);
const b = Math.floor(n / l);
const p = Math.pow(10, length);
return b - Math.floor(b / p) * p;
}
const drawMapStatic = (map, renderTile, startY, endY, startX, endX, flip = false, numbered = false) => {
const res = [];
if (numbered) {
res.push(
[...Array.from({ length: endX - startX + 1 }).keys()].map((i) => i + startX).map((i) => i >= 10 ? i.toString() : "0" + i.toString())
);
}
for (let i = startY; i <= endY; i++) {
const row = numbered ? [i >= 10 ? i.toString() : "0" + i.toString()] : [];
for (let j = startX; j <= endX; j++) {
row.push(renderTile(map.get(new array_polyfill.Vec2(flip ? i : j, flip ? j : i).toString())));
}
res.push(row);
}
return res;
};
const getMatrixAlphabet = (letterMatrixType) => {
return letterMatrixType === "small" ? MATRIX_ALPHABET_SMALL : MATRIX_ALPHABET_BIG;
};
const getRowRenderedAlphabet = (letterMatrixType) => {
return Object.fromEntries(
Object.entries(getMatrixAlphabet(letterMatrixType)).map(([key, value]) => [
key,
value.split(regex.NEWLINE)
])
);
};
const UPPERCASE_ALPHABET = [
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z"
];
const A_LETTER_SMALL = `.##.
#..#
#..#
####
#..#
#..#`;
const B_LETTER_SMALL = `###.
#..#
###.
#..#
#..#
###.`;
const C_LETTER_SMALL = `.##.
#..#
#...
#...
#..#
.##.`;
const D_UNVERIFIED_LETTER_SMALL = `###.
#..#
#..#
#..#
#..#
###.`;
const E_LETTER_SMALL = `####
#...
###.
#...
#...
####`;
const F_LETTER_SMALL = `####
#...
###.
#...
#...
#...`;
const G_LETTER_SMALL = `.##.
#..#
#...
#.##
#..#
.###`;
const H_LETTER_SMALL = `#..#
#..#
####
#..#
#..#
#..#`;
const I_LETTER_SMALL = `###
.#.
.#.
.#.
.#.
###`;
const J_LETTER_SMALL = `..##
...#
...#
...#
#..#
.##.`;
const K_LETTER_SMALL = `#..#
#.#.
##..
#.#.
#.#.
#..#`;
const L_LETTER_SMALL = `#...
#...
#...
#...
#...
####`;
const M_UNVERIFIED_LETTER_SMALL = `#...#
##.##
#.#.#
#...#
#...#
#...#`;
const N_UNVERIFIED_LETTER_SMALL = `#...#
##..#
#.#.#
#.#.#
#..##
#...#`;
const O_LETTER_SMALL = `.##.
#..#
#..#
#..#
#..#
.##.`;
const P_LETTER_SMALL = `###.
#..#
#..#
###.
#...
#...`;
const Q_UNVERIFIED_LETTER_SMALL = `.##.
#..#
#..#
#..#
#.##
.###`;
const R_LETTER_SMALL = `###.
#..#
#..#
###.
#.#.
#..#`;
const S_LETTER_SMALL = `.###
#...
#...
.##.
...#
###.`;
const T_UNVERIFIED_LETTER_SMALL = `#####
..#..
..#..
..#..
..#..
..#..`;
const U_LETTER_SMALL = `#..#
#..#
#..#
#..#
#..#
.##.`;
const V_UNVERIFIED_LETTER_SMALL = `#...#
#...#
#...#
#...#
.#.#.
..#..`;
const W_UNVERIFIED_LETTER_SMALL = `#.......#
#.......#
#...#...#
#...#...#
.#.#.#.#.
..#...#..`;
const X_UNVERIFIED_LETTER_SMALL = `#...#
.#.#.
..#..
..#..
.#.#.
#...#`;
const Y_LETTER_SMALL = `#...#
#...#
.#.#.
..#..
..#..
..#..`;
const Z_LETTER_SMALL = `####
...#
..#.
.#..
#...
####`;
const MATRIX_ALPHABET_SMALL = {
A: A_LETTER_SMALL,
B: B_LETTER_SMALL,
C: C_LETTER_SMALL,
D: D_UNVERIFIED_LETTER_SMALL,
E: E_LETTER_SMALL,
F: F_LETTER_SMALL,
G: G_LETTER_SMALL,
H: H_LETTER_SMALL,
I: I_LETTER_SMALL,
J: J_LETTER_SMALL,
K: K_LETTER_SMALL,
L: L_LETTER_SMALL,
M: M_UNVERIFIED_LETTER_SMALL,
N: N_UNVERIFIED_LETTER_SMALL,
O: O_LETTER_SMALL,
P: P_LETTER_SMALL,
Q: Q_UNVERIFIED_LETTER_SMALL,
R: R_LETTER_SMALL,
S: S_LETTER_SMALL,
T: T_UNVERIFIED_LETTER_SMALL,
U: U_LETTER_SMALL,
V: V_UNVERIFIED_LETTER_SMALL,
W: W_UNVERIFIED_LETTER_SMALL,
X: X_UNVERIFIED_LETTER_SMALL,
Y: Y_LETTER_SMALL,
Z: Z_LETTER_SMALL
};
const A_LETTER_BIG = `..##..
.#..#.
#....#
#....#
#....#
######
#....#
#....#
#....#
#....#
`;
const B_LETTER_BIG = `#####.
#....#
#....#
#....#
#####.
#....#
#....#
#....#
#....#
#####.
`;
const C_LETTER_BIG = `.####.
#....#
#.....
#.....
#.....
#.....
#.....
#.....
#....#
.####.
`;
const D_UNVERIFIED_LETTER_BIG = `#####.
#....#
#....#
#....#
#....#
#....#
#....#
#....#
#....#
#####.
`;
const E_LETTER_BIG = `######
#.....
#.....
#.....
#####.
#.....
#.....
#.....
#.....
######
`;
const F_LETTER_BIG = `######
#.....
#.....
#.....
#####.
#.....
#.....
#.....
#.....
#.....
`;
const G_LETTER_BIG = `.####.
#....#
#.....
#.....
#.....
#..###
#....#
#....#
#...##
.###.#
`;
const H_LETTER_BIG = `#....#
#....#
#....#
#....#
######
#....#
#....#
#....#
#....#
#....#
`;
const I_UNVERIFIED_LETTER_BIG = `###
.#.
.#.
.#.
.#.
.#.
.#.
.#.
.#.
###
`;
const J_LETTER_BIG = `...###
....#.
....#.
....#.
....#.
....#.
....#.
#...#.
#...#.
.###..
`;
const K_LETTER_BIG = `#....#
#...#.
#..#..
#.#...
##....
##....
#.#...
#..#..
#...#.
#....#
`;
const L_LETTER_BIG = `#.....
#.....
#.....
#.....
#.....
#.....
#.....
#.....
#.....
######
`;
const M_UNVERIFIED_LETTER_BIG = `#.....#
##...##
##...##
#.#.#.#
#.#.#.#
#..#..#
#..#..#
#.....#
#.....#
#.....#
`;
const N_LETTER_BIG = `#....#
##...#
##...#
#.#..#
#.#..#
#..#.#
#..#.#
#...##
#...##
#....#
`;
const O_UNVERIFIED_LETTER_BIG = `.####.
#....#
#....#
#....#
#....#
#....#
#....#
#....#
#....#
.####.
`;
const P_LETTER_BIG = `#####.
#....#
#....#
#....#
#####.
#.....
#.....
#.....
#.....
#.....
`;
const Q_UNVERIFIED_LETTER_BIG = `.####.
#....#
#....#
#....#
#....#
#....#
#....#
#..#.#
#...##
.#####
`;
const R_LETTER_BIG = `#####.
#....#
#....#
#....#
#####.
#..#..
#...#.
#...#.
#....#
#....#
`;
const S_UNVERIFIED_LETTER_BIG = `.####.
#.....
#.....
#.....
.####.
.....#
.....#
.....#
.....#
#####.
`;
const T_UNVERIFIED_LETTER_BIG = `#####
..#..
..#..
..#..
..#..
..#..
..#..
..#..
..#..
..#..
`;
const U_UNVERIFIED_LETTER_BIG = `#....#
#....#
#....#
#....#
#....#
#....#
#....#
#....#
#....#
.####.
`;
const V_UNVERIFIED_LETTER_BIG = `#...#
#...#
#...#
#...#
#...#
#...#
#...#
.#.#.
.#.#.
..#..
`;
const W_UNVERIFIED_LETTER_BIG = `#.......#
#.......#
#.......#
#...#...#
#...#...#
#...#...#
#...#...#
.#.#.#.#.
.#.#.#.#.
..#...#..
`;
const X_LETTER_BIG = `#....#
#....#
.#..#.
.#..#.
..##..
..##..
.#..#.
.#..#.
#....#
#....#
`;
const Y_UNVERIFIED_LETTER_BIG = `#...#
#...#
.#.#.
.#.#.
..#..
..#..
..#..
..#..
..#..
..#..
`;
const Z_LETTER_BIG = `######
.....#
.....#
....#.
...#..
..#...
.#....
#.....
#.....
######
`;
const MATRIX_ALPHABET_BIG = {
A: A_LETTER_BIG,
B: B_LETTER_BIG,
C: C_LETTER_BIG,
D: D_UNVERIFIED_LETTER_BIG,
E: E_LETTER_BIG,
F: F_LETTER_BIG,
G: G_LETTER_BIG,
H: H_LETTER_BIG,
I: I_UNVERIFIED_LETTER_BIG,
J: J_LETTER_BIG,
K: K_LETTER_BIG,
L: L_LETTER_BIG,
M: M_UNVERIFIED_LETTER_BIG,
N: N_LETTER_BIG,
O: O_UNVERIFIED_LETTER_BIG,
P: P_LETTER_BIG,
Q: Q_UNVERIFIED_LETTER_BIG,
R: R_LETTER_BIG,
S: S_UNVERIFIED_LETTER_BIG,
T: T_UNVERIFIED_LETTER_BIG,
U: U_UNVERIFIED_LETTER_BIG,
V: V_UNVERIFIED_LETTER_BIG,
W: W_UNVERIFIED_LETTER_BIG,
X: X_LETTER_BIG,
Y: Y_UNVERIFIED_LETTER_BIG,
Z: Z_LETTER_BIG
};
const LETTER_SPACING = 1;
const parseLetterMatrix = (matrix, letterType = "small") => {
const renderedAlphabet = getRowRenderedAlphabet(letterType);
const renderedRows = matrix.map((row) => row.join(""));
const width = renderedRows.map((row) => row.length).reduce(array_polyfill.max, Number.NEGATIVE_INFINITY);
const parsedLetters = [];
let offset = 0;
while (offset <= width) {
let someMatched = false;
let matchedWidth = 4;
for (const letter of UPPERCASE_ALPHABET) {
const renderedLetter = renderedAlphabet[letter];
const renderedLetterFirstRow = renderedLetter[0];
if (renderedLetterFirstRow) {
const letterWidth = renderedLetterFirstRow.length;
const matches = renderedRows.every((renderedRow, i) => {
const letterPortion = renderedRow.slice(offset, offset + letterWidth);
return renderedLetter[i] === letterPortion;
});
if (matches) {
parsedLetters.push(letter);
matchedWidth = renderedLetterFirstRow.length;
someMatched = true;
}
}
}
offset += matchedWidth + LETTER_SPACING;
if (offset <= width && !someMatched) {
throw new Error(
`No letter matched at offset ${offset - (matchedWidth + LETTER_SPACING)} during letter matrix parsing!`
);
}
}
return parsedLetters.join("");
};
const pairs = (t) => {
const result = [];
for (let i = 0; i < t.length - 1; i++) {
for (let j = i; j < t.length - 1; j++) {
result.push([t[i], t[j + 1]]);
}
}
return result;
};
const perm = (a) => {
return a.length > 0 ? a.reduce(
(r, v, i) => [
...r,
...perm([...a.slice(0, i), ...a.slice(i + 1)]).map((x) => [v, ...x])
],
[]
) : [[]];
};
const rotateArrayTimes = (array, n) => {
let i = 0;
const na = Math.abs(n);
while (i < na) {
if (n > 0) {
array.push(array.shift());
} else {
array.unshift(array.pop());
}
i++;
}
return array;
};
const rotateArray = (array, until) => {
while (until(array, array[0])) {
array.push(array.shift());
}
return array;
};
const rotateArrayBack = (array, until) => {
while (until(array, array.at(-1))) {
array.unshift(array.pop());
}
return array;
};
const usingMap = (map) => (key) => map[key];
const vectorsToMatrix = (vects) => {
const boundingBox = array_polyfill.BoundingBox.fromVectors(vects);
const matrix = [];
for (let y = boundingBox.top; y <= boundingBox.bottom; y++) {
const row = [];
for (let x = boundingBox.left; x <= boundingBox.right; x++) {
if (vects.some((v) => v.x === x && v.y === y)) {
row.push("#");
} else {
row.push(".");
}
}
matrix.push(row);
}
return {
matrix,
boundingBox
};
};
exports.A_LETTER_BIG = A_LETTER_BIG;
exports.A_LETTER_SMALL = A_LETTER_SMALL;
exports.B_LETTER_BIG = B_LETTER_BIG;
exports.B_LETTER_SMALL = B_LETTER_SMALL;
exports.C_LETTER_BIG = C_LETTER_BIG;
exports.C_LETTER_SMALL = C_LETTER_SMALL;
exports.D_UNVERIFIED_LETTER_BIG = D_UNVERIFIED_LETTER_BIG;
exports.D_UNVERIFIED_LETTER_SMALL = D_UNVERIFIED_LETTER_SMALL;
exports.E_LETTER_BIG = E_LETTER_BIG;
exports.E_LETTER_SMALL = E_LETTER_SMALL;
exports.F_LETTER_BIG = F_LETTER_BIG;
exports.F_LETTER_SMALL = F_LETTER_SMALL;
exports.G_LETTER_BIG = G_LETTER_BIG;
exports.G_LETTER_SMALL = G_LETTER_SMALL;
exports.H_LETTER_BIG = H_LETTER_BIG;
exports.H_LETTER_SMALL = H_LETTER_SMALL;
exports.I_LETTER_SMALL = I_LETTER_SMALL;
exports.I_UNVERIFIED_LETTER_BIG = I_UNVERIFIED_LETTER_BIG;
exports.J_LETTER_BIG = J_LETTER_BIG;
exports.J_LETTER_SMALL = J_LETTER_SMALL;
exports.K_LETTER_BIG = K_LETTER_BIG;
exports.K_LETTER_SMALL = K_LETTER_SMALL;
exports.L_LETTER_BIG = L_LETTER_BIG;
exports.L_LETTER_SMALL = L_LETTER_SMALL;
exports.MATRIX_ALPHABET_BIG = MATRIX_ALPHABET_BIG;
exports.MATRIX_ALPHABET_SMALL = MATRIX_ALPHABET_SMALL;
exports.M_UNVERIFIED_LETTER_BIG = M_UNVERIFIED_LETTER_BIG;
exports.M_UNVERIFIED_LETTER_SMALL = M_UNVERIFIED_LETTER_SMALL;
exports.N_LETTER_BIG = N_LETTER_BIG;
exports.N_UNVERIFIED_LETTER_SMALL = N_UNVERIFIED_LETTER_SMALL;
exports.O_LETTER_SMALL = O_LETTER_SMALL;
exports.O_UNVERIFIED_LETTER_BIG = O_UNVERIFIED_LETTER_BIG;
exports.P_LETTER_BIG = P_LETTER_BIG;
exports.P_LETTER_SMALL = P_LETTER_SMALL;
exports.Q_UNVERIFIED_LETTER_BIG = Q_UNVERIFIED_LETTER_BIG;
exports.Q_UNVERIFIED_LETTER_SMALL = Q_UNVERIFIED_LETTER_SMALL;
exports.R_LETTER_BIG = R_LETTER_BIG;
exports.R_LETTER_SMALL = R_LETTER_SMALL;
exports.S_LETTER_SMALL = S_LETTER_SMALL;
exports.S_UNVERIFIED_LETTER_BIG = S_UNVERIFIED_LETTER_BIG;
exports.T_UNVERIFIED_LETTER_BIG = T_UNVERIFIED_LETTER_BIG;
exports.T_UNVERIFIED_LETTER_SMALL = T_UNVERIFIED_LETTER_SMALL;
exports.UPPERCASE_ALPHABET = UPPERCASE_ALPHABET;
exports.U_LETTER_SMALL = U_LETTER_SMALL;
exports.U_UNVERIFIED_LETTER_BIG = U_UNVERIFIED_LETTER_BIG;
exports.V_UNVERIFIED_LETTER_BIG = V_UNVERIFIED_LETTER_BIG;
exports.V_UNVERIFIED_LETTER_SMALL = V_UNVERIFIED_LETTER_SMALL;
exports.W_UNVERIFIED_LETTER_BIG = W_UNVERIFIED_LETTER_BIG;
exports.W_UNVERIFIED_LETTER_SMALL = W_UNVERIFIED_LETTER_SMALL;
exports.X_LETTER_BIG = X_LETTER_BIG;
exports.X_UNVERIFIED_LETTER_SMALL = X_UNVERIFIED_LETTER_SMALL;
exports.Y_LETTER_SMALL = Y_LETTER_SMALL;
exports.Y_UNVERIFIED_LETTER_BIG = Y_UNVERIFIED_LETTER_BIG;
exports.Z_LETTER_BIG = Z_LETTER_BIG;
exports.Z_LETTER_SMALL = Z_LETTER_SMALL;
exports.chunksOfArray = chunksOfArray;
exports.copyMatrix = copyMatrix;
exports.createTileMatrixFromMap = createTileMatrixFromMap;
exports.drawMapStatic = drawMapStatic;
exports.findCorners = findCorners;
exports.generateStringTile = generateStringTile;
exports.getMatrixAlphabet = getMatrixAlphabet;
exports.getRowRenderedAlphabet = getRowRenderedAlphabet;
exports.integerLength = integerLength;
exports.integerLengthMath = integerLengthMath;
exports.is = is;
exports.iteratorGetUntil = iteratorGetUntil;
exports.mergeTileMatrix = mergeTileMatrix;
exports.numAt = numAt;
exports.numStart = numStart;
exports.pairs = pairs;
exports.parseLetterMatrix = parseLetterMatrix;
exports.perm = perm;
exports.rotateArray = rotateArray;
exports.rotateArrayBack = rotateArrayBack;
exports.rotateArrayTimes = rotateArrayTimes;
exports.usingMap = usingMap;
exports.vectorsToMatrix = vectorsToMatrix;