Day 6: Guard Gallivant
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
TypeScript
The code
import fs from "fs"; enum GuardDirection { UP = "^", RIGHT = ">", DOWN = "v", LEFT = "<", }; const originalGrid: string[][] = fs.readFileSync("./06/input.txt", "utf-8") .split(/[\r\n]+/) .filter(Boolean) .map(row => row.split("")) .map(row => row.map(char => char === "." ? "" : char)); const gridWidth = originalGrid[0].length; const startingPosition = getStartPosition(originalGrid); const startingDirection = originalGrid[startingPosition.y][startingPosition.x] as GuardDirection; originalGrid[startingPosition.y][startingPosition.x] = ""; // Part 1 const grid = getGridCopy(originalGrid); doGuardMovement(grid); console.info("Part 1: " + grid.flatMap(row => row).filter(cell => cell.startsWith("X")).length); // Part 2 let part2Result = 0; for (let y = 0; y < originalGrid.length; y++) { for (let x = 0; x < originalGrid.length; x++) { if (!originalGrid[y][x].length && grid[y][x].startsWith("X")) { // Cell is empty AND was visited during part 1 => Should place an obstacle here const gridCopy = getGridCopy(originalGrid); gridCopy[y][x] = "#"; if (!doGuardMovement(gridCopy)) { part2Result++; } } } } console.info("Part 2: " + part2Result); function doGuardMovement(grid: string[][]): boolean { // Returns false if loop detected let [x, y, guard] = [startingPosition.x, startingPosition.y, startingDirection]; while (y >= 0 && y < grid.length && x >= 0 && x < gridWidth) { // Check for loop if (grid[y][x].length > 3) { return false; } grid[y][x] += "X"; // Mark each visitation with X // If there is something directly in front of you, turn right 90 degrees if (guard === GuardDirection.UP && y > 0 && grid[y - 1][x] === "#") { guard = GuardDirection.RIGHT; } else if (guard === GuardDirection.RIGHT && x < gridWidth - 1 && grid[y][x + 1] === "#") { guard = GuardDirection.DOWN; } else if (guard === GuardDirection.DOWN && y < grid.length - 1 && grid[y + 1][x] === "#") { guard = GuardDirection.LEFT; } else if (guard === GuardDirection.LEFT && x > 0 && grid[y][x - 1] === "#") { guard = GuardDirection.UP; } // Otherwise, take a step forward else if (guard === GuardDirection.UP) { y--; } else if (guard === GuardDirection.RIGHT) { x++; } else if (guard === GuardDirection.DOWN) { y++; } else if (guard === GuardDirection.LEFT) { x--; } else { throw new Error("Something went wrong"); } } return true; // Exited the grid } function getGridCopy(grid: string[][]): string[][] { return grid.map(row => [...row]); } function getStartPosition(grid: string[][]): {x: number, y: number} { for (let y = 0; y < grid.length; y++) { for (let x = 0; x < grid.length; x++) { if (Object.values(GuardDirection).some(char => grid[y][x] === char)) { return {x, y}; } } } throw new Error("Could not find starting position"); }