Files
AoC/2024/06/index.ts

134 lines
3.1 KiB
TypeScript
Raw Normal View History

2024-12-07 14:55:58 +00:00
const fs = require('fs');
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
interface Coord { x: number, y: number };
enum Dir {
Up,
Right,
Down,
Left
}
const obs: Array<Coord> = [];
let guard: { pos: Coord, dir: Dir } = { pos: { x: 0, y: 0}, dir: Dir.Up };
const keyMap: { [key: string]: (pos: Coord) => any } = {
"#": (pos: Coord) => obs.push(pos),
"^": (pos: Coord) => guard = { pos, dir: Dir.Up },
">": (pos: Coord) => guard = { pos, dir: Dir.Up },
"v": (pos: Coord) => guard = { pos, dir: Dir.Up },
"<": (pos: Coord) => guard = { pos, dir: Dir.Up },
}
let x = 0;
let y = 0;
for (let i = 0; i <= input.length; i++) {
const char = input[i];
if (char === "\n") {
y++;
x = 0;
continue;
}
if (keyMap[char]) {
keyMap[char]({ x, y });
}
x++;
}
2024-12-08 11:47:51 +00:00
const width = x;
2024-12-07 14:55:58 +00:00
const height = y + 1;
const guardStart = guard.pos;
const positions: Array<Coord> = [guard.pos];
2024-12-08 11:47:51 +00:00
function coordsMatch(a: Coord, b: Coord) {
2024-12-07 14:55:58 +00:00
return a.x === b.x && a.y === b.y;
}
function getNextPosition() {
if (guard.dir === Dir.Up) {
return { x: guard.pos.x, y: guard.pos.y - 1 };
}
if (guard.dir === Dir.Right) {
return { x: guard.pos.x + 1, y: guard.pos.y };
}
if (guard.dir === Dir.Down) {
return { x: guard.pos.x, y: guard.pos.y + 1 };
}
return { x: guard.pos.x - 1, y: guard.pos.y };
}
function rotateGuard() {
if (guard.dir === Dir.Up) {
guard.dir = Dir.Right;
} else if (guard.dir === Dir.Right) {
guard.dir = Dir.Down;
} else if (guard.dir === Dir.Down) {
guard.dir = Dir.Left;
} else {
guard.dir = Dir.Up;
}
}
function isObs(coord: Coord, otherObs: Array<Coord>|null = null) {
2024-12-08 11:47:51 +00:00
return (otherObs || obs).some((obsCoord) => coordsMatch(obsCoord, coord));
2024-12-07 14:55:58 +00:00
}
function offMap(coord: Coord) {
return coord.x >= width
|| coord.x < 0
|| coord.y >= height
|| coord.y < 0;
}
function alreadyVisited(coord: Coord) {
2024-12-08 11:47:51 +00:00
return positions.some((pos) => coordsMatch(pos, coord));
2024-12-07 14:55:58 +00:00
}
while (true) {
const nextPos = getNextPosition();
if (isObs(nextPos)) {
rotateGuard();
continue;
}
if (offMap(nextPos)) {
break;
}
guard.pos = nextPos;
if (!alreadyVisited(nextPos)) {
positions.push(nextPos);
}
}
// Part 2
let loops = 0;
positions.slice(1).forEach((pos, i) => {
console.log(Math.floor(`${i / positions.length * 100}%`));
guard.pos = guardStart;
guard.dir = Dir.Up;
const newObs = [...obs, pos];
const guardPositions: Array<string> = [];
while (true) {
const nextPos = getNextPosition();
if (isObs(nextPos, newObs)) {
rotateGuard();
continue;
}
if (offMap(nextPos)) {
break;
}
const guardPos = `${guard.pos.x},${guard.pos.y},${guard.dir}`;
if (guardPositions.includes(guardPos)) {
loops++;
break;
}
guardPositions.push(guardPos);
guard.pos = nextPos;
}
x++;
});
// End Part 2
console.log(positions.length);
console.log(loops);