再帰関数を使用して配列のすべての順列を出力するメソッドがあります。
/// <summary>
/// Yields a sequence of all permutations in lexical order
/// </summary>
/// <typeparam name="T">Type of item in the input sequence</typeparam>
/// <param name="input">The initial sequence</param>
/// <returns>A sequence of all permutations in lexical order</returns>
public IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> input)
{
var list = input.ToList();
list.Sort(); // into lexical order
if (list.Count > 2)
{
foreach (var item in list)
{
var itemArray = new[] {item};
T[] otherItems = list.Except(itemArray).ToArray();
foreach (var permutation in Permute(otherItems))
yield return itemArray.Concat(permutation).ToArray();
}
}
else
{
yield return new[] {list[0], list[1]};
yield return new[] {list[1], list[0]};
}
}
ただし、NUnit テストでこの関数を実行すると、予想よりもはるかに早く終了します。
[Test]
public void Can_print_all_permutations()
{
foreach (var p in Permute("123456789"))
{
Console.WriteLine(new string(p.ToArray()));
}
}
テストによって出力された最後の行は次のとおりです (投稿目的でカンマで区切りました)。
349527816、349527861、349528167、349528176、349528617、3
突然の終了は、コンソールによるバッファリングとフラッシュが問題の一部であると思わせますが、表示される最後の行は 987654321 であるため、ループが早期に終了しているように感じます。
ループに計算を含めると、さらに早く (24... の範囲で) 終了します。
この動作を説明する実装に何かありますか? スタックの限界を押し上げていますか?