diff --git a/Solutions/2024/Day08.cs b/Solutions/2024/Day08.cs index 74b3394..87192e9 100644 --- a/Solutions/2024/Day08.cs +++ b/Solutions/2024/Day08.cs @@ -18,12 +18,13 @@ public static void LoadMap(string[] input, Action? visualise = n .ForEachCell() .Where(c => char.IsAsciiLetterOrDigit(c)) .ToLookup(a => a.Value, a => a.Index); + _map.VisualiseMap([], "Initial", visualise); } public static int Part1(string[] _, Action? visualise = null) { - List antinodes = _antennae.GetAntinodes(Antinodes); + List antinodes = _antennae.GetAntinodes(a => a.Antinodes(_map, start: 1)); _map.VisualiseMap(antinodes, "Final", visualise); return antinodes.Count; @@ -31,7 +32,7 @@ public static int Part1(string[] _, Action? visualise = null) public static int Part2(string[] _, Action? visualise = null) { - List antinodes = _antennae.GetAntinodes(a => a.ResidentHarmonicAntinodes(_map)); + List antinodes = _antennae.GetAntinodes(a => a.Antinodes(_map, start: 0)); _map.VisualiseMap(antinodes, "Final", visualise); return antinodes.Count; @@ -39,57 +40,63 @@ public static int Part2(string[] _, Action? visualise = null) private static List GetAntinodes(this ILookup antennae, Func, IEnumerable> antinodesFunc) { - return [..antennae + return [.. + antennae .Select(a => antennae[a.Key]) .Select(antinodesFunc) .SelectMany(antinodes => antinodes) .Distinct() - .Where(antinode => _map.IsInBounds(antinode))]; - } - - private static IEnumerable Antinodes(this IEnumerable locations) - { - foreach (IEnumerable item in locations.Combinations(2)) { - Point a1 = item.First(); - Point a2 = item.Last(); - yield return a1 - a2 + a1; - yield return a2 - a1 + a2; - } + ]; } - private static IEnumerable ResidentHarmonicAntinodes(this IEnumerable locations, char[,] map) + private static IEnumerable Antinodes(this IEnumerable locations, char[,] map, int start) { - foreach (IEnumerable item in locations.Combinations(2)) { - Point a1 = item.First(); - Point a2 = item.Last(); - int i = 0; - while (map.IsInBounds(((a1 - a2) * i) + a1)) { - yield return ((a1 - a2) * i) + a1; - i++; - } - - i = 0; - while (map.IsInBounds(((a2 - a1) * i) + a2)) { - yield return ((a2 - a1) * i) + a2; - i++; + foreach (IEnumerable pair in locations.Combinations(2)) { + Point antenna1 = pair.First(); + Point antenna2 = pair.Last(); + + for (int n = start; ; n++) { + bool allOutOfBounds = true; + + Point[] antinodes = [AntinodeN(antenna1, antenna2, n), AntinodeN(antenna2, antenna1, n)]; + foreach (Point antinode in antinodes) { + if (map.IsInBounds(antinode)) { + yield return antinode; + allOutOfBounds = false; + } + } + + if (allOutOfBounds || start == 1) { + break; + } } } } + private static Point AntinodeN(Point ant1, Point ant2, int n = 1) => ((ant1 - ant2) * n) + ant1; + + // Not needed for AoC input + //private static Point AntinodeGcdN(Point ant1, Point ant2, int n = 1) + //{ + // Point gcd = new( + // 0.GreatestCommonDivisor(ant1.X - ant2.X), + // 0.GreatestCommonDivisor(ant1.Y - ant2.Y)); + // return (gcd * n) + ant1; + //} public static void VisualiseMap(this char[, ] map, IEnumerable antinodes, string title, Action? visualise) { - char[,] copy = (char[,])map.Clone(); + const char ANTINODE = '#'; + + char[,] vMap = (char[,])map.Clone(); foreach (Point antinode in antinodes) { - copy[antinode.X, antinode.Y] = ANTINODE; + vMap[antinode.X, antinode.Y] = ANTINODE; } if (visualise is not null) { - string[] output = ["", title, .. copy.PrintAsStringArray(0)]; + string[] output = ["", title, .. vMap.AsStrings()]; _ = Task.Run(() => visualise?.Invoke(output, false)); } } - - private const char ANTINODE = '#'; }