OK, tengo solución.
No se si es la más eficiente, pero al menos cumple.
Es un poquito complicada. No de escribir, no son muchas líneas de código en verdad, pero si de entender.
A ver si puedo razonar mi conclusión...
No podemos elegir crear más o menos bucles según un valor.
¿Y por qué necesitamos esos bucles?
Porque queremos tener
varios indices para recorrer
un único array y hacer combinaciones con sus elementos.
Entonces, en realidad no necesitamos bucles,
lo que necesitamos son indices. Y entonces se me ha ocurrido crear una
tabla de indices, es decir, un array.
El tamaño de este array dependerá de los elementos que tenga el array con los valores que queremos combinar.
Si tiene dos elementos, tendremos dos indices en la tabla. Si nos envían tres elementos, pues tres indices, etc...
Con esos indices, combinaremos los valores recibidos. Y tras mostrar en pantalla cada combinación, actualizaremos la tabla de indices de la forma apropiada.
Por ejemplo, si nos envían los valores: [10, 20, 30]
Pues crearemos una tabla de tres indices: [0, 0, 0]
Para "crear" cada combinación, iniciaremos un bucle donde se irá creando un tercer array con el mismo número de elementos, seleccionado los elementos que indiquen los indices de la tabla.
Así la primera iteración del bucle, como todos los indices de la tabla apuntan a valor 0, pues la primera combinación será : [10, 10, 10]
Tras mostrar esa combinación, actualizamos la tabla: [0, 0, 1]
Se repite el bucle y la siguiente combinación será: [10, 10, 20]
Y actualizamos de nuevo la tabla: [0, 0, 2]
Siguiente combinación: [10, 10, 30]
Actualizamos tabla: [0, 1, 0]
Nueva combinación: [10, 20, 10]
Tabla se actualiza: [0, 1, 1]
Combinación: [10, 20, 20]
Y así sucesivamente, los indices pasarán por todos sus posibles valores y con ellos podremos hacer todas las combinaciones de los valores que nos hayan pasado.
Lo único complicado es actualizar la tabla de forma correcta.
Hay que ir recorriéndola a la inversa, del último indice al primero.
Comprobar si el último indice se puede incrementar. El límite hasta donde podemos incrementar nos lo da la propia cantidad de elementos que nos han pasado. Si nos dan 3 elementos, el valor máximo de cada indice es 2 (3 - 1)
Si un indice no se puede incrementar porque ya está en su límite, nos movemos por la tabla (hacia atrás) para consultar el indice anterior a este.
Pero, hay momentos que un indice que ya está al máximo, ha de reiniciarse a valor 0.
¿Cómo sabemos cuándo han de volver a 0 los indices y cuándo no?
Esto es lo que me ha traído un poquito de cabeza, encontrar una solución óptima y que sea más o menos entendible...
La solución que he dado es que, antes de intentar incrementar el próximo indice de la tabla (si es que aun quedan), compruebo si es "incrementable".
Si lo es, implica que el indice actual, y los siguientes... han de reiniciarse a valor 0.
Por ejemplo, supongamos que la tabla de indices es esta: [0, 1, 2]
Empiezo desde el final y pregunto si puedo incrementar el último indice.
No puedo, porque ya tiene el valor máximo.
Intentaré incrementar el indice anterior, pero antes quiero saber si el indice actual ha de volver a 0. Así que antes de posicionarme en el indice anterior, pregunto si es incrementable. La respuesta es sí, entonces reinicio a 0 el indice actual.
Y ahora ya sí me voy al anterior y lo incremento.
La tabla me quedaría: [0, 2, 0]
Supongamos que luego la tabla llega a ese valor: [0, 2, 2]
¿Puedo incrementar el último indice? No.
¿He de ponerlo a 0? El indice anterior a este NO es incrementable ahora mismo, por tanto, PARECE que no he de resetear a 0 el último.
Lo dejo como está y paso al anterior. ¿Puedo incrementarlo? No, también tiene valor máximo.
¿He de ponerlo a 0? Pues el indice anterior (el primero) SI es incrementable.
Así que reseteo a 0 el indice actual, pero también todos los siguientes a él, aunque previamente parecía que no se iban a resetear.
Y tras resetearlos a 0, paso al primer indice y lo incremento.
La tabla queda: [1, 0, 0]
Por último, supongamos que la tabla llega a: [2, 2, 2]
¿Último indice incrementable? No.
¿Se ha de resetear? Parece que no, pues el anterior tampoco es incrementable.
Paso a indice anterior, ¿es incrementable? Ya hemos visto que no.
¿Se ha de resetear? Parece que no, pues su anterior tampoco es incrementable.
Paso a indice anterior, el primero de la tabla (y el último a comprobar).
¿Incrementable? No.
¿Reseteable a 0? No, porque no tiene un indice anterior. Ninguno ha de volver a 0, porque esa sería la última combinación posible.
El proceso habría terminado.
Bien, no se si estas explicaciones son suficientes para entender la lógica que he seguido.
Dejo aquí el código. Pregunta lo que no entiendas.
Como digo, no son muchas líneas (casi hay más comentarios que código), pero la lógica es un poco liosa, pues hay un indice, que apunta al array de indices, que son los indices que combinan elementos... suena un poco loco... ¡¡pero funciona!!