Compare commits
10
Commits
ed3b577516
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e3bb81140 | ||
|
|
554ab0557e | ||
|
|
d878ab186e | ||
|
|
9d4051ece1 | ||
|
|
0665713725 | ||
|
|
149977d02f | ||
|
|
acef1dd7d2 | ||
|
|
56521d39d7 | ||
|
|
ee061757a8 | ||
|
|
0359bacf47 |
@@ -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]
|
||||||
@@ -32,6 +30,116 @@ public class EnumerableExtensionsTest
|
|||||||
|
|
||||||
var actual = data.Combinations(3).ToArray();
|
var actual = data.Combinations(3).ToArray();
|
||||||
|
|
||||||
Assert.Contains([1, 2, 3], actual);
|
Assert.Equal([[1, 2, 3]], actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Combinations_repeated_12_2_equals_11_12_22()
|
||||||
|
{
|
||||||
|
int[] data = [1, 2];
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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) =>
|
public static IEnumerable<TValue[]> CombinationsWithRepeats<TValue>(this IEnumerable<TValue> values, int count)
|
||||||
innerIndices.Select(i => innerPool[i]).ToArray();
|
{
|
||||||
|
var pool = values.ToArray();
|
||||||
static IEnumerable<int> Range(int start, int end)
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user