Compare commits

..
10 Commits
Author SHA1 Message Date
Buddhism8003 5e3bb81140 Added a sliding window extension for IEnumerable 2026-01-30 21:55:40 +01:00
Sebastian Lindemeier 554ab0557e Add Manhattan distance methods and CoordinateNd class for n-dimensionality support 2025-12-16 08:55:13 +01:00
Sebastian Lindemeier d878ab186e Refactor Permutations in EnumerableExtensions by extracting RotateIndices method to simplify and reuse index rotation logic 2025-12-16 08:00:03 +01:00
Sebastian Lindemeier 9d4051ece1 Refactor Permutations in EnumerableExtensions, add PermutationsWithRepeats method, and update tests for improved validation and clarity 2025-12-16 07:56:20 +01:00
Sebastian Lindemeier 0665713725 Add CombinationsWithRepeats method to EnumerableExtensions with corresponding tests 2025-12-15 13:45:21 +01:00
Sebastian Lindemeier 149977d02f Refactor Permutations method in EnumerableExtensions to remove unnecessary logic and add validation for output count in tests 2025-12-15 11:54:40 +01:00
Sebastian Lindemeier acef1dd7d2 Add Permutations method to EnumerableExtensions with corresponding tests 2025-12-15 11:05:51 +01:00
Sebastian Lindemeier 56521d39d7 Refactor EnumerableExtensions to simplify combination generation by removing Range method and streamlining index logic 2025-12-15 10:44:38 +01:00
Sebastian Lindemeier ee061757a8 Refactor Day10 to simplify lamp parsing by removing redundant .Index() call and unnecessary LINQ chain 2025-12-15 10:28:06 +01:00
Sebastian Lindemeier 0359bacf47 Add subtraction and scalar multiplication operators to Coordinate and Coordinate3d 2025-12-15 10:21:43 +01:00
4 changed files with 307 additions and 32 deletions
@@ -4,13 +4,13 @@ namespace AdventOfCode.Extensions.Tests;
public class EnumerableExtensionsTest public class EnumerableExtensionsTest
{ {
[Fact] [Fact]
public void Combinations_12_2_equals_12_21() public void Combinations_12_2_equals_12()
{ {
int[] data = [1, 2]; int[] data = [1, 2];
var actual = data.Combinations(2).ToArray(); var actual = data.Combinations(2).ToArray();
Assert.Contains([1, 2], actual); Assert.Equal([[1, 2]], actual);
} }
[Fact] [Fact]
@@ -20,9 +20,7 @@ public class EnumerableExtensionsTest
var actual = data.Combinations(2).ToArray(); var actual = data.Combinations(2).ToArray();
Assert.Contains([1, 2], actual); Assert.Equal([[1, 2], [1, 3], [2, 3]], actual);
Assert.Contains([1, 3], actual);
Assert.Contains([2, 3], actual);
} }
[Fact] [Fact]
@@ -31,7 +29,117 @@ public class EnumerableExtensionsTest
int[] data = [1, 2, 3]; int[] data = [1, 2, 3];
var actual = data.Combinations(3).ToArray(); var actual = data.Combinations(3).ToArray();
Assert.Equal([[1, 2, 3]], actual);
}
[Fact]
public void Combinations_repeated_12_2_equals_11_12_22()
{
int[] data = [1, 2];
Assert.Contains([1, 2, 3], actual); var actual = data.CombinationsWithRepeats(2).ToArray();
Assert.Equal([[1, 1], [1, 2], [2, 2]], actual);
}
[Fact]
public void Combinations_repeated_123_2_equals_11_12_13_22_23_33()
{
int[] data = [1, 2, 3];
var actual = data.CombinationsWithRepeats(2).ToArray();
Assert.Equal([[1, 1], [1, 2], [1, 3], [2, 2], [2, 3], [3, 3]], actual);
}
[Fact]
public void Combinations_repeated_123_3_equals_many()
{
int[] data = [1, 2, 3];
var actual = data.CombinationsWithRepeats(3).ToArray();
Assert.Equal([[1, 1, 1], [1, 1, 2], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 3, 3], [2, 2, 2], [2, 2, 3], [2, 3, 3], [3, 3, 3]], actual);
}
[Fact]
public void Permutations_repeated_12_2_equals_11_12_21_22()
{
int[] data = [1, 2];
var actual = data.PermutationsWithRepeats(2).ToArray();
Assert.Equal([[1, 1], [1, 2], [2, 1], [2, 2]], actual);
}
[Fact]
public void Permutations_12_2_equals_12_21()
{
int[] data = [1, 2];
var actual = data.Permutations(2).ToArray();
Assert.Equal([[1, 2], [2, 1]], actual);
}
[Fact]
public void Permutations_repeated_123_2_equals_11_12_13_21_22_23_31_32_33()
{
int[] data = [1, 2, 3];
var actual = data.PermutationsWithRepeats(2).ToArray();
Assert.Equal([[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]], actual);
}
[Fact]
public void Permutations_123_2_equals_12_13_21_23_31_32()
{
int[] data = [1, 2, 3];
var actual = data.Permutations(2).ToArray();
Assert.Equal([[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]], actual);
}
[Fact]
public void SlidingWindowOver_none_1_equals_none()
{
int[] data = [];
var actual = data.SlidingWindow(1).ToArray();
Assert.Equal([], actual);
}
[Fact]
public void SlidingWindowOver_1_1_equals_1()
{
int[] data = [1];
var actual = data.SlidingWindow(1).ToArray();
Assert.Equal([[1]], actual);
}
[Fact]
public void SlidingWindowOver_1234_2_equals_1_12_23_34()
{
int[] data = [1, 2, 3, 4];
var actual = data.SlidingWindow(2).ToArray();
Assert.Equal([[1], [1, 2], [2, 3], [3, 4]], actual);
}
[Fact]
public void SlidingWindowOver_1234_3_equals_1_12_123_234()
{
int[] data = [1, 2, 3, 4];
var actual = data.SlidingWindow(3).ToArray();
Assert.Equal([[1], [1, 2], [1, 2, 3], [2, 3, 4]], actual);
} }
} }
+131 -21
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
namespace AdventOfCode.Extensions; namespace AdventOfCode.Extensions;
@@ -12,41 +13,150 @@ public static class EnumerableExtensions
var poolLength = pool.Length; var poolLength = pool.Length;
if (count > poolLength) if (count > poolLength)
yield break; yield break;
var indices = Range(0, count).ToArray(); int[] indices = [..Enumerable.Range(0, count)];
yield return GetCombination(indices, pool); yield return GetCombination(indices, pool);
while (true) while (true)
{ {
var validIndex = false; var idx = count - 1;
var currentIndex = 0; for(;idx >= 0; --idx)
for(var i = count - 1; i >= 0; i--)
{ {
currentIndex = i; var maxPossibleIndex = idx + poolLength - count;
if (indices[i] != i + poolLength - count) var isIndexBelowMax = indices[idx] != maxPossibleIndex;
{ if (isIndexBelowMax)
validIndex = true;
break; break;
}
} }
if(!validIndex) if(idx < 0)
yield break; yield break;
indices[currentIndex] += 1; indices[idx] += 1;
foreach (var j in Range(currentIndex + 1, count)) for (var j = idx + 1; j < indices.Length; j++)
{ {
Index ix = j - 1; indices[j] = indices[j - 1] + 1;
indices[j] = indices[ix] + 1;
} }
yield return GetCombination(indices, pool); yield return GetCombination(indices, pool);
} }
}
static TValue[] GetCombination(int[] innerIndices, TValue[] innerPool) =>
innerIndices.Select(i => innerPool[i]).ToArray(); public static IEnumerable<TValue[]> CombinationsWithRepeats<TValue>(this IEnumerable<TValue> values, int count)
{
static IEnumerable<int> Range(int start, int end) var pool = values.ToArray();
var poolLength = pool.Length;
if (count > poolLength)
yield break;
int[] indices = [..Enumerable.Repeat(0, count)];
yield return GetCombination(indices, pool);
while (true)
{ {
for (var i = start; i < end; i++) var idx = count - 1;
yield return i; for(;idx >= 0; --idx)
{
var maxPossibleIndex = poolLength - 1;
var isIndexBelowMax = indices[idx] != maxPossibleIndex;
if (isIndexBelowMax)
break;
}
if(idx < 0)
yield break;
var num = indices[idx];
for (var j = idx; j < indices.Length; j++)
{
indices[j] = num + 1;
}
yield return GetCombination(indices, pool);
}
}
public static IEnumerable<TValue[]> PermutationsWithRepeats<TValue>(this IEnumerable<TValue> values, int count)
{
var pool = values.ToArray();
if (count > pool.Length)
yield break;
var indices = Enumerable.Repeat(0, count).ToArray();
yield return GetCombination(indices, pool);
while (true)
{
var idx = count - 1;
for(;idx > 0; --idx)
{
var isIndexBelowMax = indices[idx] != idx + pool.Length - count;
if (isIndexBelowMax)
break;
}
if(indices.All(i => i >= pool.Length - 1))
yield break;
indices[idx] += 1;
for (var j = idx + 1; j < count; j++)
{
indices[j] = 0;
}
yield return GetCombination(indices, pool);
}
}
public static IEnumerable<TValue[]> Permutations<TValue>(this IEnumerable<TValue> values, int count)
{
var pool = values.ToArray();
var poolLength = pool.Length;
if (count > poolLength)
yield break;
var indices = Enumerable.Range(0, poolLength).ToArray();
var cycles = Enumerable.Range(0, poolLength + 1)
.Skip(poolLength - count + 1)
.Reverse()
.ToArray();
yield return GetCombination(indices[..count], pool);
var notDone = true;
while (notDone)
{
notDone = false;
for (var i = count - 1; i >= 0; i--)
{
cycles[i] -= 1;
if (cycles[i] == 0)
{
RotateIndices(indices, i);
cycles[i] = poolLength - i;
}
else
{
var j = cycles[i];
(indices[i], indices[^j]) = (indices[^j], indices[i]);
yield return GetCombination(indices[..count], pool);
notDone = true;
break;
}
}
}
yield break;
static void RotateIndices(int[] indices, int from)
{
var tmp = indices[from];
for (var j = from; j < indices.Length - 1; j++)
{
indices[j] = indices[j + 1];
}
indices[^1] = tmp;
}
}
private static TValue[] GetCombination<TValue>(int[] indices, TValue[] values) =>
indices.Select(i => values[i]).ToArray();
public static IEnumerable<TValue[]> SlidingWindow<TValue>(this IEnumerable<TValue> values, int count)
{
var queue = new Queue<TValue>(count);
foreach (var value in values)
{
queue.Enqueue(value);
if(queue.Count > count)
queue.Dequeue();
yield return queue.ToArray();
} }
} }
} }
+59 -1
View File
@@ -2,6 +2,12 @@
public record Coordinate(long X, long Y) public record Coordinate(long X, long Y)
{ {
public long GetManhattanDistance(Coordinate other) =>
GetManhattanDistance(this, other);
public static long GetManhattanDistance(Coordinate a, Coordinate b) =>
Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y);
public double GetEuclidianDistance(Coordinate other) => public double GetEuclidianDistance(Coordinate other) =>
GetEuclidianDistance(this, other); GetEuclidianDistance(this, other);
@@ -10,10 +16,22 @@ public record Coordinate(long X, long Y)
public static Coordinate operator +(Coordinate left, Coordinate right) => public static Coordinate operator +(Coordinate left, Coordinate right) =>
new(left.X + right.X, left.Y + right.Y); new(left.X + right.X, left.Y + right.Y);
public static Coordinate operator -(Coordinate left, Coordinate right) =>
new(left.X - right.X, left.Y - right.Y);
public static Coordinate operator *(Coordinate coord, int amount) =>
new(coord.X * amount, coord.Y * amount);
} }
public record Coordinate3d(long X, long Y, long Z) public record Coordinate3d(long X, long Y, long Z)
{ {
public long GetManhattanDistance(Coordinate3d other) =>
GetManhattanDistance(this, other);
public static long GetManhattanDistance(Coordinate3d a, Coordinate3d b) =>
Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y) + Math.Abs(a.Z - b.Z);
public double GetEuclidianDistance(Coordinate3d other) => public double GetEuclidianDistance(Coordinate3d other) =>
GetEuclidianDistance(this, other); GetEuclidianDistance(this, other);
@@ -22,4 +40,44 @@ public record Coordinate3d(long X, long Y, long Z)
public static Coordinate3d operator +(Coordinate3d left, Coordinate3d right) => public static Coordinate3d operator +(Coordinate3d left, Coordinate3d right) =>
new(left.X + right.X, left.Y + right.Y, left.Z + right.Z); new(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
}
public static Coordinate3d operator -(Coordinate3d left, Coordinate3d right) =>
new(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
public static Coordinate3d operator *(Coordinate3d coord, int amount) =>
new(coord.X * amount, coord.Y * amount, coord.Z * amount);
}
public record CoordinateNd(long[] Axes)
{
public long GetManhattanDistance(CoordinateNd other) =>
GetManhattanDistance(this, other);
public static long GetManhattanDistance(CoordinateNd a, CoordinateNd b) =>
a.Axes.Length == b.Axes.Length
? a.Axes.Zip(b.Axes, (ax, bx) => Math.Abs(ax - bx)).Sum()
: throw new DimensionMismatchException();
public double GetEuclidianDistance(CoordinateNd other) =>
GetEuclidianDistance(this, other);
public static double GetEuclidianDistance(CoordinateNd a, CoordinateNd b) =>
a.Axes.Length == b.Axes.Length
? Math.Sqrt(a.Axes.Zip(b.Axes, (ax, bx) => (ax - bx) * (ax - bx)).Sum())
: throw new DimensionMismatchException();
public static CoordinateNd operator +(CoordinateNd left, CoordinateNd right) =>
left.Axes.Length == right.Axes.Length
? new CoordinateNd([..left.Axes.Zip(right.Axes, (l, r) => l + r)])
: throw new DimensionMismatchException();
public static CoordinateNd operator -(CoordinateNd left, CoordinateNd right) =>
left.Axes.Length == right.Axes.Length
? new CoordinateNd([..left.Axes.Zip(right.Axes, (l, r) => l - r)])
: throw new DimensionMismatchException();
public static CoordinateNd operator *(CoordinateNd coord, int amount) =>
new CoordinateNd([..coord.Axes.Select(a => a * amount)]);
}
public class DimensionMismatchException : Exception {}
+2 -3
View File
@@ -23,9 +23,8 @@ public class Day10 : IPuzzleSolver<long>
.ToArray(); .ToArray();
var lamps = puzzleInput var lamps = puzzleInput
.Select(input => input.lamps) .Select(input => input.lamps)
.Select(lamps => lamps.Index()) .Select(lamps =>
.Select(ixlamps => lamps.Select(lamp => lamp == '#').ToArray())
ixlamps.Select(ixlamp => ixlamp.Item == '#').ToArray())
.ToArray(); .ToArray();
var buttons = puzzleInput var buttons = puzzleInput
.Select(input => input.buttons) .Select(input => input.buttons)