|
| 1 | +type Paths = Record<string, Record<string, string>>; |
| 2 | + |
| 3 | +const numericKeypadPaths: Paths = Object.fromEntries( |
| 4 | + [ |
| 5 | + ["", "^<", "^", "^>", "^^<", "^^", "^^>", "^^^<", "^^^", "^^^>", ">"], |
| 6 | + [">v", "", ">", ">>", "^", "^>", "^>>", "^^", "^^>", "^^>>", ">>v"], |
| 7 | + ["v", "<", "", ">", "<^", "^", "^>", "<^^", "^^", "^^>", "v>"], |
| 8 | + ["<v", "<<", "<", "", "<<^", "<^", "^", "<<^^", "<^^", "^^", "v"], |
| 9 | + [">vv", "v", "v>", "v>>", "", ">", ">>", "^", "^>", "^>>", ">>vv"], |
| 10 | + ["vv", "<v", "v", "v>", "<", "", ">", "<^", "^", "^>", "vv>"], |
| 11 | + ["<vv", "<<v", "<v", "v", "<<", "<", "", "<<^", "<^", "^", "vv"], |
| 12 | + [">vvv", "vv", "vv>", "vv>>", "v", "v>", "v>>", "", ">", ">>", ">>vvv"], |
| 13 | + ["vvv", "<vv", "vv", "vv>", "<v", "v", "v>", "<", "", ">", "vvv>"], |
| 14 | + ["<vvv", "<<vv", "<vv", "vv", "<<v", "<v", "v", "<<", "<", "", "vvv"], |
| 15 | + ["<", "^<<", "<^", "^", "^^<<", "<^^", "^^", "^^^<<", "<^^^", "^^^", ""], |
| 16 | + ].map((row, u) => [ |
| 17 | + u.toString(11).toUpperCase(), |
| 18 | + Object.fromEntries(row.map((p, v) => [v.toString(11).toUpperCase(), p])), |
| 19 | + ]), |
| 20 | +); |
| 21 | + |
| 22 | +const directionalKeypadPaths: Paths = { |
| 23 | + "^": { "^": "", "v": "v", "<": "v<", ">": "v>", "A": ">" }, |
| 24 | + "v": { "^": "^", "v": "", "<": "<", ">": ">", "A": "^>" }, |
| 25 | + "<": { "^": ">^", "v": ">", "<": "", ">": ">>", "A": ">>^" }, |
| 26 | + ">": { "^": "<^", "v": "<", "<": "<<", ">": "", "A": "^" }, |
| 27 | + "A": { "^": "<", "v": "<v", "<": "v<<", ">": "v", "A": "" }, |
| 28 | +}; |
| 29 | + |
| 30 | +function findShortestSequenceLength( |
| 31 | + code: string, |
| 32 | + depth: number, |
| 33 | + { |
| 34 | + paths = numericKeypadPaths, |
| 35 | + seen = new Map<`${number},${string}`, number>(), |
| 36 | + } = {}, |
| 37 | +): number { |
| 38 | + if (depth < 0) return code.length; |
| 39 | + const hash = `${depth},${code}` as const; |
| 40 | + if (seen.has(hash)) return seen.get(hash)!; |
| 41 | + let result = 0; |
| 42 | + let pointer = "A"; |
| 43 | + const options = { paths: directionalKeypadPaths, seen }; |
| 44 | + for (const char of code) { |
| 45 | + result += findShortestSequenceLength( |
| 46 | + `${paths[pointer][char]}A`, |
| 47 | + depth - 1, |
| 48 | + options, |
| 49 | + ); |
| 50 | + pointer = char; |
| 51 | + } |
| 52 | + seen.set(hash, result); |
| 53 | + return result; |
| 54 | +} |
| 55 | + |
| 56 | +export default function solve(input: string, { depth = 25 } = {}) { |
| 57 | + const codes = input.split("\n"); |
| 58 | + let sum = 0; |
| 59 | + for (const code of codes) { |
| 60 | + sum += findShortestSequenceLength(code, depth) * parseInt(code); |
| 61 | + } |
| 62 | + return sum; |
| 63 | +} |
0 commit comments