[2k25] Add day 1
This commit is contained in:
194
Days/Day6.cs
194
Days/Day6.cs
@@ -1,194 +0,0 @@
|
||||
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.AsSpan().EnumerateLines())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user