diff --git a/2024/04/2024-04.run.xml b/2024/04/2024-04.run.xml new file mode 100644 index 0000000..9da70d1 --- /dev/null +++ b/2024/04/2024-04.run.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/2024/04/index.test.ts b/2024/04/index.test.ts new file mode 100644 index 0000000..9bab481 --- /dev/null +++ b/2024/04/index.test.ts @@ -0,0 +1,21 @@ +import { describe, expect, it } from 'bun:test'; +import { solveFirst, solveSecond } from './index.ts'; + +describe('2024-04', () => { + const testInput = `MMMSXXMASM +MSAMXMSMSA +AMXSXMAAMM +MSAMASMSMX +XMASAMXAMM +XXAMMXXAMA +SMSMSASXSS +SAXAMASAAA +MAMMMXMMMM +MXMXAXMASX`; + it('first', () => { + expect(solveFirst(testInput)).toBe(18); + }); + it('second', () => { + expect(solveSecond(testInput)).toBe(9); + }); +}); diff --git a/2024/04/index.ts b/2024/04/index.ts new file mode 100644 index 0000000..0886047 --- /dev/null +++ b/2024/04/index.ts @@ -0,0 +1,87 @@ +import { sumArray } from '../../utils/array.ts'; + +export function solveFirst(input: string): number { + const regex = /XMAS/g; + const regexBackwards = /SAMX/g; + + const cForwards = [...input.matchAll(regex)].length; + const cBackwards = [...input.matchAll(regexBackwards)].length; + + const rows = input.split('\n'); + const columns = rows.reduce((columns, row) => { + row + .split('') + .forEach((char, i) => (columns[i] = (columns[i] || '') + char)); + return columns; + }, []); + + const cColumns = sumArray( + columns.map( + (column) => + [...column.matchAll(regex), ...column.matchAll(regexBackwards)].length + ) + ); + + const rowCount = rows.length - 1; + + const diagonals = rows.reduce((diagonals, row, rowIndex) => { + row + .split('') + .forEach( + (char, columnIndex) => + (diagonals[columnIndex + (rowCount - rowIndex)] = + (diagonals[columnIndex + (rowCount - rowIndex)] || '') + char) + ); + return diagonals; + }, []); + + const diagonals2 = rows.reduce((diagonals, row, rowIndex) => { + row + .split('') + .forEach( + (char, columnIndex) => + (diagonals[columnIndex + rowIndex] = + (diagonals[columnIndex + rowIndex] || '') + char) + ); + return diagonals; + }, []); + + const cDiagonals = sumArray( + diagonals.map( + (column) => + [...column.matchAll(regex), ...column.matchAll(regexBackwards)].length + ) + ); + + const cDiagonals2 = sumArray( + diagonals2.map( + (column) => + [...column.matchAll(regex), ...column.matchAll(regexBackwards)].length + ) + ); + + return cForwards + cBackwards + cColumns + cDiagonals + cDiagonals2; +} + +export function solveSecond(input: string): number { + const rows = input.split('\n'); + + const rowCount = rows.length; + const columnCount = rows[0].length; + + let found = 0; + for (let y = 0; y < rowCount - 2; y++) { + for (let x = 0; x < columnCount - 2; x++) { + const diag = rows[y][x] + rows[y + 1][x + 1] + rows[y + 2][x + 2]; + const diag2 = rows[y + 2][x] + rows[y + 1][x + 1] + rows[y][x + 2]; + if ( + (diag === 'MAS' || diag === 'SAM') && + (diag2 === 'MAS' || diag2 === 'SAM') + ) { + found++; + } + } + } + + return found; +} diff --git a/2024/04/run.ts b/2024/04/run.ts new file mode 100644 index 0000000..88783cd --- /dev/null +++ b/2024/04/run.ts @@ -0,0 +1,12 @@ +import { join } from 'path'; +import { solveFirst, solveSecond } from './index.ts'; + +const input = await Bun.file(join(__dirname, 'input.txt')).text(); + +const firstAnswer = solveFirst(input); + +console.log(firstAnswer); + +const secondAnswer = solveSecond(input); + +console.log(secondAnswer);