134 lines
3.5 KiB
TypeScript
134 lines
3.5 KiB
TypeScript
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<string> } = {
|
|
'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<string> {
|
|
const dx = to.x - from.x;
|
|
const dy = to.y - from.y;
|
|
|
|
if (dx === 0 && dy === 0) {
|
|
return ['A'];
|
|
}
|
|
|
|
const buttons: Array<Array<string>> = [];
|
|
|
|
const xArrow = dx < 0 ? '<' : '>';
|
|
const yArrow = dy < 0 ? '^' : 'v';
|
|
|
|
const absX = Math.abs(dx);
|
|
const absY = Math.abs(dy);
|
|
const perms: Array<string> = permsMap[`${absX},${absY}`];
|
|
|
|
return perms.map((seq: string) => {
|
|
return seq.split('').map((xy) => xy === 'X' ? xArrow : yArrow);
|
|
}).filter((seq: Array<string>) => {
|
|
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<string> {
|
|
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); |