Files
AoC/2024/15/index2.ts
2024-12-15 11:29:00 +00:00

184 lines
5.0 KiB
TypeScript

const fs = require('fs');
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
interface Coord {
x: number,
y: number,
};
let [mapStr, movementsStr] = input.split("\n\n");
mapStr = mapStr.replace(/([#.])/g, '$1$1').replaceAll('O', '[]').replaceAll('@', '@.');
const map: Array<Array<string>> = mapStr.split("\n").map((row: string) => row.split(''))
const movements = movementsStr.split("\n").join('');
const width = map[0].length;
const height = map.length;
const robotIndex = mapStr.indexOf('@');
let robotPos = { x: robotIndex % (width + 1), y: Math.floor(robotIndex / width) };
map[robotPos.y][robotPos.x] = '.';
function nextCoord(pos: Coord, dir: '^'|'>'|'<'|'v'): Coord {
return {
"^": { x: pos.x, y: pos.y - 1 },
">": { x: pos.x + 1, y: pos.y },
"v": { x: pos.x, y: pos.y + 1 },
"<": { x: pos.x - 1, y: pos.y },
}[dir];
}
function printMap() {
const mapClone = map.slice().map((row: Array<string>) => row.slice());
mapClone[robotPos.y][robotPos.x] = '@';
console.log(mapClone.map((row: Array<string>) => row.join('')).join("\n"));
}
printMap();
function get(coord: Coord) {
return map[coord.y][coord.x];
}
function set(coord: Coord, val: string) {
return map[coord.y][coord.x] = val;
}
function canPushBox(leftPart: Coord, dir: '^'|'>'|'<'|'v'): boolean {
if (dir === '<') {
const next = nextCoord(leftPart, dir);
const val = get(next);
if (val === '#') {
return false;
}
if (val === ']') {
const movedNext = canPushBox(nextCoord(next, dir)!, dir);
if (!movedNext) {
return false;
}
}
return true;
}
const rightPart = nextCoord(leftPart, '>');
if (dir === '>') {
const next = nextCoord(rightPart, dir);
const val = get(next);
if (val === '#') {
return false;
}
if (val === '[') {
const movedNext = canPushBox(next, dir);
if (!movedNext) {
return false;
}
}
return true;
}
const nextLeft = nextCoord(leftPart, dir);
const nextRight = nextCoord(rightPart, dir);
const nextLeftVal = get(nextLeft);
const nextRightVal = get(nextRight);
if (nextLeftVal === '#' || nextRightVal === '#') {
return false;
}
if (nextLeftVal === '[' || nextLeftVal === ']') {
const movedNext = canPushBox(nextLeftVal === '[' ? nextLeft : nextCoord(nextLeft, '<'), dir);
if (!movedNext) {
return false;
}
}
if (nextRightVal === '[') {
const movedNext = canPushBox(nextRight, dir);
if (!movedNext) {
return false;
}
}
return true;
}
function pushBox(leftPart: Coord, dir: '^'|'>'|'<'|'v') {
if (dir === '<') {
const next = nextCoord(leftPart, dir);
const val = get(next);
if (val === ']') {
pushBox(nextCoord(next, dir)!, dir);
}
set(next, '[');
set(leftPart, ']');
set(nextCoord(leftPart, '>')!, '.');
return;
}
const rightPart = nextCoord(leftPart, '>');
if (dir === '>') {
const next = nextCoord(rightPart, dir);
const val = get(next);
if (val === '[') {
pushBox(next, dir);
}
set(rightPart, '[');
set(next, ']');
set(leftPart, '.');
return;
}
const nextLeft = nextCoord(leftPart, dir);
const nextRight = nextCoord(rightPart, dir);
const nextLeftVal = get(nextLeft);
const nextRightVal = get(nextRight);
if (nextLeftVal === '[' || nextLeftVal === ']') {
pushBox(nextLeftVal === '[' ? nextLeft : nextCoord(nextLeft, '<'), dir);
}
if (nextRightVal === '[') {
pushBox(nextRight, dir);
}
set(nextLeft, '[');
set(nextRight, ']');
set(leftPart, '.');
set(rightPart, '.');
}
function sleep() {
const promise: Promise<void> = new Promise((resolve) => {
setTimeout(() => resolve(), 50);
});
return promise;
}
async function go() {
for (let i = 0; i < movements.length; i++) {
const direction = movements[i];
const nextRobotPosition = nextCoord(robotPos, direction);
let value = get(nextRobotPosition);
if (value === '#') {
printMap();
continue;
}
if (value === '[' || value === ']') {
const leftBoxCoord = value === '[' ? nextRobotPosition : nextCoord(nextRobotPosition, '<');
if (canPushBox(leftBoxCoord, direction)) {
pushBox(leftBoxCoord, direction);
} else {
printMap();
continue;
}
}
robotPos = nextRobotPosition;
printMap();
await sleep();
}
let sum = 0;
map.forEach((row, y) => {
row.forEach((val, x) => {
if (val === '[') {
sum += ((y * 100) + x);
}
});
});
console.log(sum);
}
go();