todas sacar programacion posibles online mostrar letras las hacer combinaciones algoritmo c# combinatorics cartesian-product

c# - sacar - posibles combinaciones de 2 letras



Generando todas las combinaciones posibles (11)

Dadas 2 matrices Array1 = {a,b,c...n} y Array2 = {10,20,15....x} ¿cómo puedo generar todas las combinaciones posibles como Cadenas a (i) b (j) c ( k) n (p) donde

1 <= i <= 10, 1 <= j <= 20 , 1 <= k <= 15, .... 1 <= p <= x

Como:

a1 b1 c1 .... n1 a1 b1 c1..... n2 ...... ...... a10 b20 c15 nx (last combination)

Entonces en todo el número total de combinación = producto de elementos de array2 = (10 X 20 X 15 X ..X x)

Similar a un producto cartesiano, en el que el segundo conjunto define el límite superior para cada elemento en el primer conjunto.

Ejemplo con números fijos,

Array x = [a,b,c] Array y = [3,2,4]

Entonces tendremos 3 * 2 * 4 = 24 combinaciones. Los resultados deberían ser:

a1 b1 c1 a1 b1 c2 a1 b1 c3 a1 b1 c4 a1 b2 c1 a1 b2 c2 a1 b2 c3 a1 b2 c4 a2 b1 c1 a2 b1 c2 a2 b1 c3 a2 b1 c4 a2 b2 c1 a2 b2 c2 a2 b2 c3 a2 b2 c4 a3 b1 c1 a3 b1 c2 a3 b1 c3 a3 b1 c4 a3 b2 c1 a3 b2 c2 a3 b2 c3 a3 b2 c4 (last)


A modo de comparación, aquí hay una forma de hacerlo con Python

from itertools import product X=["a", "b", "c"] Y=[3, 4, 2] terms = (["%s%s"%(x,i+1) for i in range(y)] for x,y in zip(X,Y)) for item in product(*terms): print " ".join(item)



Aquí hay una versión de JavaScript, que estoy seguro de que alguien puede convertir. Ha sido probado a fondo.

Aquí está el violín .

function combinations (Asource){ var combos = []; var temp = []; var picker = function (arr, temp_string, collect) { if (temp_string.length) { collect.push(temp_string); } for (var i=0; i<arr.length; i++) { var arrcopy = arr.slice(0, arr.length); var elem = arrcopy.splice(i, 1); if (arrcopy.length > 0) { picker(arrcopy, temp_string.concat(elem), collect); } else { collect.push(temp_string.concat(elem)); } } } picker(Asource, temp, combos); return combos; } var todo = ["a", "b", "c", "d"]; // 5 in this set var resultingCombos = combinations (todo); console.log(resultingCombos);


Cosa segura. Es un poco complicado hacer esto con LINQ, pero ciertamente es posible usar solo los operadores de consulta estándar.

ACTUALIZACIÓN: Este es el tema de mi blog el lunes 28 de junio de 2010 ; gracias por la gran pregunta. Además, un comentarista en mi blog señaló que hay una consulta aún más elegante que la que di. Actualizaré el código aquí para usarlo.

La parte difícil es hacer el producto cartesiano de muchas secuencias arbitrariamente. "Comprimir" en las letras es trivial en comparación con eso. Debes estudiar esto para asegurarte de que entiendes cómo funciona. Cada parte es lo suficientemente simple, pero la forma en que se combinan entre sí requiere un tiempo para acostumbrarse:

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) { IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>()}; return sequences.Aggregate( emptyProduct, (accumulator, sequence) => from accseq in accumulator from item in sequence select accseq.Concat(new[] {item}) ); }

Para explicar cómo funciona esto, primero comprenda qué está haciendo la operación "acumular". La operación de acumulación más simple es "agregar todo en esta secuencia". La forma en que haces eso es: comienza con cero. Para cada elemento de la secuencia, el valor actual del acumulador es igual a la suma del elemento y el valor previo del acumulador. Estamos haciendo lo mismo, excepto que en lugar de acumular la suma basada en la suma hasta el momento y el artículo actual, estamos acumulando el producto cartesiano sobre la marcha.

La forma en que vamos a hacer eso es aprovechar el hecho de que ya tenemos un operador en LINQ que calcula el producto cartesiano de dos cosas:

from x in xs from y in ys do something with each possible (x, y)

Al tomar repetidamente el producto cartesiano del acumulador con el siguiente elemento de la secuencia de entrada y pegar un poco los resultados, podemos generar el producto cartesiano sobre la marcha.

