import fs from "node:fs"; const DIRECTIONS = { UP: "up", DOWN: "down", LEFT: "left", RIGHT: "right", }; function rotate(currentDir) { switch (currentDir) { case DIRECTIONS.UP: return DIRECTIONS.RIGHT; case DIRECTIONS.RIGHT: return DIRECTIONS.DOWN; case DIRECTIONS.DOWN: return DIRECTIONS.LEFT; case DIRECTIONS.LEFT: return DIRECTIONS.UP; } } function getInput() { const data = fs .readFileSync("input2.txt", "utf8") .split("\n") .map((line) => line.split("")); return data; } function getStart(data) { const HEIGHT = data.length; let actualPos = { x: 0, y: 0 }; for (let y = 0; y < HEIGHT; y++) { const x = data[y].indexOf("^"); if (x == -1) continue; actualPos.y = y; actualPos.x = x; } return actualPos; } function detectLoop(obstacle) { let data = getInput(); data[obstacle[0]][obstacle[1]] = "#"; let currentDir = DIRECTIONS.UP; let actualPos = getStart(data); data[actualPos.y][actualPos.x] = "."; let counter = 1; let nextStep = null; let newX = null; let newY = null; while (true) { switch (currentDir) { case DIRECTIONS.UP: newY = actualPos.y - 1; newX = actualPos.x; break; case DIRECTIONS.DOWN: newY = actualPos.y + 1; newX = actualPos.x; break; case DIRECTIONS.LEFT: newY = actualPos.y; newX = actualPos.x - 1; break; case DIRECTIONS.RIGHT: newY = actualPos.y; newX = actualPos.x + 1; break; } nextStep = (data[newY] ?? [])[newX]; if (nextStep == undefined) return false; if (nextStep == ".") { // data[newY][newX] = "X"; actualPos.y = newY; actualPos.x = newX; counter++; if (counter >= 20000) return true; } else { currentDir = rotate(currentDir); } } } function part1(data = getInput()) { let currentDir = DIRECTIONS.UP; let actualPos = getStart(data); data[actualPos.y][actualPos.x] = "X"; // Start algorithm let counter = 1; let nextStep = null; let newX = null; let newY = null; while (true) { switch (currentDir) { case DIRECTIONS.UP: newY = actualPos.y - 1; newX = actualPos.x; break; case DIRECTIONS.DOWN: newY = actualPos.y + 1; newX = actualPos.x; break; case DIRECTIONS.LEFT: newY = actualPos.y; newX = actualPos.x - 1; break; case DIRECTIONS.RIGHT: newY = actualPos.y; newX = actualPos.x + 1; break; } nextStep = (data[newY] ?? [])[newX]; if (nextStep == undefined) break; if (nextStep == ".") { data[newY][newX] = "X"; actualPos.y = newY; actualPos.x = newX; counter++; } else if (nextStep == "X") { actualPos.y = newY; actualPos.x = newX; } else { currentDir = rotate(currentDir); } } console.log(counter); // print board // console.log(data.map((line) => line.join("")).join("\n")); } function part2() { let data = getInput(); let actualPos = getStart(data); let possibleObstacle = []; for (let y in data) { for (let x in data) { if (data[y][x] == "." || (y != actualPos.y && x != actualPos.x)) { possibleObstacle.push([y, x]); } } } let counter = 0; for (const obstacle of possibleObstacle) { let innerData = getInput(); if (detectLoop(obstacle)) { counter++; } } console.log(counter); } console.log("Part 1:"); part1(); console.log("Part 2:"); part2();