diff --git a/2024/21/index.ts b/2024/21/index.ts new file mode 100644 index 0000000..2b621d9 --- /dev/null +++ b/2024/21/index.ts @@ -0,0 +1,134 @@ +const fs = require('fs'); + +const input = fs.readFileSync(__dirname + '/input.txt', 'utf8'); + +interface Coord { + x: number, + y: number, +}; + +const keyPadMap: { [key: string]: Coord } = { + A: { x: 2, y: 3 }, + '0': { x: 1, y: 3 }, + '1': { x: 0, y: 2 }, + '2': { x: 1, y: 2 }, + '3': { x: 2, y: 2 }, + '4': { x: 0, y: 1 }, + '5': { x: 1, y: 1 }, + '6': { x: 2, y: 1 }, + '7': { x: 0, y: 0 }, + '8': { x: 1, y: 0 }, + '9': { x: 2, y: 0 }, +}; + +const directionMap: { [key: string]: Coord } = { + '<': { x: 0, y: 1 }, + 'v': { x: 1, y: 1 }, + '>': { x: 2, y: 1 }, + '^': { x: 1, y: 0 }, + A: { x: 2, y: 0 }, +}; + +const permsMap: { [key: string]: Array } = { + '0,0': [], + '0,1': ['Y'], + '1,0': ['X'], + '1,1': ['XY', 'YX'], + '2,0': ['XX'], + '2,1': ['XXY', 'YXX'], + '2,2': ['XXYY', 'YYXX'], + '0,2': ['YY'], + '1,2': ['XYY', 'YYX'], + '0,3': ['YYY'], + '1,3': ['XYYY', 'YYYX'], + '2,3': ['XXYYY', 'YYYXX'], +}; + +function buttonsToPressCoords(from: Coord, to: Coord, forbidden: Coord): Array { + const dx = to.x - from.x; + const dy = to.y - from.y; + + if (dx === 0 && dy === 0) { + return ['A']; + } + + const buttons: Array> = []; + + const xArrow = dx < 0 ? '<' : '>'; + const yArrow = dy < 0 ? '^' : 'v'; + + const absX = Math.abs(dx); + const absY = Math.abs(dy); + const perms: Array = permsMap[`${absX},${absY}`]; + + return perms.map((seq: string) => { + return seq.split('').map((xy) => xy === 'X' ? xArrow : yArrow); + }).filter((seq: Array) => { + let coord = { x: from.x, y: from.y }; + for (let arrow of seq) { + if (arrow === '<') { + coord.x--; + } else if (arrow === '>') { + coord.x++ + } else if (arrow === '^') { + coord.y--; + } else { + coord.y++; + } + if (coord.x === forbidden.x && coord.y === forbidden.y) { + return false; + } + } + return true; + }).map((seq) => [...seq, 'A'].join('')); +} + +function buttonsForSequence(start: Coord, seq: string, keyMap: { [key: string]: Coord }): Array { + let allPerms = []; + const buttons = []; + for (let ch of seq) { + const to = keyMap[ch]; + const keyPerms = buttonsToPressCoords(start, to, keyMap === keyPadMap ? { x: 0, y: 3 } : { x: 0, y: 0 }); + allPerms.push(keyPerms); + start = to; + } + return allPerms.reduce((buttons, perms) => { + if (!buttons.length) { + return perms; + } + if (!perms.length) { + return buttons; + } + return buttons.flatMap((button) => { + return perms.map((perm) => button + perm); + }); + }, []); +} + +let sum = 0; + +input.split("\n").forEach((seq: string) => { + let buttons = buttonsForSequence(keyPadMap.A, seq, keyPadMap); + for (let i = 0; i < 2; i++) { + buttons = buttons.flatMap((seq) => { + return buttonsForSequence(directionMap.A, seq, directionMap); + }); + } + + let shortestLength: number = buttons[0].length; + let shortest = buttons[0]; + buttons.forEach((perm) => { + if (perm.length < shortestLength) { + shortestLength = perm.length; + shortest = perm; + } + }) + + const seqNum = parseInt(seq.substring(-1)); + console.log(seq); + console.log(shortest); + console.log(seqNum, shortestLength); + sum += (seqNum * shortestLength); +}); + +console.log(sum); \ No newline at end of file