Entonces piensa en el valor del acumulador. Para fines ilustrativos, mostraré el valor del acumulador como los resultados de los operadores de secuencia que contiene. Eso no es lo que el acumulador realmente contiene. Lo que el acumulador realmente contiene son los operadores que producen estos resultados. Toda la operación aquí solo crea un árbol masivo de operadores de secuencia, cuyo resultado es el producto cartesiano. Pero el producto cartesiano final en sí mismo no se calcula hasta que se ejecuta la consulta. Con fines ilustrativos, mostraré cuáles son los resultados en cada etapa del camino, pero recuerde que esto realmente contiene los operadores que producen esos resultados.

Supongamos que tomamos el producto cartesiano de la secuencia de secuencias {{1, 2}, {3, 4}, {5, 6}} . El acumulador comienza como una secuencia que contiene una secuencia vacía: { { } }

En la primera acumulación, el acumulador es {{}} y el elemento es {1, 2}. Nosotros hacemos esto:

from accseq in accumulator from item in sequence select accseq.Concat(new[] {item})

Así que estamos tomando el producto cartesiano de { { } } con {1, 2} , y para cada par, concatenamos: Tenemos el par ({ }, 1) , así que concatenamos { } y {1} para obtener {1} . Tenemos el par ({ }, 2}) , así que concatenamos { } y {2} para obtener {2} . Por lo tanto, tenemos {{1}, {2}} como resultado.

Entonces, en la segunda acumulación, el acumulador es {{1}, {2}} y el elemento es {3, 4} . De nuevo, calculamos el producto cartesiano de estas dos secuencias para obtener:

{({1}, 3), ({1}, 4), ({2}, 3), ({2}, 4)}

y luego de esos elementos, concatenar el segundo sobre el primero. Entonces el resultado es la secuencia {{1, 3}, {1, 4}, {2, 3}, {2, 4}} , que es lo que queremos.

Ahora nos acumulamos de nuevo. Tomamos el producto cartesiano del acumulador con {5, 6} para obtener

