Add day 18

This commit is contained in:
2025-01-24 10:19:12 +01:00
parent 380eeda47b
commit ed8f30c972
2 changed files with 3654 additions and 0 deletions

204
Days/Day18.cs Normal file
View File

@@ -0,0 +1,204 @@
using System.Numerics;
using System.Runtime.Intrinsics.X86;
using Spectre.Console;
namespace AdventOfCode.Days;
public class Day18 : Day
{
public override int Number => 18;
public override string Name => "RAM Run";
private const int Size = 71;
private const char Corrupted = '#';
private const char Empty = ' ';
public override void RunPart1(bool display = true)
{
var grid = ParseGrid(1024);
var visited = new Dictionary<Point, int>();
var toVisit = new Queue<(Point Position, int Score)>();
var end = new Point(Size - 1, Size - 1);
var minimumScore = int.MaxValue;
toVisit.Enqueue((new Point(0, 0), 0));
while (toVisit.Count > 0)
{
var (position, score) = toVisit.Dequeue();
// Cannot go out of bounds
if (position is { X: < 0 or >= Size } or { Y: < 0 or >= Size })
{
continue;
}
// Cannot go onto a corrupted space
if (grid[position.X, position.Y] is Corrupted)
{
continue;
}
if (visited.TryGetValue(position, out var savedScore) && savedScore <= score)
{
continue;
}
visited[position] = score;
// End
if (position == end)
{
if (score < minimumScore)
{
minimumScore = score;
}
continue;
}
toVisit.Enqueue((position + (1, 0), score + 1));
toVisit.Enqueue((position + (-1, 0), score + 1));
toVisit.Enqueue((position + (0, 1), score + 1));
toVisit.Enqueue((position + (0, -1), score + 1));
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Minimum number of steps to reach the exit: [yellow]{minimumScore}[/][/]");
}
}
public override void RunPart2(bool display = true)
{
(int X, int Y)[] bytesToFall = Input.ReadAllLines()
.Select(line => line.Split(','))
.Select(split => (int.Parse(split[0]), int.Parse(split[1])))
.ToArray();
var nextByteIndex = 1024;
var grid = ParseGrid(1024);
while (true)
{
var nextByte = bytesToFall[nextByteIndex];
grid[nextByte.X, nextByte.Y] = Corrupted;
if (!IsGridCompletable())
{
break;
}
nextByteIndex++;
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Grid will be blocked at byte n°{nextByteIndex} at position: [yellow]{bytesToFall[nextByteIndex]}[/][/]");
}
return;
bool IsGridCompletable()
{
var visited = new HashSet<Point>();
var toVisit = new Queue<Point>();
var end = new Point(Size - 1, Size - 1);
toVisit.Enqueue(new Point(0, 0));
while (toVisit.Count > 0)
{
var position = toVisit.Dequeue();
// Cannot go out of bounds
if (position is { X: < 0 or >= Size } or { Y: < 0 or >= Size })
{
continue;
}
// Cannot go onto a corrupted space
if (grid[position.X, position.Y] is Corrupted)
{
continue;
}
if (!visited.Add(position))
{
continue;
}
// End
if (position == end)
{
return true;
}
toVisit.Enqueue(position + (1, 0));
toVisit.Enqueue(position + (-1, 0));
toVisit.Enqueue(position + (0, 1));
toVisit.Enqueue(position + (0, -1));
}
return false;
}
}
private char[,] ParseGrid(int limit)
{
var grid = new char[Size, Size];
var counter = 0;
foreach (var line in Input.AsSpan().EnumerateLines())
{
if (counter >= limit)
{
break;
}
var x = int.Parse(line[..line.IndexOf(',')]);
var y = int.Parse(line[(line.IndexOf(',') + 1)..]);
grid[x, y] = Corrupted;
counter++;
}
return grid;
}
private readonly record struct Point(int X, int Y)
: IAdditionOperators<Point, Point, Point>,
ISubtractionOperators<Point, Point, Point>,
IMultiplyOperators<Point, int, Point>
{
public static Point operator +(Point left, Point right)
{
return new Point(left.X + right.X, left.Y + right.Y);
}
public static Point operator -(Point left, Point right)
{
return new Point(left.X - right.X, left.Y - right.Y);
}
public static Point operator *(Point left, int right)
{
return new Point(left.X * right, left.Y * right);
}
public static Point operator *(int left, Point right)
{
return new Point(right.X * left, right.Y * left);
}
public static implicit operator Point((int X, int Y) point)
=> new(point.X, point.Y);
}
}

3450
Inputs/Day18.txt Normal file

File diff suppressed because it is too large Load Diff