diff --git a/index.ts b/index.ts index e3443c3..bf7f09c 100644 --- a/index.ts +++ b/index.ts @@ -1,3 +1,3 @@ -import {runDayTen} from "./src/day_ten"; +import {runDayFifteen} from "./src/day_fifteen"; -runDayTen(); \ No newline at end of file +runDayFifteen(); \ No newline at end of file diff --git a/src/day_fifteen.test.ts b/src/day_fifteen.test.ts new file mode 100644 index 0000000..ad8358c --- /dev/null +++ b/src/day_fifteen.test.ts @@ -0,0 +1,30 @@ +import {totalFocusingPower, hash, hashSum} from "./day_fifteen"; + +describe('Day Fifteen', () => { + it.each([ + ['HASH', 52], + ['rn=1', 30], + ['cm-', 253], + ['qp=3', 97], + ['cm=2', 47], + ['qp-', 14], + ['pc=4', 180], + ['ot=9', 9], + ['ab=5', 197], + ['pc-', 48], + ['pc=6', 214], + ['ot=7', 231], + ])('calculates the hash of %s to %s', (input, expected) => { + expect(hash(input)).toBe(expected); + }); + + it('calculates the hash of the example', () => { + const input = 'rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7'; + expect(hashSum(input)).toEqual(1320); + }); + + it('calculates the focusing power', () => { + const input = 'rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7'; + expect(totalFocusingPower(input)).toEqual(145); + }) +}); \ No newline at end of file diff --git a/src/day_fifteen.ts b/src/day_fifteen.ts new file mode 100644 index 0000000..6185ea1 --- /dev/null +++ b/src/day_fifteen.ts @@ -0,0 +1,57 @@ +import fs from "fs"; + +export const hash = (input: string): number => { + const parts = input.split(''); + let hash = 0; + for (let i = 0; i < parts.length; i++) { + hash += parts[i].charCodeAt(0); + hash *= 17; + hash %= 256; + } + return hash; +} + +export const hashSum = (input: string): number => { + return input.split(',').reduce((sum, part) => sum + hash(part), 0); +} + + +const focusingPower = (boxNumber: number, slot: number, value: number): number => { + return (1 + boxNumber) * (1 + slot) * value; +} + +export const totalFocusingPower = (input: string): number => { + const boxes: [string, number][][] = new Array(256).fill(0).map(() => []); + + input.split(',').forEach(part => { + if (part.includes('=')) { + const [label, value] = part.split('='); + const box = hash(label); + const index = boxes[box].findIndex(([l]) => l === label); + boxes[hash(label)].splice(index === -1 ? boxes[box].length : index, 1, [label, parseInt(value)]); + } else { + const [label] = part.split('-'); + let box = hash(label); + const index = boxes[box].findIndex(([l]) => l === label); + if (index !== -1) { + boxes[box].splice(index, 1); + } + } + }); + + return boxes.reduce( + (sum, box, boxIndex) => + sum + box.reduce( + (total, [label, value], slot) => { + return total + focusingPower(boxIndex, slot, value) + }, + 0 + ), + 0 + ); +} + +export const runDayFifteen = () => { + const input = fs.readFileSync('./inputs/day_fifteen_input.txt', 'utf-8').trimEnd(); + console.log('Day Fifteen output:', totalFocusingPower(input)); +} \ No newline at end of file