{({ 1, 3}, 5), ({1, 3}, 6), ({1, 4}, 5), ...

y luego concatenar el segundo elemento sobre el primero para obtener:

{{1, 3, 5}, {1, 3, 6}, {1, 4, 5}, {1, 4, 6} ... }

y hemos terminado. Hemos acumulado el producto cartesiano.

Ahora que tenemos una función de utilidad que puede tomar el producto cartesiano de muchas secuencias arbitrariamente, el resto es fácil en comparación:

var arr1 = new[] {"a", "b", "c"}; var arr2 = new[] { 3, 2, 4 }; var result = from cpLine in CartesianProduct( from count in arr2 select Enumerable.Range(1, count)) select cpLine.Zip(arr1, (x1, x2) => x2 + x1);

Y ahora tenemos una secuencia de secuencias de cadenas, una secuencia de cadenas por línea:

foreach (var line in result) { foreach (var s in line) Console.Write(s); Console.WriteLine(); }

¡Pan comido!


El resultado final es el conjunto deseado. Se supone que ambas matrices son del mismo tamaño.

char[] Array1 = { ''a'', ''b'', ''c'' }; int[] Array2 = { 3, 2, 4 }; var finalResult = new List<string>(); finalResult.Add(String.Empty); for(int i=0; i<Array1.Length; i++) { var tmp = from a in finalResult from b in Enumerable.Range(1,Array2[i]) select String.Format("{0} {1}{2}",a,Array1[i],b).Trim(); finalResult = tmp.ToList(); }

Creo que esto será suficiente.


Fon otra solución no basada en linq puedes usar:

public class CartesianProduct<T> { int[] lengths; T[][] arrays; public CartesianProduct(params T[][] arrays) { lengths = arrays.Select(k => k.Length).ToArray(); if (lengths.Any(l => l == 0)) throw new ArgumentException("Zero lenght array unhandled."); this.arrays = arrays; } public IEnumerable<T[]> Get() { int[] walk = new int[arrays.Length]; int x = 0; yield return walk.Select(k => arrays[x++][k]).ToArray(); while (Next(walk)) { x = 0; yield return walk.Select(k => arrays[x++][k]).ToArray(); } } private bool Next(int[] walk) { int whoIncrement = 0; while (whoIncrement < walk.Length) { if (walk[whoIncrement] < lengths[whoIncrement] - 1) { walk[whoIncrement]++; return true; } else { walk[whoIncrement] = 0; whoIncrement++; } } return false; } }

Puede encontrar un ejemplo sobre cómo usarlo aquí .


Fon otra solución no basada en linq, más efectiva:

static IEnumerable<T[]> CartesianProduct<T>(T[][] arrays) { int[] lengths; lengths = arrays.Select(a => a.Length).ToArray(); int Len = arrays.Length; int[] inds = new int[Len]; int Len1 = Len - 1; while (inds[0] != lengths[0]) { T[] res = new T[Len]; for (int i = 0; i != Len; i++) { res[i] = arrays[i][inds[i]]; } yield return res; int j = Len1; inds[j]++; while (j > 0 && inds[j] == lengths[j]) { inds[j--] = 0; inds[j]++; } } }


No estoy dispuesto a darte el código fuente completo. Así que aquí está la idea detrás.

Puedes generar los elementos de la siguiente manera:

Supongo que A=(a1, a2, ..., an) y B=(b1, b2, ..., bn) (por lo que A y B tienen cada uno n elementos).

¡Entonces hazlo recursivamente! Escribe un método que tome una A y una B y haga tus cosas:

Si A y B contienen cada uno un solo elemento (llamado an resp. bn ), simplemente itera de 1 a bn y concatenar an a tu variable de iteración.

Si A y B contienen cada uno más de un elemento, toma los primeros elementos ( a1 resp b1 ), itera de 1 a bn y haz para cada paso de iteración:

  • llama al método recursivamente con los subcampos de A y B comenzando en el segundo elemento, es decir, A''=(a2, a3, ..., an) resp B''=(b2, b3, ..., bn) . Para cada elemento generado por la llamada recursiva, concatenar a1 , la variable iterativa y el elemento generado de la llamada recursiva.

Here puede encontrar un ejemplo analítico de cómo generar cosas en C #, usted "solo" tiene que adaptarlo a sus necesidades.


Si lo estoy haciendo bien, buscas algo como producto cartesiano . Si este es el caso, aquí está cómo puede hacerlo utilizando LINQ. Puede que no sea la respuesta exacta, pero intente obtener la idea

char[] Array1 = { ''a'', ''b'', ''c'' }; string[] Array2 = { "10", "20", "15" }; var result = from i in Array1 from j in Array2 select i + j;

Estos artículos pueden ayudar


Solución alternativa:

Paso uno: lea mi serie de artículos sobre cómo generar todas las cadenas que coincidan con una gramática sensible al contexto:

http://blogs.msdn.com/b/ericlippert/archive/tags/grammars/

Paso dos: defina una gramática que genere el idioma que desea. Por ejemplo, puedes definir la gramática:

S: a A b B c C A: 1 | 2 | 3 B: 1 | 2 C: 1 | 2 | 3 | 4

Claramente, puede generar fácilmente esa cadena de definición gramatical a partir de sus dos matrices. Luego, introdúzcalo en el código que genera todas las cadenas en una gramática dada, y listo; obtendrás todas las posibilidades. (No necesariamente en el orden en que los quiere, no se preocupe).


using System; using System.Text; public static string[] GenerateCombinations(string[] Array1, int[] Array2) { if(Array1 == null) throw new ArgumentNullException("Array1"); if(Array2 == null) throw new ArgumentNullException("Array2"); if(Array1.Length != Array2.Length) throw new ArgumentException("Must be the same size as Array1.", "Array2"); if(Array1.Length == 0) return new string[0]; int outputSize = 1; var current = new int[Array1.Length]; for(int i = 0; i < current.Length; ++i) { if(Array2[i] < 1) throw new ArgumentException("Contains invalid values.", "Array2"); if(Array1[i] == null) throw new ArgumentException("Contains null values.", "Array1"); outputSize *= Array2[i]; current[i] = 1; } var result = new string[outputSize]; for(int i = 0; i < outputSize; ++i) { var sb = new StringBuilder(); for(int j = 0; j < current.Length; ++j) { sb.Append(Array1[j]); sb.Append(current[j].ToString()); if(j != current.Length - 1) sb.Append('' ''); } result[i] = sb.ToString(); int incrementIndex = current.Length - 1; while(incrementIndex >= 0 && current[incrementIndex] == Array2[incrementIndex]) { current[incrementIndex] = 1; --incrementIndex; } if(incrementIndex >= 0) ++current[incrementIndex]; } return result; }