From d0b612154ab9bb6a59eb01a0edc8aed80136b258 Mon Sep 17 00:00:00 2001 From: Sebastian Lindemeier Date: Fri, 12 Dec 2025 12:35:01 +0100 Subject: [PATCH] Extract `Combinations` method to `AdventOfCode.Extensions` and refactor usages to improve modularity and reduce duplication --- .../AdventOfCode.Extensions.csproj | 9 ++++ .../EnumerableExtensions.cs | 52 +++++++++++++++++++ AdventOfCode.sln | 6 +++ AoC_2025/AoC_2025.csproj | 1 + AoC_2025/Day08.cs | 15 ++---- AoC_2025/Day09.cs | 14 +---- AoC_2025/Day10.cs | 47 +---------------- 7 files changed, 75 insertions(+), 69 deletions(-) create mode 100644 AdventOfCode.Extensions/AdventOfCode.Extensions.csproj create mode 100644 AdventOfCode.Extensions/EnumerableExtensions.cs diff --git a/AdventOfCode.Extensions/AdventOfCode.Extensions.csproj b/AdventOfCode.Extensions/AdventOfCode.Extensions.csproj new file mode 100644 index 0000000..93bf97d --- /dev/null +++ b/AdventOfCode.Extensions/AdventOfCode.Extensions.csproj @@ -0,0 +1,9 @@ + + + + net9.0 + disable + enable + + + diff --git a/AdventOfCode.Extensions/EnumerableExtensions.cs b/AdventOfCode.Extensions/EnumerableExtensions.cs new file mode 100644 index 0000000..a0d05f0 --- /dev/null +++ b/AdventOfCode.Extensions/EnumerableExtensions.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace AdventOfCode.Extensions; + +public static class EnumerableExtensions +{ + public static IEnumerable Combinations(this IEnumerable values, int count) + { + var pool = values.ToArray(); + var poolLength = pool.Length; + if (count > poolLength) + yield break; + var indices = Range(0, count).ToArray(); + yield return GetCombination(indices, pool); + while (true) + { + var validIndex = false; + var currentIndex = 0; + foreach (var i in Range(0, count).Reverse()) + { + currentIndex = i; + if (indices[i] != i + poolLength - count) + { + validIndex = true; + break; + } + } + if(!validIndex) + yield break; + + indices[currentIndex] += 1; + foreach (var j in Range(currentIndex + 1, count)) + { + Index ix = j - 1; + indices[j] = indices[ix] + 1; + } + + yield return GetCombination(indices, pool); + } + + static TValue[] GetCombination(int[] innerIndices, TValue[] innerPool) => + innerIndices.Select(i => innerPool[i]).ToArray(); + + static IEnumerable Range(int start, int end) + { + for (var i = start; i < end; i++) + yield return i; + } + } +} \ No newline at end of file diff --git a/AdventOfCode.sln b/AdventOfCode.sln index 1750e5c..9926868 100644 --- a/AdventOfCode.sln +++ b/AdventOfCode.sln @@ -10,6 +10,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AoC_2025.Runner", "AoC_2025 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvenOfCode.Contracts", "AdvenOfCode.Contracts\AdvenOfCode.Contracts.csproj", "{0249A329-D5C1-4699-88BE-A668B362432E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdventOfCode.Extensions", "AdventOfCode.Extensions\AdventOfCode.Extensions.csproj", "{1466A0F6-7C88-47FF-B8F8-FF30368E26DC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -32,6 +34,10 @@ Global {0249A329-D5C1-4699-88BE-A668B362432E}.Debug|Any CPU.Build.0 = Debug|Any CPU {0249A329-D5C1-4699-88BE-A668B362432E}.Release|Any CPU.ActiveCfg = Release|Any CPU {0249A329-D5C1-4699-88BE-A668B362432E}.Release|Any CPU.Build.0 = Release|Any CPU + {1466A0F6-7C88-47FF-B8F8-FF30368E26DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1466A0F6-7C88-47FF-B8F8-FF30368E26DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1466A0F6-7C88-47FF-B8F8-FF30368E26DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1466A0F6-7C88-47FF-B8F8-FF30368E26DC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {4F395AE3-DABB-4546-A4D0-5A62425FE168} = {05EBAA1C-B33B-4AFE-8635-A58D7CA509A7} diff --git a/AoC_2025/AoC_2025.csproj b/AoC_2025/AoC_2025.csproj index 678a88a..badaa42 100644 --- a/AoC_2025/AoC_2025.csproj +++ b/AoC_2025/AoC_2025.csproj @@ -8,6 +8,7 @@ + diff --git a/AoC_2025/Day08.cs b/AoC_2025/Day08.cs index 5f1bcef..7f9e54e 100644 --- a/AoC_2025/Day08.cs +++ b/AoC_2025/Day08.cs @@ -4,6 +4,7 @@ using System.Data.Common; using System.IO; using System.Linq; using AdvenOfCode.Contracts; +using AdventOfCode.Extensions; using Coordinate = (long x, long y, long z); namespace AoC_2025; @@ -92,21 +93,11 @@ public class Day08 : IPuzzleSolver private IEnumerable<(Coordinate boxA, Coordinate boxB)> GetAllCombinationsSortedByDistance(IEnumerable jBoxes) { - var combinations = Combinations(jBoxes) + var combinations = jBoxes.Combinations(2) + .Select(x => (a: x[0], b: x[1])) .OrderBy(x => GetDistance(x.a, x.b)); return combinations; } - - private IEnumerable<(TValue a, TValue b)> Combinations(IEnumerable values) - { - var enumeratedValues = values.Index().ToArray(); - var pairs = - from a in enumeratedValues - from b in enumeratedValues - where a.Index < b.Index - select (a.Item, b.Item); - return pairs; - } private long MultiplyLargestCircuitLength(List> circuits, int amountMultiply) { diff --git a/AoC_2025/Day09.cs b/AoC_2025/Day09.cs index 4c44c60..4a3e28a 100644 --- a/AoC_2025/Day09.cs +++ b/AoC_2025/Day09.cs @@ -4,6 +4,7 @@ using System.Data.Common; using System.IO; using System.Linq; using AdvenOfCode.Contracts; +using AdventOfCode.Extensions; using Coordinate = (long x, long y); using CoordinatePair = (long minX, long minY, long maxX, long maxY); @@ -54,7 +55,7 @@ public class Day09 : IPuzzleSolver private IEnumerable GetAllPossibleRectanglesAsPairs(Coordinate[] redTiles) { - return Combinations(redTiles).Select(x => AsPair(x.a, x.b)); + return redTiles.Combinations(2).Select(x => AsPair(x[0], x[1])); } private CoordinatePair[] GetBordersAsPairs(Coordinate[] redTiles) @@ -84,17 +85,6 @@ public class Day09 : IPuzzleSolver return (Math.Abs(tileA.x - tileB.x) + 1) * (Math.Abs(tileA.y - tileB.y) + 1); } - private IEnumerable<(TValue a, TValue b)> Combinations(IEnumerable values) - { - var enumeratedValues = values.Index().ToArray(); - var pairs = - from a in enumeratedValues - from b in enumeratedValues - where a.Index < b.Index - select (a.Item, b.Item); - return pairs; - } - private IEnumerable<(Coordinate a, Coordinate b)> GetBorders(Coordinate[] tiles) { return tiles.Zip([..tiles[1..], tiles[0]], (a, b) => (a, b)); diff --git a/AoC_2025/Day10.cs b/AoC_2025/Day10.cs index db2714b..9ab5f82 100644 --- a/AoC_2025/Day10.cs +++ b/AoC_2025/Day10.cs @@ -6,6 +6,7 @@ using System.Data.Common; using System.IO; using System.Linq; using AdvenOfCode.Contracts; +using AdventOfCode.Extensions; using Microsoft.Z3; namespace AoC_2025; @@ -214,7 +215,7 @@ public class Day10 : IPuzzleSolver yield return ([..Enumerable.Repeat(0, patternLength)], 0); for (var i = 1; i <= buttons.Length; i++) { - foreach (var buttonPattern in Combinations(buttons, i)) + foreach (var buttonPattern in buttons.Combinations(i)) { var joltageLevels = GetJoltageLevelsForButtonPattern(patternLength, buttonPattern); yield return (joltageLevels, buttonPattern.Length); @@ -271,50 +272,6 @@ public class Day10 : IPuzzleSolver var answer = answerExpression is IntNum number ? number.Int64 : 0; return answer; } - - private IEnumerable Combinations(IEnumerable values, int count) - { - var pool = values.ToArray(); - var poolLength = pool.Length; - if (count > poolLength) - yield break; - var indices = Range(0, count).ToArray(); - yield return GetCombination(indices, pool); - while (true) - { - var validIndex = false; - var currentIndex = 0; - foreach (var i in Range(0, count).Reverse()) - { - currentIndex = i; - if (indices[i] != i + poolLength - count) - { - validIndex = true; - break; - } - } - if(!validIndex) - yield break; - - indices[currentIndex] += 1; - foreach (var j in Range(currentIndex + 1, count)) - { - Index ix = j - 1; - indices[j] = indices[ix] + 1; - } - - yield return GetCombination(indices, pool); - } - - static TValue[] GetCombination(int[] innerIndices, TValue[] innerPool) => - innerIndices.Select(i => innerPool[i]).ToArray(); - - static IEnumerable Range(int start, int end) - { - for (var i = start; i < end; i++) - yield return i; - } - } } public class IntArrayEqualityComparer : IEqualityComparer