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 = Enumerable.Range(0, count).ToArray(); yield return GetCombination(indices, pool); while (true) { var idx = count - 1; for(;idx >= 0; --idx) { var isIndexBelowMax = indices[idx] != idx + poolLength - count; if (isIndexBelowMax) break; } if(idx < 0) yield break; indices[idx] += 1; for (var j = idx + 1; j < count; j++) { indices[j] = indices[j - 1] + 1; } yield return GetCombination(indices, pool); } } public static IEnumerable Permutations(this IEnumerable values, int count) { var pool = values.ToArray(); if (count > pool.Length) yield break; foreach (var p in InnerPermutations(pool, count)) yield return p; foreach (var p in InnerPermutations([..pool.Reverse()], count)) yield return p; yield break; static IEnumerable InnerPermutations(TValue[] pool, int count) { 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(idx < 0) break; indices[idx] += 1; for (var j = idx + 1; j < count; j++) { indices[j] = indices[j - 1]; } yield return GetCombination(indices, pool); } } } private static TValue[] GetCombination(int[] innerIndices, TValue[] innerPool) => innerIndices.Select(i => innerPool[i]).ToArray(); }