-
-
Notifications
You must be signed in to change notification settings - Fork 52
/
Statics-Combinations.cs
85 lines (81 loc) · 3.98 KB
/
Statics-Combinations.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
namespace Towel;
/// <summary>Root type of the static functional methods in Towel.</summary>
public static partial class Statics
{
/// <summary>Iterates through all combinations of the provided per-index element values.</summary>
/// <typeparam name="T">The element type of the combinations to iterate.</typeparam>
/// <param name="elementPosibilities">The possible element values at each index.</param>
/// <param name="action">The action to perform on each possible combination.</param>
public static void Combinations<T>(T[][] elementPosibilities, Action_ReadOnlySpan<T> action) =>
Combinations<T, Action_ReadOnlySpan_Runtime<T>>(elementPosibilities, action);
/// <summary>Iterates through all combinations of the provided per-index element values.</summary>
/// <typeparam name="T">The element type of the combinations to iterate.</typeparam>
/// <typeparam name="TAction">The action to perform on each combination.</typeparam>
/// <param name="elementPosibilities">The possible element values at each index.</param>
/// <param name="action">The action to perform on each possible combination.</param>
public static void Combinations<T, TAction>(T[][] elementPosibilities, TAction action = default)
where TAction : struct, IAction_ReadOnlySpan<T> =>
Combinations<T, TAction, Func_int_int_JaggedArray_Length0<T>, Func_int_int_T_JaggedArray_Get<T>>(
elementPosibilities.Length,
action,
elementPosibilities,
elementPosibilities);
/// <summary>Iterates through all combinations of the provided per-index element values.</summary>
/// <typeparam name="T">The element type of the combinations to iterate.</typeparam>
/// <param name="length">The length of the spans to iterate.</param>
/// <param name="action">The action to perform on each combination.</param>
/// <param name="indexPossibilities">The function to get the possible element values at each index.</param>
/// <param name="valueAt">The action to perform on each possible combination.</param>
public static void Combinations<T>(int length, Action_ReadOnlySpan<T> action, Func<int, int> indexPossibilities, Func<int, int, T> valueAt) =>
Combinations<T, Action_ReadOnlySpan_Runtime<T>, SFunc<int, int>, SFunc<int, int, T>>(length, action, indexPossibilities, valueAt);
/// <summary>Iterates through all combinations of the provided per-index element values.</summary>
/// <typeparam name="T">The element type of the combinations to iterate.</typeparam>
/// <typeparam name="TAction">Thetype of action to perform on each combination.</typeparam>
/// <typeparam name="TIndexPossibilities">The type of function to get the possible element values at each index.</typeparam>
/// <typeparam name="TValueAt">The type of action to perform on each possible combination.</typeparam>
/// <param name="length">The length of the spans to iterate.</param>
/// <param name="action">The action to perform on each combination.</param>
/// <param name="indexPossibilities">The function to get the possible element values at each index.</param>
/// <param name="valueAt">The action to perform on each possible combination.</param>
public static void Combinations<T, TAction, TIndexPossibilities, TValueAt>(
int length,
TAction action = default,
TIndexPossibilities indexPossibilities = default,
TValueAt valueAt = default)
where TAction : struct, IAction_ReadOnlySpan<T>
where TIndexPossibilities : struct, IFunc<int, int>
where TValueAt : struct, IFunc<int, int, T>
{
Span<int> digits = stackalloc int[length];
Span<T> span = new T[length];
for (int i = 0; i < span.Length; i++)
{
digits[i] = 0;
span[i] = valueAt.Invoke(i, 0);
}
while (true)
{
action.Invoke(span);
int digit = 0;
while (true)
{
if (digit >= length)
{
return;
}
digits[digit]++;
if (digits[digit] >= indexPossibilities.Invoke(digit))
{
digits[digit] = 0;
span[digit] = valueAt.Invoke(digit, digits[digit]);
digit++;
}
else
{
span[digit] = valueAt.Invoke(digit, digits[digit]);
break;
}
}
}
}
}