UNPKG

@alexaegis/advent-of-code-lib

Version:
852 lines (851 loc) 16.8 kB
"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;