AdventOfCode/AoC_2025/Day08.cs

132 lines
4.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
using AdvenOfCode.Contracts;
using Coordinate = (int x, int y, int z);
namespace AoC_2025;
public class Day08
{
private Coordinate[] ParsePuzzleInput(string path)
{
var puzzleInput = File.ReadAllLines(path)
.Where(line => !string.IsNullOrWhiteSpace(line))
.Select(line => line.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(str => int.Parse(str)).ToArray())
.Select(numbers => (numbers[0], numbers[1], numbers[2]))
.ToArray();
return puzzleInput;
}
public long SolvePart1(string pathToPuzzleInput, int amountToConnect)
{
var points = ParsePuzzleInput(pathToPuzzleInput);
var pointPairs = GetAllCombinationsSortedByDistance(points);
var circuits = CombineCircuits(amountToConnect, points, pointPairs);
return circuits
.Select(circuit => circuit.Count)
.OrderDescending()
.Take(3)
.Aggregate((acc, next) => acc * next);
}
public long SolvePart2(string pathToPuzzleInput)
{
var points = ParsePuzzleInput(pathToPuzzleInput);
var pointPairs = GetAllCombinationsSortedByDistance(points);
var lastConnected = LastCombinedConnectAllCircuits(points, pointPairs);
return lastConnected.a.x * lastConnected.b.x;
}
private List<List<Coordinate>> CombineCircuits(int amountToConnect, Coordinate[] points,
(Coordinate pointA, Coordinate pointB)[] pointPairs)
{
var circuits = points.Select(p => new List<Coordinate>() { p }).ToList();
for (var i = 0; i < amountToConnect; i++)
{
var nextToConnect = pointPairs[i];
circuits = AddToCircuits(nextToConnect.pointA, nextToConnect.pointB, circuits);
}
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();
var lastConnected = pointPairs.First();
var i = 0;
while(circuits.Count > 1)
{
var nextToConnect = pointPairs[i++];
circuits = AddToCircuits(nextToConnect.pointA, nextToConnect.pointB, circuits);
lastConnected = nextToConnect;
}
return lastConnected;
}
private double GetDistance(Coordinate a, Coordinate b)
{
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 List<List<Coordinate>> AddToCircuits(Coordinate a, Coordinate b, List<List<Coordinate>> circuits)
{
var circuitToAddBTo = circuits.FirstOrDefault(circuit => circuit.Contains(a));
var circuitToAddATo = circuits.FirstOrDefault(circuit => circuit.Contains(b));
if (circuitToAddATo == null && circuitToAddBTo == null)
{
circuits.Add([a, b]);
return circuits;
}
if (circuitToAddATo == circuitToAddBTo)
{
return circuits;
}
if (circuitToAddATo != null && circuitToAddBTo != null)
{
circuits.Remove(circuitToAddATo);
circuits.Remove(circuitToAddBTo);
circuits.Add([..circuitToAddATo, ..circuitToAddBTo]);
return circuits;
}
if (circuitToAddATo != null)
{
circuitToAddATo.Add(a);
}
else
{
circuitToAddBTo!.Add(b);
}
return circuits;
}
private (Coordinate pointA, Coordinate pointB)[] GetAllCombinationsSortedByDistance(Coordinate[] coordinates)
{
var combinations = Combinations(coordinates)
.OrderBy(x => GetDistance(x.a, x.b))
.ToArray();
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)));
}
}