Solve 2024-21
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="2024-21" type="BunRunConfiguration">
|
||||
<option name="program" value="2024/21/run.ts" />
|
||||
<option name="workingDirectory" value="$PROJECT_DIR$" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -0,0 +1,13 @@
|
||||
import { describe, expect, it } from 'bun:test';
|
||||
import { solveFirst } from './index.ts';
|
||||
|
||||
describe('2024-21', () => {
|
||||
it('first', () => {
|
||||
const testInput = `029A
|
||||
980A
|
||||
179A
|
||||
456A
|
||||
379A`;
|
||||
expect(solveFirst(testInput)).toBe(126384);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,120 @@
|
||||
import { sumBy } from '../../utils/array.ts';
|
||||
import {
|
||||
type Coordinate,
|
||||
type Coordinates,
|
||||
findCoordsOfDigit
|
||||
} from '../../utils/coordinates.ts';
|
||||
|
||||
const DIRS = [
|
||||
// up
|
||||
[0, -1],
|
||||
// right
|
||||
[1, 0],
|
||||
// down
|
||||
[0, 1],
|
||||
// left
|
||||
[-1, 0]
|
||||
] as Coordinates;
|
||||
|
||||
const DIRS_LIT = ['^', '>', 'v', '<'];
|
||||
const numPad = ['789', '456', '123', '#0A'];
|
||||
const dirPad = ['#^A', '<v>'];
|
||||
|
||||
const findShortestPaths = (pad: string[], startVal: string, endVal: string) => {
|
||||
const start = findCoordsOfDigit(pad, startVal === '^' ? /\^/g : startVal)[0];
|
||||
const stack: {
|
||||
p: Coordinate;
|
||||
path: string[];
|
||||
cost: number;
|
||||
dirId?: number;
|
||||
}[] = [{ p: start, path: [], cost: 0 }];
|
||||
const seen: Map<string, number> = new Map();
|
||||
const paths: string[][] = [];
|
||||
let minCost = Infinity;
|
||||
|
||||
while (stack.length) {
|
||||
const {
|
||||
cost,
|
||||
dirId,
|
||||
p: [x, y],
|
||||
path
|
||||
} = stack.shift()!;
|
||||
if (dirId !== undefined) {
|
||||
path.push(DIRS_LIT[dirId]);
|
||||
}
|
||||
if (pad[y]?.[x] === endVal) {
|
||||
if (cost < minCost) {
|
||||
paths.length = 0;
|
||||
minCost = cost;
|
||||
}
|
||||
if (cost === minCost) paths.push(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
const k = `${x}_${y}`;
|
||||
if ((seen.get(k) || Infinity) < cost) {
|
||||
continue;
|
||||
}
|
||||
seen.set(k, cost);
|
||||
if (cost > minCost) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DIRS.forEach(([dx, dy], dirId) => {
|
||||
const [px, py] = [x + dx, y + dy];
|
||||
if (pad[py]?.[px] === '#') {
|
||||
return;
|
||||
}
|
||||
stack.push({
|
||||
path: [...path],
|
||||
p: [px, py],
|
||||
dirId,
|
||||
cost: cost + 1
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return paths.map((p) => p.join('') + 'A');
|
||||
};
|
||||
|
||||
const execute = (
|
||||
pad: string[],
|
||||
code: string,
|
||||
depth: number,
|
||||
memo: Map<string, number> = new Map()
|
||||
) => {
|
||||
const k = `${code}_${depth}`;
|
||||
const saved = memo.get(k);
|
||||
if (saved !== undefined) return saved;
|
||||
|
||||
let curPos = 'A';
|
||||
let length = 0;
|
||||
|
||||
for (const nextPos of code.split('')) {
|
||||
const paths = findShortestPaths(pad, curPos, nextPos);
|
||||
if (depth === 0) {
|
||||
length += paths[0].length;
|
||||
} else {
|
||||
length += Math.min(
|
||||
...paths.map((path) => execute(dirPad, path, depth - 1, memo))
|
||||
);
|
||||
}
|
||||
curPos = nextPos;
|
||||
}
|
||||
|
||||
memo.set(k, length);
|
||||
return length;
|
||||
};
|
||||
export function solveFirst(input: string): number {
|
||||
return sumBy(
|
||||
input.split('\n'),
|
||||
(code) => parseInt(code) * execute(numPad, code, 2)
|
||||
);
|
||||
}
|
||||
|
||||
export function solveSecond(input: string): number {
|
||||
return sumBy(
|
||||
input.split('\n'),
|
||||
(code) => parseInt(code) * execute(numPad, code, 25)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { join } from 'path';
|
||||
import { solveFirst, solveSecond } from './index.ts';
|
||||
|
||||
const input = await Bun.file(join(__dirname, 'input.txt')).text();
|
||||
|
||||
const firstAnswer = solveFirst(input);
|
||||
|
||||
console.log(firstAnswer);
|
||||
|
||||
const secondAnswer = solveSecond(input);
|
||||
|
||||
console.log(secondAnswer);
|
||||
Reference in New Issue
Block a user