Add day 8
This commit is contained in:
169
Days/Day8.cs
Normal file
169
Days/Day8.cs
Normal file
@@ -0,0 +1,169 @@
|
||||
using System.Collections.Frozen;
|
||||
using System.Numerics;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace AdventOfCode.Days;
|
||||
|
||||
public class Day8 : Day
|
||||
{
|
||||
public override int Number => 8;
|
||||
public override string Name => "Resonant Collinearity";
|
||||
|
||||
private const int GridSize = 50;
|
||||
|
||||
public override void RunPart1(bool display = true)
|
||||
{
|
||||
HashSet<Point> antinodePositions = [];
|
||||
|
||||
var frequencyAntennas = ParseAntennas();
|
||||
|
||||
// Find antinodes for each frequency
|
||||
foreach (var (_, antennas) in frequencyAntennas)
|
||||
{
|
||||
// Take antennas by pair to find antinodes
|
||||
foreach (var firstAntenna in antennas)
|
||||
{
|
||||
foreach (var secondAntenna in antennas.Where(a => a != firstAntenna))
|
||||
{
|
||||
var firstAntinode = firstAntenna + (firstAntenna - secondAntenna);
|
||||
var secondAntinode = secondAntenna + (secondAntenna - firstAntenna);
|
||||
|
||||
if (firstAntinode is { X: >= 0 and < GridSize, Y: >= 0 and < GridSize })
|
||||
{
|
||||
antinodePositions.Add(firstAntinode);
|
||||
}
|
||||
|
||||
if (secondAntinode is { X: >= 0 and < GridSize, Y: >= 0 and < GridSize })
|
||||
{
|
||||
antinodePositions.Add(secondAntinode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (display)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[green]Unique antinode positions count: [yellow]{antinodePositions.Count}[/][/]");
|
||||
}
|
||||
}
|
||||
|
||||
public override void RunPart2(bool display = true)
|
||||
{
|
||||
HashSet<Point> antinodePositions = [];
|
||||
|
||||
var frequencyAntennas = ParseAntennas();
|
||||
|
||||
// Find antinodes for each frequency
|
||||
foreach (var (_, antennas) in frequencyAntennas)
|
||||
{
|
||||
// Take antennas by pair to find antinodes
|
||||
foreach (var firstAntenna in antennas)
|
||||
{
|
||||
foreach (var secondAntenna in antennas.Where(a => a != firstAntenna))
|
||||
{
|
||||
// Always add antinodes on antennas if a pair is formed
|
||||
antinodePositions.Add(firstAntenna);
|
||||
antinodePositions.Add(secondAntenna);
|
||||
|
||||
// Compute potential antinode positions
|
||||
var firstAntinodeOffset = firstAntenna - secondAntenna;
|
||||
var secondAntinodeOffset = secondAntenna - firstAntenna;
|
||||
|
||||
for (var i = 1; ; i++)
|
||||
{
|
||||
var firstAntinode = firstAntenna + (i * firstAntinodeOffset);
|
||||
|
||||
if (firstAntinode is { X: >= 0 and < GridSize, Y: >= 0 and < GridSize })
|
||||
{
|
||||
antinodePositions.Add(firstAntinode);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 1; ; i++)
|
||||
{
|
||||
var secondAntinode = secondAntenna + (i * secondAntinodeOffset);
|
||||
|
||||
if (secondAntinode is { X: >= 0 and < GridSize, Y: >= 0 and < GridSize })
|
||||
{
|
||||
antinodePositions.Add(secondAntinode);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (display)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[green]Unique antinode positions count: [yellow]{antinodePositions.Count}[/][/]");
|
||||
}
|
||||
}
|
||||
|
||||
private FrozenDictionary<char, List<Point>> ParseAntennas()
|
||||
{
|
||||
var antennas = new Dictionary<char, List<Point>>();
|
||||
|
||||
var y = 0;
|
||||
foreach (var line in Input.AsSpan().EnumerateLines())
|
||||
{
|
||||
var x = 0;
|
||||
|
||||
foreach (var frequency in line)
|
||||
{
|
||||
if (frequency is '.')
|
||||
{
|
||||
x++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!antennas.TryGetValue(frequency, out var list))
|
||||
{
|
||||
list = [];
|
||||
antennas[frequency] = list;
|
||||
}
|
||||
|
||||
list.Add(new Point(x, y));
|
||||
|
||||
x++;
|
||||
}
|
||||
|
||||
y++;
|
||||
}
|
||||
|
||||
return antennas.ToFrozenDictionary();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user