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);