diff --git a/solutions/typescript/2023/13/src/internal/matrix-reflection.ts b/solutions/typescript/2023/13/src/internal/matrix-reflection.ts index 336a7faf3..16b4ef308 100644 --- a/solutions/typescript/2023/13/src/internal/matrix-reflection.ts +++ b/solutions/typescript/2023/13/src/internal/matrix-reflection.ts @@ -1,14 +1,8 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import type { GridGraph, GridGraphNode, Interval, ToString } from '@alexaegis/advent-of-code-lib'; - -export const matchingNodes = < - T extends ToString = string, - N extends GridGraphNode = GridGraphNode, ->( - a: N[], - b: N[], -): number => { - return a.zip(b).filter(([an, bn]) => an.value === bn.value).length; +import { Interval } from '@alexaegis/advent-of-code-lib'; + +export const matchingNodes = (a: string[], b: string[]): number => { + return a.zip(b).filter(([an, bn]) => an === bn).length; }; export const findReflectivePairings = ( @@ -24,19 +18,14 @@ export const findReflectivePairings = ( }); }; -export const findReflection = < - T extends ToString = string, - N extends GridGraphNode = GridGraphNode, ->( - gg: GridGraph, - axis: 'row' | 'column', +export const findReflection = ( + matrix: string[][], smudges = 0, skip?: number, ): number | undefined => { - const aabb = gg.boundingBox(); - const axisInterval = axis === 'column' ? aabb.horizontal : aabb.vertical; - const otherAxistInterval = axis === 'column' ? aabb.vertical : aabb.horizontal; - const getNodesOfAxis = (n: number) => (axis === 'column' ? gg.getColumn(n) : gg.getRow(n)); + const axisInterval = Interval.closed(0, matrix.length - 1); + const otherAxisInterval = Interval.closed(0, matrix[0]!.length - 1); + return axisInterval.collectValues().find((index) => { if (skip !== undefined && index === skip) { return false; @@ -50,12 +39,12 @@ export const findReflection = < const matching = pairs .map(([left, right]) => { - const leftNodes = getNodesOfAxis(left)!; - const rightNodes = getNodesOfAxis(right)!; - return matchingNodes(leftNodes, rightNodes); + const leftNodes = matrix[left]!; + const rightNodes = matrix[right]!; + return matchingNodes(leftNodes, rightNodes); }) .sum(); - return matching + smudges === pairs.length * otherAxistInterval.length; + return matching + smudges === pairs.length * otherAxisInterval.length; }); }; diff --git a/solutions/typescript/2023/13/src/p1.ts b/solutions/typescript/2023/13/src/p1.ts index 169e27de1..df1370e7c 100644 --- a/solutions/typescript/2023/13/src/p1.ts +++ b/solutions/typescript/2023/13/src/p1.ts @@ -1,24 +1,25 @@ -import { DOUBLE_NEWLINE, task } from '@alexaegis/advent-of-code-lib'; +import { DOUBLE_NEWLINE, isNotNullish, task } from '@alexaegis/advent-of-code-lib'; import packageJson from '../package.json'; import { findReflection } from './internal/matrix-reflection.js'; export const p1 = (input: string): number => input .split(DOUBLE_NEWLINE) - .map((m) => m.toGridGraph()) - .map((graph) => { - const columnReflectionIndex = findReflection(graph, 'column'); - const rowReflectionIndex = findReflection(graph, 'row'); + .map((m) => m.toMatrix()) + .map((matrix) => { + const rowWise = matrix; + const columnWise = matrix.rotateMatrix('r'); + const rowReflectionIndex = findReflection(rowWise); + const columnReflectionIndex = findReflection(columnWise); - let value = 0; - if (columnReflectionIndex !== undefined) { - value = columnReflectionIndex + 1; + if (isNotNullish(columnReflectionIndex)) { + return columnReflectionIndex + 1; + } else if (isNotNullish(rowReflectionIndex)) { + return (rowReflectionIndex + 1) * 100; + } else { + throw new Error('Reflection not found'); } - if (rowReflectionIndex !== undefined) { - value = (rowReflectionIndex + 1) * 100; - } - return value; }) .sum(); -await task(p1, packageJson.aoc); // 37718 ~371.96ms +await task(p1, packageJson.aoc); // 37718 ~2.59ms diff --git a/solutions/typescript/2023/13/src/p2.ts b/solutions/typescript/2023/13/src/p2.ts index d33b92a01..25c80721d 100644 --- a/solutions/typescript/2023/13/src/p2.ts +++ b/solutions/typescript/2023/13/src/p2.ts @@ -1,27 +1,28 @@ -import { DOUBLE_NEWLINE, task } from '@alexaegis/advent-of-code-lib'; +import { DOUBLE_NEWLINE, isNotNullish, task } from '@alexaegis/advent-of-code-lib'; import packageJson from '../package.json'; import { findReflection } from './internal/matrix-reflection.js'; -export const p2 = (input: string): number => { - return input +export const p2 = (input: string): number => + input .split(DOUBLE_NEWLINE) - .map((m) => m.toGridGraph()) - .map((graph) => { - const smudgyRowIndex = findReflection(graph, 'row'); - const smudgyColumnIndex = findReflection(graph, 'column'); - const rowIndex = findReflection(graph, 'row', 1, smudgyRowIndex); - const columnIndex = findReflection(graph, 'column', 1, smudgyColumnIndex); + .map((m) => m.toMatrix()) + .map((matrix) => { + const rowWise = matrix; + const columnWise = matrix.rotateMatrix('r'); - let value = 0; - if (columnIndex !== undefined) { - value = columnIndex + 1; - } - if (rowIndex !== undefined) { - value = (rowIndex + 1) * 100; + const smudgyRowIndex = findReflection(rowWise); + const smudgyColumnIndex = findReflection(columnWise); + const rowIndex = findReflection(rowWise, 1, smudgyRowIndex); + const columnIndex = findReflection(columnWise, 1, smudgyColumnIndex); + + if (isNotNullish(columnIndex)) { + return columnIndex + 1; + } else if (isNotNullish(rowIndex)) { + return (rowIndex + 1) * 100; + } else { + throw new Error('Reflection not found'); } - return value; }) .sum(); -}; -await task(p2, packageJson.aoc); // 40995 ~658.23ms +await task(p2, packageJson.aoc); // 40995 ~4.95ms diff --git a/solutions/typescript/libs/lib/src/string/string-to-matrix.function.ts b/solutions/typescript/libs/lib/src/string/string-to-matrix.function.ts index 38fc32d23..f1c286540 100644 --- a/solutions/typescript/libs/lib/src/string/string-to-matrix.function.ts +++ b/solutions/typescript/libs/lib/src/string/string-to-matrix.function.ts @@ -1,5 +1,11 @@ import { NEWLINE } from '../regex/index.js'; +export interface StringToMatrixOptions { + valueConverter?: ((value: string) => T) | undefined; + rowSeparator?: RegExp | string; + itemSeparator?: RegExp | string; +} + /** * Splits a string into a matrix along row and item separators. By default it * splits along new lines and every character @@ -8,15 +14,18 @@ import { NEWLINE } from '../regex/index.js'; * @param rowSeparator to split the rows apart with * @param itemSeparator to split the items apart with */ -export const stringToMatrix = ( +export const stringToMatrix = ( s: string, - rowSeparator: RegExp | string = NEWLINE, - itemSeparator: RegExp | string = '', -): string[][] => { - const lines = s.split(rowSeparator); + options?: StringToMatrixOptions, +): T[][] => { + const lines = s.split(options?.rowSeparator ?? NEWLINE); if (lines.at(-1) === '') { lines.pop(); } - const matrix = lines.map((line) => line.split(itemSeparator)); - return matrix; + const matrix = lines.map((line) => { + const values = line.split(options?.itemSeparator ?? ''); + + return options?.valueConverter ? values.map(options?.valueConverter) : values; + }); + return matrix as T[][]; }; diff --git a/solutions/typescript/libs/lib/src/string/string-to-vectormap.function.ts b/solutions/typescript/libs/lib/src/string/string-to-vectormap.function.ts index 35e558770..3de4e0154 100644 --- a/solutions/typescript/libs/lib/src/string/string-to-vectormap.function.ts +++ b/solutions/typescript/libs/lib/src/string/string-to-vectormap.function.ts @@ -11,6 +11,7 @@ export interface StringToVectorMapOptions { */ ignoreValues?: (value: V) => boolean; } + /** * Splits a string into a matrix along row and item separators. By default it * splits along new lines and every character @@ -24,7 +25,7 @@ export const stringToVectorMap = ( rawOptions?: StringToVectorMapOptions, ): Map => { const options = normalizeStringToVectorMapOptions(rawOptions); - const matrix = stringToMatrix(s, options.rowSeparator, options.itemSeparator); + const matrix = stringToMatrix(s, options); const map = new Map(); for (let y = 0; y < matrix.length; y++) { @@ -33,11 +34,8 @@ export const stringToVectorMap = ( for (let x = 0; x < row.length; x++) { const coord = new Vec2(x, y); const value = row[x]; - if (value !== undefined) { - const convertedValue = options.valueConverter?.(value) ?? (value as V); - if (!options.ignoreValues(convertedValue)) { - map.set(coord.toString(), convertedValue); - } + if (value !== undefined && !options.ignoreValues(value)) { + map.set(coord.toString(), value); } } } diff --git a/solutions/typescript/libs/lib/src/string/string.polyfill.ts b/solutions/typescript/libs/lib/src/string/string.polyfill.ts index eb12453b4..194075281 100644 --- a/solutions/typescript/libs/lib/src/string/string.polyfill.ts +++ b/solutions/typescript/libs/lib/src/string/string.polyfill.ts @@ -2,11 +2,10 @@ import { GridGraph, type GridGraphOptions } from '../model/graph/grid-graph.clas import type { ToString } from '../model/to-string.interface.js'; import type { Vec2 } from '../model/vector/vec2.class.js'; import type { Vec2String } from '../model/vector/vec2.class.types.js'; -import { NEWLINE } from '../regex/whitespace.regex.js'; import { alphabeticalOrder } from './alphabetical-order.function.js'; import { rightSplit } from './right-split.function.js'; import { splitIntoStringPair } from './split-into-tuple.function.js'; -import { stringToMatrix } from './string-to-matrix.function.js'; +import { stringToMatrix, type StringToMatrixOptions } from './string-to-matrix.function.js'; import { stringToVectorMap } from './string-to-vectormap.function.js'; import { vectorsInStringTile } from './vectors-in-string-tile.function.js'; export * from '../array/array.polyfill.js'; // `toInt` is used in `splitToInt` @@ -15,7 +14,7 @@ declare global { interface String { alphabeticalOrder(): number; toInt(radix?: number): number; - toMatrix(): string[][]; + toMatrix(options?: StringToMatrixOptions): T[][]; toGridGraph( gridOptions?: GridGraphOptions & { valueConverter?: (value: string) => T; @@ -131,11 +130,8 @@ String.prototype.splitToInt = function (options?: { }); }; -String.prototype.toMatrix = function ( - rowSeparator: RegExp | string = NEWLINE, - itemSeparator: RegExp | string = '', -): string[][] { - return stringToMatrix(this as string, rowSeparator, itemSeparator); +String.prototype.toMatrix = function (options?: StringToMatrixOptions): T[][] { + return stringToMatrix(this as string, options); }; String.prototype.vectorsOf = function (character: string, fromBottom = false): Vec2[] { diff --git a/solutions/typescript/readme.md b/solutions/typescript/readme.md index 22cc598bc..95eef3241 100644 --- a/solutions/typescript/readme.md +++ b/solutions/typescript/readme.md @@ -20,7 +20,7 @@ | [Day 10](/solutions/typescript/2023/10/) | [68.44ms](/solutions/typescript/2023/10/src/p1.ts) | [1.4s](/solutions/typescript/2023/10/src/p2.ts) | | [Day 11](/solutions/typescript/2023/11/) | [104.54ms](/solutions/typescript/2023/11/src/p1.ts) | [104.48ms](/solutions/typescript/2023/11/src/p2.ts) | | [Day 12](/solutions/typescript/2023/12/) | [30.83ms](/solutions/typescript/2023/12/src/p1.ts) | [539.06ms](/solutions/typescript/2023/12/src/p2.ts) | -| [Day 13](/solutions/typescript/2023/13/) | [371.96ms](/solutions/typescript/2023/13/src/p1.ts) | [658.23ms](/solutions/typescript/2023/13/src/p2.ts) | +| [Day 13](/solutions/typescript/2023/13/) | [2.59ms](/solutions/typescript/2023/13/src/p1.ts) | [4.95ms](/solutions/typescript/2023/13/src/p2.ts) | | [Day 14](/solutions/typescript/2023/14/) | [?ms](/solutions/typescript/2023/14/src/p1.ts) | [?ms](/solutions/typescript/2023/14/src/p2.ts) | | [Day 15](/solutions/typescript/2023/15/) | [0.19ms](/solutions/typescript/2023/15/src/p1.ts) | [0.65ms](/solutions/typescript/2023/15/src/p2.ts) | | [Day 16](/solutions/typescript/2023/16/) | [31.37ms](/solutions/typescript/2023/16/src/p1.ts) | [\~1s](/solutions/typescript/2023/16/src/p2.ts) |