Add day 14
This commit is contained in:
151
Days/Day14.cs
Normal file
151
Days/Day14.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using System.Collections.Frozen;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace AdventOfCode.Days;
|
||||
|
||||
public class Day14 : Day
|
||||
{
|
||||
public override int Number => 14;
|
||||
public override string Name => "Restroom Redoubt";
|
||||
|
||||
private const int Height = 103;
|
||||
private const int HeightCenter = Height / 2;
|
||||
|
||||
private const int Width = 101;
|
||||
private const int WidthCenter = Width / 2;
|
||||
|
||||
private const int Iterations = 100;
|
||||
|
||||
public override void RunPart1(bool display = true)
|
||||
{
|
||||
var robots = ParseRobots();
|
||||
|
||||
for (var i = 0; i < Iterations; i++)
|
||||
{
|
||||
foreach (var robot in robots)
|
||||
{
|
||||
robot.Position = new Point(
|
||||
Math.Abs((Width + robot.Position.X + robot.Velocity.X) % Width),
|
||||
Math.Abs((Height + robot.Position.Y + robot.Velocity.Y) % Height)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute safety factor
|
||||
var safetyFactor =
|
||||
robots.Count(r => r.Position is { X: < WidthCenter, Y: < HeightCenter }) *
|
||||
robots.Count(r => r.Position is { X: > WidthCenter, Y: < HeightCenter }) *
|
||||
robots.Count(r => r.Position is { X: < WidthCenter, Y: > HeightCenter }) *
|
||||
robots.Count(r => r.Position is { X: > WidthCenter, Y: > HeightCenter });
|
||||
|
||||
if (display)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[green]Safety factor: [yellow]{safetyFactor}[/][/]");
|
||||
}
|
||||
}
|
||||
|
||||
public override void RunPart2(bool display = true)
|
||||
{
|
||||
var robots = ParseRobots();
|
||||
|
||||
var canvas = new Canvas(Width, Height);
|
||||
|
||||
for (var i = 0; i < int.MaxValue; i++)
|
||||
{
|
||||
for (var x = 0; x < Width; x++)
|
||||
{
|
||||
for (var y = 0; y < Height; y++)
|
||||
{
|
||||
canvas.SetPixel(x, y, Color.Grey23);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var robot in robots)
|
||||
{
|
||||
robot.Position = new Point(
|
||||
Math.Abs((Width + robot.Position.X + robot.Velocity.X) % Width),
|
||||
Math.Abs((Height + robot.Position.Y + robot.Velocity.Y) % Height)
|
||||
);
|
||||
|
||||
canvas.SetPixel(robot.Position.X, robot.Position.Y, Color.Green1);
|
||||
}
|
||||
|
||||
// Display grid
|
||||
if ((i + 1 - 46) % 101 == 0)
|
||||
{
|
||||
AnsiConsole.Write(canvas);
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
AnsiConsole.Write($"Seconds elapsed: {i + 1}");
|
||||
|
||||
var key = Console.ReadKey(true).Key;
|
||||
|
||||
if (key is ConsoleKey.Enter)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine($"[green]Image at instant: [yellow]t={i + 1}s[/][/]");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
AnsiConsole.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Robot> ParseRobots()
|
||||
{
|
||||
var robots = new List<Robot>();
|
||||
|
||||
foreach (var line in Input.AsSpan().EnumerateLines())
|
||||
{
|
||||
var positionX = int.Parse(line[(line.IndexOf('=') + 1)..line.IndexOf(',')]);
|
||||
var positionY = int.Parse(line[(line.IndexOf(',') + 1)..line.IndexOf(' ')]);
|
||||
|
||||
var velocityX = int.Parse(line[(line.LastIndexOf('=') + 1)..line.LastIndexOf(',')]);
|
||||
var velocityY = int.Parse(line[(line.LastIndexOf(',') + 1)..]);
|
||||
|
||||
robots.Add(new Robot(new Point(positionX, positionY), new Point(velocityX, velocityY)));
|
||||
}
|
||||
|
||||
return robots;
|
||||
}
|
||||
|
||||
private class Robot(Point position, Point velocity)
|
||||
{
|
||||
public Point Position { get; set; } = position;
|
||||
public Point Velocity { get; } = velocity;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user