Add day 6

This commit is contained in:
2025-01-24 10:19:11 +01:00
parent 323bb83e56
commit 9920041301
4 changed files with 324 additions and 4 deletions

194
Days/Day6.cs Normal file
View File

@@ -0,0 +1,194 @@
using System.Numerics;
using Spectre.Console;
namespace AdventOfCode.Days;
public class Day6 : Day
{
public override int Number => 6;
public override string Name => "Guard Gallivant";
private const int GridSize = 130;
private static readonly Point DirectionUp = new(0, -1);
private static readonly Point DirectionDown = new(0, 1);
private static readonly Point DirectionLeft = new(-1, 0);
private static readonly Point DirectionRight = new(1, 0);
public override void RunPart1(bool display = true)
{
HashSet<Point> visited = [];
var direction = DirectionUp;
var (obstaclesGrid, position) = ReadInputGrid();
visited.Add(position);
// Move the guard till it leaves the grid
while (true)
{
var destination = position + direction;
if (destination.X is < 0 or >= GridSize ||
destination.Y is < 0 or >= GridSize)
{
break;
}
// Check if it's possible to move or if there is an obstacle
if (obstaclesGrid[destination.X, destination.Y])
{
direction = NextDirection(direction);
continue;
}
position = destination;
visited.Add(position);
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Amount of distinct positions: [yellow]{visited.Count}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
var possibleLoops = 0;
var (initialGrid, startPosition) = ReadInputGrid();
for (var y = 0; y < GridSize; y++)
{
for (var x = 0; x < GridSize; x++)
{
// Store obstacle state
var initialState = initialGrid[x, y];
// Check if grid is a loop after adding an obstacle there
initialGrid[x, y] = true;
if (IsLoop(initialGrid, startPosition))
{
possibleLoops++;
}
// Restore obstacle state
initialGrid[x, y] = initialState;
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Amount of possible loop positions: [yellow]{possibleLoops}[/][/]");
}
return;
bool IsLoop(bool[,] obstaclesGrid, Point position)
{
HashSet<(Point position, Point direction)> visited = [];
var direction = DirectionUp;
visited.Add((position, direction));
// Move the guard till it loops or leaves the grid
while (true)
{
var destination = position + direction;
if (visited.Contains((destination, direction)))
{
return true;
}
if (destination.X is < 0 or >= GridSize || destination.Y is < 0 or >= GridSize)
{
return false;
}
// Check if it's possible to move or if there is an obstacle
if (obstaclesGrid[destination.X, destination.Y])
{
direction = NextDirection(direction);
continue;
}
position = destination;
visited.Add((position, direction));
}
}
}
private (bool[,] ObstaclesGrid, Point Start) ReadInputGrid()
{
var grid = new bool[GridSize, GridSize];
Point start = default;
var y = 0;
foreach (var line in Input.ReadAllLines())
{
var x = 0;
foreach (var symbol in line)
{
if (symbol == '^')
{
start = new Point(x, y);
grid[x, y] = false;
}
else
{
grid[x, y] = symbol switch
{
'#' => true,
_ => false
};
}
x++;
}
y++;
}
return (grid, start);
}
private static Point NextDirection(Point direction)
{
if (direction == DirectionUp)
{
return DirectionRight;
}
if (direction == DirectionRight)
{
return DirectionDown;
}
if (direction == DirectionDown)
{
return DirectionLeft;
}
if (direction == DirectionLeft)
{
return DirectionUp;
}
throw new ArgumentException("Invalid direction", nameof(direction));
}
private readonly record struct Point(int X, int Y) : IAdditionOperators<Point, Point, Point>
{
public static Point operator +(Point left, Point right)
{
return new Point(left.X + right.X, left.Y + right.Y);
}
}
}