Refactor Day08 to improve readability and speed

This commit is contained in:
Sebastian Lindemeier 2025-12-08 09:13:17 +01:00
parent 04d9b2fd45
commit b60db3c78a
1 changed files with 49 additions and 77 deletions

View File

@ -23,30 +23,10 @@ public class Day08
public long SolvePart1(string pathToPuzzleInput, int amountToConnect) public long SolvePart1(string pathToPuzzleInput, int amountToConnect)
{ {
var points = ParsePuzzleInput(pathToPuzzleInput); var points = ParsePuzzleInput(pathToPuzzleInput);
Dictionary<Coordinate, HashSet<Coordinate>> connected = points.ToDictionary(p => p, p => new HashSet<Coordinate>());
var pointsWithClosest = points.Select(point =>
{
var closest = GetClosestPoint(point, points, connected);
return (point, closest: closest.point, closest.distance);
})
.OrderBy(x => x.distance)
.ToArray();
List<List<Coordinate>> circuits = []; var pointPairs = GetAllCombinationsSortedByDistance(points);
for (var i = 0; i < amountToConnect; i++)
{ var circuits = CombineCircuits(amountToConnect, points, pointPairs);
var next = pointsWithClosest[0];
_ = AddToCircuits(next.point, next.closest, circuits);
connected[next.point].Add(next.closest);
connected[next.closest].Add(next.point);
pointsWithClosest = points.Select(point =>
{
var closest = GetClosestPoint(point, points, connected);
return (point, closest: closest.point, closest.distance);
})
.OrderBy(x => x.distance)
.ToArray();
}
return circuits return circuits
.Select(circuit => circuit.Count) .Select(circuit => circuit.Count)
@ -58,54 +38,41 @@ public class Day08
public long SolvePart2(string pathToPuzzleInput) public long SolvePart2(string pathToPuzzleInput)
{ {
var points = ParsePuzzleInput(pathToPuzzleInput); var points = ParsePuzzleInput(pathToPuzzleInput);
Dictionary<Coordinate, HashSet<Coordinate>> connected = points.ToDictionary(p => p, p => new HashSet<Coordinate>());
var pointsWithClosest = points.Select(point =>
{
var closest = GetClosestPoint(point, points, connected);
return (point, closest: closest.point, closest.distance);
})
.OrderBy(x => x.distance)
.ToArray();
List<List<Coordinate>> circuits = points.Select(p => new List<Coordinate>() { p }).ToList(); var pointPairs = GetAllCombinationsSortedByDistance(points);
(Coordinate a, Coordinate b) lastConnected = ((0, 0, 0), (0, 0, 0));
while(circuits.Count > 1) var lastConnected = LastCombinedConnectAllCircuits(points, pointPairs);
{
var next = pointsWithClosest[0];
_ = AddToCircuits(next.point, next.closest, circuits);
connected[next.point].Add(next.closest);
connected[next.closest].Add(next.point);
lastConnected = (next.point, next.closest);
pointsWithClosest = points.Select(point =>
{
var closest = GetClosestPoint(point, points, connected);
return (point, closest: closest.point, closest.distance);
})
.OrderBy(x => x.distance)
.ToArray();
}
return lastConnected.a.x * lastConnected.b.x; return lastConnected.a.x * lastConnected.b.x;
} }
private (Coordinate point, double distance) GetClosestPoint(Coordinate a, Coordinate[] points, Dictionary<Coordinate, HashSet<Coordinate>> connections) private List<List<Coordinate>> CombineCircuits(int amountToConnect, Coordinate[] points,
(Coordinate pointA, Coordinate pointB)[] pointPairs)
{ {
var minDistance = double.MaxValue; var circuits = points.Select(p => new List<Coordinate>() { p }).ToList();
var minIndex = -1; for (var i = 0; i < amountToConnect; i++)
for (var i = 0; i < points.Length; i++)
{ {
if(a == points[i]) continue; var next = pointPairs[i];
if(connections[a].Contains(points[i])) continue; circuits = AddToCircuits(next.pointA, next.pointB, circuits);
var distance = GetDistance(a, points[i]);
if (minDistance > distance)
{
minIndex = i;
minDistance = GetDistance(a, points[i]);
}
} }
return (points[minIndex], minDistance); return circuits;
}
private (Coordinate a, Coordinate b) LastCombinedConnectAllCircuits(Coordinate[] points,
(Coordinate pointA, Coordinate pointB)[] pointPairs)
{
var circuits = points.Select(p => new List<Coordinate>() { p }).ToList();
(Coordinate a, Coordinate b) lastConnected = ((0, 0, 0), (0, 0, 0));
var i = 0;
while(circuits.Count > 1)
{
var next = pointPairs[i++];
circuits = AddToCircuits(next.pointA, next.pointB, circuits);
lastConnected = (next.pointA, next.pointB);
}
return lastConnected;
} }
private double GetDistance(Coordinate a, Coordinate b) private double GetDistance(Coordinate a, Coordinate b)
@ -113,19 +80,19 @@ public class Day08
return Math.Sqrt(Math.Pow(a.x - b.x, 2) + Math.Pow(a.y - b.y, 2) + Math.Pow(a.z - b.z, 2)); return Math.Sqrt(Math.Pow(a.x - b.x, 2) + Math.Pow(a.y - b.y, 2) + Math.Pow(a.z - b.z, 2));
} }
private int AddToCircuits(Coordinate a, Coordinate b, List<List<Coordinate>> circuits) private List<List<Coordinate>> AddToCircuits(Coordinate a, Coordinate b, List<List<Coordinate>> circuits)
{ {
var circuitToAddBTo = circuits.FirstOrDefault(circuit => circuit.Contains(a)); var circuitToAddBTo = circuits.FirstOrDefault(circuit => circuit.Contains(a));
var circuitToAddATo = circuits.FirstOrDefault(circuit => circuit.Contains(b)); var circuitToAddATo = circuits.FirstOrDefault(circuit => circuit.Contains(b));
if (circuitToAddATo == null && circuitToAddBTo == null) if (circuitToAddATo == null && circuitToAddBTo == null)
{ {
circuits.Add([a, b]); circuits.Add([a, b]);
return 2; return circuits;
} }
if (circuitToAddATo == circuitToAddBTo) if (circuitToAddATo == circuitToAddBTo)
{ {
return 0; return circuits;
} }
if (circuitToAddATo != null && circuitToAddBTo != null) if (circuitToAddATo != null && circuitToAddBTo != null)
@ -133,7 +100,7 @@ public class Day08
circuits.Remove(circuitToAddATo); circuits.Remove(circuitToAddATo);
circuits.Remove(circuitToAddBTo); circuits.Remove(circuitToAddBTo);
circuits.Add([..circuitToAddATo, ..circuitToAddBTo]); circuits.Add([..circuitToAddATo, ..circuitToAddBTo]);
return 0; return circuits;
} }
if (circuitToAddATo != null) if (circuitToAddATo != null)
@ -142,19 +109,24 @@ public class Day08
} }
else else
{ {
circuitToAddBTo.Add(b); circuitToAddBTo!.Add(b);
} }
return 1; return circuits;
} }
private IEnumerable<(Coordinate pointA, Coordinate pointB, double distance)> GetAllDistances(Coordinate[] coordinates) private (Coordinate pointA, Coordinate pointB)[] GetAllCombinationsSortedByDistance(Coordinate[] coordinates)
{ {
var combinations = coordinates var combinations = Combinations(coordinates)
.SelectMany((coord, ix) => .OrderBy(x => GetDistance(x.a, x.b))
coordinates.Skip(ix + 1).Select(coordB => (coord, coordB, distance: GetDistance(coord, coordB))))
.OrderBy(x => x.distance)
.ToArray(); .ToArray();
return combinations; return combinations;
} }
private IEnumerable<(TValue a, TValue b)> Combinations<TValue>(IEnumerable<TValue> values)
{
var enumerated = values.ToArray();
return enumerated
.SelectMany((valueA, ix) => enumerated.Skip(ix + 1).Select(valueB => (valueA, valueB)));
}
} }