122 lines
3.5 KiB
C#
122 lines
3.5 KiB
C#
var lines = File.ReadAllLines("input.txt");
|
|
var charArray = new char[lines.Length, lines[0].Length];
|
|
Dictionary<Direction, (int dx, int dy)> 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<int[]>();
|
|
|
|
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<int[]> 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
|
|
} |