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
|
||||
{
|
||||
[Fact]
|
||||
public void Combinations_12_2_equals_12_21()
|
||||
public void Combinations_12_2_equals_12()
|
||||
{
|
||||
int[] data = [1, 2];
|
||||
|
||||
var actual = data.Combinations(2).ToArray();
|
||||
|
||||
Assert.Contains([1, 2], actual);
|
||||
Assert.Equal([[1, 2]], actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -20,9 +20,7 @@ public class EnumerableExtensionsTest
|
||||
|
||||
var actual = data.Combinations(2).ToArray();
|
||||
|
||||
Assert.Contains([1, 2], actual);
|
||||
Assert.Contains([1, 3], actual);
|
||||
Assert.Contains([2, 3], actual);
|
||||
Assert.Equal([[1, 2], [1, 3], [2, 3]], actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -32,6 +30,116 @@ public class EnumerableExtensionsTest
|
||||
|
||||
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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace AdventOfCode.Extensions;
|
||||
|
||||
@@ -12,41 +13,150 @@ public static class EnumerableExtensions
|
||||
var poolLength = pool.Length;
|
||||
if (count > poolLength)
|
||||
yield break;
|
||||
var indices = Range(0, count).ToArray();
|
||||
int[] indices = [..Enumerable.Range(0, count)];
|
||||
yield return GetCombination(indices, pool);
|
||||
while (true)
|
||||
{
|
||||
var validIndex = false;
|
||||
var currentIndex = 0;
|
||||
for(var i = count - 1; i >= 0; i--)
|
||||
var idx = count - 1;
|
||||
for(;idx >= 0; --idx)
|
||||
{
|
||||
currentIndex = i;
|
||||
if (indices[i] != i + poolLength - count)
|
||||
{
|
||||
validIndex = true;
|
||||
var maxPossibleIndex = idx + poolLength - count;
|
||||
var isIndexBelowMax = indices[idx] != maxPossibleIndex;
|
||||
if (isIndexBelowMax)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!validIndex)
|
||||
if(idx < 0)
|
||||
yield break;
|
||||
|
||||
indices[currentIndex] += 1;
|
||||
foreach (var j in Range(currentIndex + 1, count))
|
||||
indices[idx] += 1;
|
||||
for (var j = idx + 1; j < indices.Length; j++)
|
||||
{
|
||||
Index ix = j - 1;
|
||||
indices[j] = indices[ix] + 1;
|
||||
indices[j] = indices[j - 1] + 1;
|
||||
}
|
||||
|
||||
yield return GetCombination(indices, pool);
|
||||
}
|
||||
}
|
||||
|
||||
static TValue[] GetCombination(int[] innerIndices, TValue[] innerPool) =>
|
||||
innerIndices.Select(i => innerPool[i]).ToArray();
|
||||
|
||||
static IEnumerable<int> Range(int start, int end)
|
||||
public static IEnumerable<TValue[]> CombinationsWithRepeats<TValue>(this IEnumerable<TValue> values, int count)
|
||||
{
|
||||
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++)
|
||||
yield return i;
|
||||
var idx = count - 1;
|
||||
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 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) =>
|
||||
GetEuclidianDistance(this, other);
|
||||
|
||||
@@ -10,10 +16,22 @@ public record Coordinate(long X, long Y)
|
||||
|
||||
public static Coordinate operator +(Coordinate left, Coordinate right) =>
|
||||
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 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) =>
|
||||
GetEuclidianDistance(this, other);
|
||||
|
||||
@@ -22,4 +40,44 @@ public record Coordinate3d(long X, long Y, long 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 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();
|
||||
var lamps = puzzleInput
|
||||
.Select(input => input.lamps)
|
||||
.Select(lamps => lamps.Index())
|
||||
.Select(ixlamps =>
|
||||
ixlamps.Select(ixlamp => ixlamp.Item == '#').ToArray())
|
||||
.Select(lamps =>
|
||||
lamps.Select(lamp => lamp == '#').ToArray())
|
||||
.ToArray();
|
||||
var buttons = puzzleInput
|
||||
.Select(input => input.buttons)
|
||||
|
||||
Reference in New Issue
Block a user