Bueno, probablemente no es la forma en que me gustaría escribir, pero:
static IEnumerable<T[]> Permute<T>(this T[] xs, params T[] pre) {
if (xs.Length == 0) yield return pre;
for (int i = 0; i < xs.Length; i++) {
foreach (T[] y in Permute(xs.Take(i).Union(xs.Skip(i+1)).ToArray(), pre.Union(new[] { xs[i] }).ToArray())) {
yield return y;
}
}
}
Re su comentario; No soy completamente claro en la pregunta; si quieres decir "¿por qué es esto útil?" - entre otras cosas, hay una variedad de escenarios de fuerza bruta en los que desearía probar diferentes permutaciones; por ejemplo, para pequeños problemas de pedidos, como vendedores ambulantes (que no son lo suficientemente grandes como para justificar una solución más sofisticada), usted podría querer comprobar si es mejor ir {base, A, B, C, base}, {base, A, C, B, base}, {base, B, A, C, base}, etc.
Si quiere decir "¿cómo usaría este método?" - no probado, pero algo así como:
int[] values = {1,2,3};
foreach(int[] perm in values.Permute()) {
WriteArray(perm);
}
void WriteArray<T>(T[] values) {
StringBuilder sb = new StringBuilder();
foreach(T value in values) {
sb.Append(value).Append(", ");
}
Console.WriteLine(sb);
}
Si quiere decir "¿cómo funciona?" - Los bloques de iterador (yield return
) son un tema complejo en sí mismos. Sin embargo, Jon tiene un capítulo libre (6) in his book. El resto del código es muy parecido a su pregunta original, simplemente usando LINQ para proporcionar el equivalente moral de +
(para matrices).
La falta de tuplas y las listas por comprensión más voluminosos (es decir LINQ) es casi seguro que el código C# torpe, pero es sin duda posible traducir el código anterior línea por línea en C#. – Juliet
Esto es realmente difícil de leer. – hasen