105 lines
2.5 KiB
TypeScript
105 lines
2.5 KiB
TypeScript
|
export type Map = string[][];
|
||
|
|
||
|
export type Move = "^" | "v" | "<" | ">";
|
||
|
|
||
|
export async function readData(path: string): Promise<{
|
||
|
map: Map,
|
||
|
moves: Move[]
|
||
|
}> {
|
||
|
const text = await Deno.readTextFile(path);
|
||
|
const [
|
||
|
map,
|
||
|
moves
|
||
|
] = text.split("\n\n");
|
||
|
return {
|
||
|
map: map.split("\n").map((line) => line.split("")),
|
||
|
moves: moves.split("\n").join("").split("").map((move) => move as Move)
|
||
|
};
|
||
|
}
|
||
|
|
||
|
export function displayMap(map: Map): string {
|
||
|
return map.map((line) => line.join("")).join("\n");
|
||
|
}
|
||
|
|
||
|
export function foreachMap(map: Map, callback: (value: string, x: number, y: number) => void): void {
|
||
|
map.forEach((line, y) => {
|
||
|
line.forEach((value, x) => {
|
||
|
callback(value, x, y);
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
export const dirToDelta = {
|
||
|
"^": [0, -1],
|
||
|
"v": [0, 1],
|
||
|
"<": [-1, 0],
|
||
|
">": [1, 0]
|
||
|
}
|
||
|
|
||
|
export function stepRobot(map: Map, robot: {x: number, y: number}, move: Move): void {
|
||
|
const {x, y} = robot;
|
||
|
const [dx, dy] = dirToDelta[move];
|
||
|
// Check if the robot can move
|
||
|
|
||
|
// like socoban, @ is the robot, # is a wall, . is a free space, O is a box
|
||
|
// multiple boxes can be pushed at the same time
|
||
|
let nextX = x;
|
||
|
let nextY = y;
|
||
|
while (true) {
|
||
|
nextX += dx;
|
||
|
nextY += dy;
|
||
|
const nextValue = map[nextY][nextX];
|
||
|
if (nextValue === "#") {
|
||
|
// The robot can't move
|
||
|
return;
|
||
|
}
|
||
|
else if (nextValue === ".") {
|
||
|
break;
|
||
|
}
|
||
|
if (nextValue === "O") {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
let prevX = nextX;
|
||
|
let prevY = nextY;
|
||
|
// move the boxes
|
||
|
while (prevX !== x || prevY !== y) {
|
||
|
map[prevY][prevX] = map[prevY - dy][prevX - dx];
|
||
|
prevX -= dx;
|
||
|
prevY -= dy;
|
||
|
}
|
||
|
// move the robot
|
||
|
map[y][x] = ".";
|
||
|
robot.x = x + dx;
|
||
|
robot.y = y + dy;
|
||
|
}
|
||
|
|
||
|
if (import.meta.main) {
|
||
|
const {map, moves} = await readData("input.txt");
|
||
|
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, ":");
|
||
|
stepRobot(map, robot, move);
|
||
|
// console.log(displayMap(map));
|
||
|
});
|
||
|
let sum = 0;
|
||
|
foreachMap(map, (value, x, y) => {
|
||
|
if (value === "O") {
|
||
|
sum += x + y * 100;
|
||
|
}
|
||
|
});
|
||
|
console.log("Sum", sum);
|
||
|
}
|