[2k25] Add day 8
This commit is contained in:
@@ -18,4 +18,8 @@
|
||||
<EmbeddedResource Include="Inputs\*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Inputs\Day8.txt" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
221
Days/Day8.cs
Normal file
221
Days/Day8.cs
Normal file
@@ -0,0 +1,221 @@
|
||||
using System.Buffers;
|
||||
using System.Numerics;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace AdventOfCode.Days;
|
||||
|
||||
public class Day8 : Day
|
||||
{
|
||||
public override int Number => 8;
|
||||
public override string Name => "Playground";
|
||||
|
||||
public override void RunPart1(bool display = true)
|
||||
{
|
||||
var boxPositions = ParseBoxPositions(Input);
|
||||
var boxPairDistances = FetchOrderedDistances(boxPositions);
|
||||
|
||||
var circuits = new List<HashSet<Box>>();
|
||||
|
||||
var connectionsCount = 0;
|
||||
|
||||
while (connectionsCount < 1000)
|
||||
{
|
||||
// Fetch next minimal distance pair. This is always the last pair in our ordered list
|
||||
var (pairLeftBox, pairRightBox, _) = boxPairDistances[^1];
|
||||
boxPairDistances.RemoveAt(boxPairDistances.Count - 1);
|
||||
|
||||
// Create a connection if those two boxes are not already connected
|
||||
if (!ConnectionExists(circuits, pairLeftBox, pairRightBox))
|
||||
{
|
||||
// Connect the boxes, eventually merging circuits
|
||||
ConnectBoxes(circuits, pairLeftBox, pairRightBox);
|
||||
}
|
||||
|
||||
connectionsCount++;
|
||||
}
|
||||
|
||||
var result = circuits
|
||||
.OrderByDescending(circuit => circuit.Count)
|
||||
.Take(3)
|
||||
.Aggregate(1, (product, circuit) => product * circuit.Count);
|
||||
|
||||
if (display)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[green]Result is: [yellow]{result}[/][/]");
|
||||
}
|
||||
}
|
||||
|
||||
public override void RunPart2(bool display = true)
|
||||
{
|
||||
var boxPositions = ParseBoxPositions(Input);
|
||||
var boxPairDistances = FetchOrderedDistances(boxPositions);
|
||||
|
||||
var circuits = new List<HashSet<Box>>();
|
||||
|
||||
long result;
|
||||
while (true)
|
||||
{
|
||||
// Fetch next minimal distance pair. This is always the last pair in our ordered list
|
||||
var (pairLeftBox, pairRightBox, _) = boxPairDistances[^1];
|
||||
boxPairDistances.RemoveAt(boxPairDistances.Count - 1);
|
||||
|
||||
// Create a connection if those two boxes are not already connected
|
||||
if (!ConnectionExists(circuits, pairLeftBox, pairRightBox))
|
||||
{
|
||||
// Connect the boxes, eventually merging circuits
|
||||
ConnectBoxes(circuits, pairLeftBox, pairRightBox);
|
||||
}
|
||||
|
||||
// Check if there is a circuit with all boxes connected
|
||||
if (circuits[0].Count >= 1000)
|
||||
{
|
||||
result = pairLeftBox.X * pairRightBox.X;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (display)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[green]Result is: [yellow]{result}[/][/]");
|
||||
}
|
||||
}
|
||||
|
||||
private static double BoxDistance(Box left, Box right)
|
||||
{
|
||||
return Math.Sqrt(
|
||||
(right.X - left.X) * (right.X - left.X) +
|
||||
(right.Y - left.Y) * (right.Y - left.Y) +
|
||||
(right.Z - left.Z) * (right.Z - left.Z)
|
||||
);
|
||||
}
|
||||
|
||||
static bool ConnectionExists(List<HashSet<Box>> circuits, Box left, Box right)
|
||||
{
|
||||
foreach (var circuit in circuits)
|
||||
{
|
||||
if (circuit.Contains(left) && circuit.Contains(right))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ConnectBoxes(List<HashSet<Box>> circuits, Box pairLeftBox, Box pairRightBox)
|
||||
{
|
||||
// Try to find circuit containing each box
|
||||
HashSet<Box>? leftCircuit = null;
|
||||
HashSet<Box>? rightCircuit = null;
|
||||
|
||||
foreach (var circuit in circuits)
|
||||
{
|
||||
if (circuit.Contains(pairLeftBox))
|
||||
{
|
||||
leftCircuit = circuit;
|
||||
}
|
||||
|
||||
if (circuit.Contains(pairRightBox))
|
||||
{
|
||||
rightCircuit = circuit;
|
||||
}
|
||||
}
|
||||
|
||||
// None is in a circuit, create a new one
|
||||
if (leftCircuit is null && rightCircuit is null)
|
||||
{
|
||||
var circuit = new HashSet<Box>
|
||||
{
|
||||
pairLeftBox,
|
||||
pairRightBox
|
||||
};
|
||||
|
||||
circuits.Add(circuit);
|
||||
}
|
||||
// One of the two is null
|
||||
else if (leftCircuit is not null && rightCircuit is null)
|
||||
{
|
||||
leftCircuit.Add(pairRightBox);
|
||||
}
|
||||
else if (leftCircuit is null && rightCircuit is not null)
|
||||
{
|
||||
rightCircuit.Add(pairLeftBox);
|
||||
}
|
||||
// Both are already in a circuit, merge them
|
||||
else
|
||||
{
|
||||
foreach (var box in rightCircuit!)
|
||||
{
|
||||
leftCircuit!.Add(box);
|
||||
}
|
||||
|
||||
circuits.Remove(rightCircuit);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Box> ParseBoxPositions(string input)
|
||||
{
|
||||
var positions = new List<Box>();
|
||||
|
||||
foreach (var line in input.EnumerateLines())
|
||||
{
|
||||
var split = line.Split(',');
|
||||
|
||||
split.MoveNext();
|
||||
var x = long.Parse(line[split.Current]);
|
||||
|
||||
split.MoveNext();
|
||||
var y = long.Parse(line[split.Current]);
|
||||
|
||||
split.MoveNext();
|
||||
var z = long.Parse(line[split.Current]);
|
||||
|
||||
positions.Add(new Box(x, y, z));
|
||||
}
|
||||
|
||||
return positions;
|
||||
}
|
||||
|
||||
private static List<BoxPairDistance> FetchOrderedDistances(List<Box> boxes)
|
||||
{
|
||||
var boxPairDistances = new List<BoxPairDistance>();
|
||||
|
||||
for (var i = 0; i < boxes.Count - 1; i++)
|
||||
{
|
||||
for (var j = i + 1; j < boxes.Count; j++)
|
||||
{
|
||||
var leftBox = boxes[i];
|
||||
var rightBox = boxes[j];
|
||||
|
||||
var distance = BoxDistance(leftBox, rightBox);
|
||||
|
||||
boxPairDistances.Add(new BoxPairDistance(leftBox, rightBox, distance));
|
||||
}
|
||||
}
|
||||
|
||||
// Sort in reverse order
|
||||
boxPairDistances.Sort((left, right) => right.CompareTo(left));
|
||||
|
||||
return boxPairDistances;
|
||||
}
|
||||
|
||||
private record Box(long X, long Y, long Z);
|
||||
|
||||
private record BoxPairDistance(Box Left, Box Right, double Distance) : IComparable<BoxPairDistance>
|
||||
{
|
||||
public int CompareTo(BoxPairDistance? other)
|
||||
{
|
||||
if (ReferenceEquals(this, other))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (other is null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return Distance.CompareTo(other.Distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
1000
Inputs/Day8.txt
Normal file
1000
Inputs/Day8.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user