aoc-2024/day_15/solve_2.ts
2024-12-15 21:13:11 +09:00

188 lines
5.1 KiB
TypeScript

import { displayMap, foreachMap, Map, Move, readData } from "./solve_1.ts";
const extendingTranslation = {
"#": "##",
".": "..",
"O": "[]",
"@": "@.",
};
function extendMap(map: Map) {
const extendedMap = map.map((row) => {
return row.map((value) => {
const v = extendingTranslation[
value as keyof typeof extendingTranslation
];
if (v) {
return v;
}
throw new Error("Invalid value");
}).join("").split("");
});
return extendedMap;
}
function getHugeBoxPos(map: Map, boxPos: [number, number]): [number, number] {
const [x, y] = boxPos;
const anyBracket = map[y][x];
if (anyBracket === "]") {
return [x - 1, y];
}
if (anyBracket === "[") {
return [x, y];
}
throw new Error("Not a huge box");
}
function IsMovableHugeBox(
map: Map,
boxPos: [number, number],
move: Move,
): boolean {
const [x, y] = getHugeBoxPos(map, boxPos);
if (move === "^" || move === "v") {
const dy = move === "^" ? -1 : 1;
if (map[y + dy][x] === "#" || map[y + dy][x + 1] === "#") {
return false;
}
if (map[y + dy][x] === "." && map[y + dy][x + 1] === ".") {
return true;
}
if (map[y + dy][x] === "]") {
const success = IsMovableHugeBox(map, [x, y + dy], move);
if (!success) {
return false;
}
} else if (map[y + dy][x] === "[") {
const success = IsMovableHugeBox(map, [x, y + dy], move);
if (!success) {
return false;
}
}
if (map[y + dy][x + 1] === "[") {
const success = IsMovableHugeBox(map, [x + 1, y + dy], move);
if (!success) {
return false;
}
}
return true;
} else {
const dx = move === "<" ? -1 : 2;
const [nx, ny] = [x + dx, y];
if (map[ny][nx] === "#") {
return false;
}
if (map[ny][nx] === ".") {
return true;
}
return IsMovableHugeBox(map, [nx, ny], move);
}
}
function pushHugeBox(map: Map, boxPos: [number, number], move: Move) {
const [x, y] = getHugeBoxPos(map, boxPos);
if (move === "^" || move === "v") {
const dy = move === "^" ? -1 : 1;
if (map[y + dy][x] === "]") {
pushHugeBox(map, [x, y + dy], move);
} else if (map[y + dy][x] === "[") {
pushHugeBox(map, [x, y + dy], move);
}
if (map[y + dy][x + 1] === "[") {
pushHugeBox(map, [x + 1, y + dy], move);
}
if (map[y + dy][x] === "." && map[y + dy][x + 1] === ".") {
map[y][x] = ".";
map[y][x + 1] = ".";
map[y + dy][x] = "[";
map[y + dy][x + 1] = "]";
return;
} else {
throw new Error("can't push the box");
}
} else {
if (map[y][x - 1] === "]" && move === "<") {
pushHugeBox(map, [x - 1, y], move);
}
if (map[y][x + 2] === "[" && move === ">") {
pushHugeBox(map, [x + 2, y], move);
}
const dx = move === "<" ? -1 : 1;
const nx = x + dx;
if (
(move === "<" && map[y][nx] === ".") ||
(move === ">" && map[y][nx + 1] === ".")
) {
map[y][x] = ".";
map[y][x + 1] = ".";
map[y][nx] = "[";
map[y][nx + 1] = "]";
return;
} else {
throw new Error("can't push the box");
}
}
}
function stepRobot(map: Map, robot: { x: number; y: number }, move: Move) {
const { x, y } = robot;
const dx = move === "<" ? -1 : move === ">" ? 1 : 0;
const dy = move === "^" ? -1 : move === "v" ? 1 : 0;
const nx = x + dx;
const ny = y + dy;
if (map[ny][nx] === "#") {
return;
}
if (map[ny][nx] === "[" || map[ny][nx] === "]") {
const [hx, hy] = getHugeBoxPos(map, [nx, ny]);
if (IsMovableHugeBox(map, [hx, hy], move)) {
pushHugeBox(map, [hx, hy], move);
} else {
return;
}
}
map[y][x] = ".";
map[ny][nx] = "@";
robot.x = nx;
robot.y = ny;
}
if (import.meta.main) {
let { map, moves } = await readData("input.txt");
console.log(displayMap(map));
map = extendMap(map);
let robot = {
x: 0,
y: 0,
};
foreachMap(map, (value, x, y) => {
if (value === "@") {
robot = {
x,
y,
};
}
});
console.log("Robot", robot);
console.log(displayMap(map));
moves.forEach((move) => {
// console.log("Move", move, ":");
try {
stepRobot(map, robot, move);
} catch (_e) {
console.log("Move", move, ":");
console.log(displayMap(map));
}
// console.log(displayMap(map));
});
let sum = 0;
foreachMap(map, (value, x, y) => {
if (value === "[") {
sum += x + y * 100;
}
});
console.log(displayMap(map));
console.log("Sum", sum);
}