var lines = File.ReadAllLines("input.txt"); var charArray = new char[lines.Length, lines[0].Length]; Dictionary moves = new() { { Direction.Up, (-1, 0) }, { Direction.Right, (0, 1) }, { Direction.Down, (1, 0) }, { Direction.Left, (0, -1) } }; var guardCurrentPosition = (0, 0); var guardDirection = Direction.Up; var visitedPositions = new List(); for (var i = 0; i < charArray.GetLength(0); i++) for (var j = 0; j < charArray.GetLength(1); j++) { if (lines[i][j] == '^') { guardCurrentPosition.Item1 = i; guardCurrentPosition.Item2 = j; visitedPositions.Add([guardCurrentPosition.Item1, guardCurrentPosition.Item2]); } charArray[i, j] = lines[i][j]; } var part1 = Part1(guardCurrentPosition, guardDirection, charArray, visitedPositions); var part2 = Part2(guardCurrentPosition, charArray); Console.WriteLine($"Part1: {part1}\nPart2: {part2}"); int Part2((int,int) currentPosition, char[,] input) { var potentialLoopPositions = new List<(int row, int col)>(); for (var i = 0; i < input.GetLength(0); i++) for (var j = 0; j < input.GetLength(1); j++) { if ((i, j) == currentPosition || input[i, j] == '#') continue; var modifiedGrid = (char[,])input.Clone(); modifiedGrid[i, j] = '#'; if (CausesLoop(currentPosition, modifiedGrid)) { potentialLoopPositions.Add((i, j)); } } return potentialLoopPositions.Count; } bool CausesLoop((int row, int col) startPosition, char[,] input) { var currentPosition = startPosition; var currentDirection = Direction.Up; var visited = new HashSet<((int row, int col), Direction)>(); visited.Add((currentPosition, currentDirection)); while (true) { var nextPosition = CalculateNextPosition(currentPosition.row, currentPosition.col, currentDirection); if (!IsValid(nextPosition.Item1, nextPosition.Item2, input)) return false; if (input[nextPosition.Item1, nextPosition.Item2] == '#') { currentDirection = (Direction)(((int)currentDirection + 1) % 4); } else { currentPosition = nextPosition; } if (!visited.Add((currentPosition, currentDirection))) { return true; } } } int Part1((int,int) currentPosition, Direction direction, char[,] input, List traveledPositions) { var nextPosition = CalculateNextPosition(currentPosition.Item1, currentPosition.Item2, direction); while (IsValid(nextPosition.Item1, nextPosition.Item2, input)) { if (IsBlocked(nextPosition.Item1, nextPosition.Item2, input)) { direction = (Direction)(((int)direction + 1) % 4); } else { currentPosition = (nextPosition.Item1, nextPosition.Item2); traveledPositions.Add([currentPosition.Item1, currentPosition.Item2]); } nextPosition = CalculateNextPosition(currentPosition.Item1, currentPosition.Item2, direction); } return traveledPositions.Select(x => $"r{x[0]},c{x[1]}").Distinct().Count(); } (int, int) CalculateNextPosition(int row, int col, Direction direction) { var (dx, dy) = moves[direction]; return (row + dx, col + dy); } bool IsValid(int row, int column, char[,] grid) => row >= 0 && row < grid.GetLength(0) && column >= 0 && column < grid.GetLength(1); bool IsBlocked(int row, int col, char[,] grid) => grid[row, col] == '#'; enum Direction { Up, Right, Down, Left }