You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
6.6 KiB
181 lines
6.6 KiB
namespace WhiteRabbit
|
|
{
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
|
|
/// <summary>
|
|
/// Converts e.g. pair of variants [[a, b, c], [d, e]] into all possible pairs: [[a, d], [a, e], [b, d], [b, e], [c, d], [c, e]]
|
|
/// </summary>
|
|
internal static class Flattener
|
|
{
|
|
// Slow universal implementation
|
|
private static IEnumerable<ImmutableStack<T>> FlattenAny<T>(ImmutableStack<T[]> phrase)
|
|
{
|
|
if (phrase.IsEmpty)
|
|
{
|
|
return new[] { ImmutableStack.Create<T>() };
|
|
}
|
|
|
|
T[] wordVariants;
|
|
var newStack = phrase.Pop(out wordVariants);
|
|
return FlattenAny(newStack).SelectMany(remainder => wordVariants.Select(word => remainder.Push(word)));
|
|
}
|
|
|
|
// Fast hard-coded implementation for 3 words
|
|
private static IEnumerable<T[]> Flatten3<T>(T[][] phrase)
|
|
{
|
|
for (var i0 = 0; i0 < phrase[0].Length; i0++)
|
|
{
|
|
for (var i1 = 0; i1 < phrase[1].Length; i1++)
|
|
{
|
|
for (var i2 = 0; i2 < phrase[2].Length; i2++)
|
|
{
|
|
yield return new T[]
|
|
{
|
|
phrase[0][i0],
|
|
phrase[1][i1],
|
|
phrase[2][i2],
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fast hard-coded implementation for 4 words
|
|
private static IEnumerable<T[]> Flatten4<T>(T[][] phrase)
|
|
{
|
|
for (var i0 = 0; i0 < phrase[0].Length; i0++)
|
|
{
|
|
for (var i1 = 0; i1 < phrase[1].Length; i1++)
|
|
{
|
|
for (var i2 = 0; i2 < phrase[2].Length; i2++)
|
|
{
|
|
for (var i3 = 0; i3 < phrase[3].Length; i3++)
|
|
{
|
|
yield return new T[]
|
|
{
|
|
phrase[0][i0],
|
|
phrase[1][i1],
|
|
phrase[2][i2],
|
|
phrase[3][i3],
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fast hard-coded implementation for 5 words
|
|
private static IEnumerable<T[]> Flatten5<T>(T[][] phrase)
|
|
{
|
|
for (var i0 = 0; i0 < phrase[0].Length; i0++)
|
|
{
|
|
for (var i1 = 0; i1 < phrase[1].Length; i1++)
|
|
{
|
|
for (var i2 = 0; i2 < phrase[2].Length; i2++)
|
|
{
|
|
for (var i3 = 0; i3 < phrase[3].Length; i3++)
|
|
{
|
|
for (var i4 = 0; i4 < phrase[4].Length; i4++)
|
|
{
|
|
yield return new T[]
|
|
{
|
|
phrase[0][i0],
|
|
phrase[1][i1],
|
|
phrase[2][i2],
|
|
phrase[3][i3],
|
|
phrase[4][i4],
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fast hard-coded implementation for 6 words
|
|
private static IEnumerable<T[]> Flatten6<T>(T[][] phrase)
|
|
{
|
|
for (var i0 = 0; i0 < phrase[0].Length; i0++)
|
|
{
|
|
for (var i1 = 0; i1 < phrase[1].Length; i1++)
|
|
{
|
|
for (var i2 = 0; i2 < phrase[2].Length; i2++)
|
|
{
|
|
for (var i3 = 0; i3 < phrase[3].Length; i3++)
|
|
{
|
|
for (var i4 = 0; i4 < phrase[4].Length; i4++)
|
|
{
|
|
for (var i5 = 0; i5 < phrase[5].Length; i5++)
|
|
{
|
|
yield return new T[]
|
|
{
|
|
phrase[0][i0],
|
|
phrase[1][i1],
|
|
phrase[2][i2],
|
|
phrase[3][i3],
|
|
phrase[4][i4],
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fast hard-coded implementation for 7 words
|
|
private static IEnumerable<T[]> Flatten7<T>(T[][] phrase)
|
|
{
|
|
for (var i0 = 0; i0 < phrase[0].Length; i0++)
|
|
{
|
|
for (var i1 = 0; i1 < phrase[1].Length; i1++)
|
|
{
|
|
for (var i2 = 0; i2 < phrase[2].Length; i2++)
|
|
{
|
|
for (var i3 = 0; i3 < phrase[3].Length; i3++)
|
|
{
|
|
for (var i4 = 0; i4 < phrase[4].Length; i4++)
|
|
{
|
|
for (var i5 = 0; i5 < phrase[5].Length; i5++)
|
|
{
|
|
for (var i6 = 0; i6 < phrase[6].Length; i6++)
|
|
{
|
|
yield return new T[]
|
|
{
|
|
phrase[0][i0],
|
|
phrase[1][i1],
|
|
phrase[2][i2],
|
|
phrase[3][i3],
|
|
phrase[4][i4],
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static IEnumerable<T[]> Flatten<T>(T[][] wordVariants)
|
|
{
|
|
switch (wordVariants.Length)
|
|
{
|
|
case 3:
|
|
return Flatten3(wordVariants);
|
|
case 4:
|
|
return Flatten4(wordVariants);
|
|
case 5:
|
|
return Flatten5(wordVariants);
|
|
case 6:
|
|
return Flatten6(wordVariants);
|
|
case 7:
|
|
return Flatten7(wordVariants);
|
|
default:
|
|
return FlattenAny(ImmutableStack.Create(wordVariants)).Select(words => words.ToArray());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|