Java - For anidados dependiendo de una variable

 
Vista:
sin imagen de perfil
Val: 15
Ha aumentado su posición en 6 puestos en Java (en relación al último mes)
Gráfica de Java

For anidados dependiendo de una variable

Publicado por Raul (4 intervenciones) el 14/11/2020 20:47:45
Buenas tardes,
Necesito realizar combinaciones de numeros enteros que nos dan. Si sabemos los elementos que hay es simplemente realizar for anidados de la siguiente manera, por ejemplo si me dan dos números almacenados en un array que se llama valores (con los valores 0 y 1) la longitud sería 2 y lo haríamos con dos for anidados:

1
2
3
4
5
6
7
for(int i=0;i<longitud;i++)
{
    for (int j=0;j<longitud;j++)
    {
        System.out.println("["+valores.get(i)+","+valores.get(j)+"]");
    }
}

Y tendríamos la salida [0,0] [0,1] [1,0] [1,1] .

¿Cómo puedo hacer el código para que de manera dinámica dependiendo de la longitud se hagan las combinaciones de números usando los for necesarios? Si la longitud es 3 debo hacer tres for, si la longitud es 4 debo hacer cuatro for y así sucesivamente pero no sé como realizar el código de manera eficiente para no tener que reescribir un método para cada longitud.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
1
Responder
sin imagen de perfil
Val: 15
Ha aumentado su posición en 6 puestos en Java (en relación al último mes)
Gráfica de Java

For anidados dependiendo de una variable

Publicado por Raul (4 intervenciones) el 15/11/2020 11:16:57
Alguien sabe como solucionarlo??
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

For anidados dependiendo de una variable

Publicado por Kabuto (1381 intervenciones) el 15/11/2020 12:00:26
Hola.

No estás siendo ignorado, estoy dándole vueltas pero por el momento no veo la lógica que se podría aplicar.

Quizás el camino sea aplicar recursividad, pero aún no se como convendría hacerlo...

A ver si alguien más listo puede iluminarnos je je..
Si se me ocurre algo lo publico por aquí.

Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 15
Ha aumentado su posición en 6 puestos en Java (en relación al último mes)
Gráfica de Java

For anidados dependiendo de una variable

Publicado por Raul (4 intervenciones) el 15/11/2020 12:08:50
Perfecto muchas gracias,
seguiremos esperando a ver si alguien se le ocurre alguna solución, yo sigo dándole vueltas y por ahora no la encuentro.
Saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Kabuto
Val: 3.428
Oro
Ha mantenido su posición en Java (en relación al último mes)
Gráfica de Java

For anidados dependiendo de una variable

Publicado por Kabuto (1381 intervenciones) el 15/11/2020 13:58:13
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!!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class Combinaciones {
 
	public static void main(String[] args) {
		int[] numeros = {10,20,30};
 
		combinaciones(numeros);
 
	}
 
	public static void combinaciones(int[] valores) {
 
		int[] indices = new int[valores.length]; //Tabla de indices con los que crear combos
		int valorMaximoDeIndice = indices.length - 1; //Valor maximo que puede alcanzar cada indice de la tabla
		boolean indicesRecorridos = false; //Cuanto TODOS los indices hayan pasado por TODOS los valores, será TRUE
 
		while(!indicesRecorridos) {
			//Creamos combinacion.
			int[] combo = new int[indices.length];
			for (int i = 0; i < combo.length; i++)
				combo[i] = valores[indices[i]];
			//Imprimimos en pantalla
			System.out.println(Arrays.toString(combo));
 
			//Actualizamos tabla de indices para el próximo combo
			/*
			 * Recorremos la tabla de indices a la inversa,
			 * a ver que indice toca actualizar.
			 * Si no se actualiza ninguno, es que ya se han
			 * recorrido todos y no quedan combos por hacer.
			 */
			boolean actualizacion = false; //Para controlar si habrá actualizacion o no
			int posicion = indices.length -1; //Posicion de la tabla de indices que intentamos actualizar
			while(!actualizacion && posicion >= 0) {
				if (posicion >= 0) {
					if (indices[posicion] < valorMaximoDeIndice) {
						indices[posicion]++; //no tiene valor maximo, se puede incrementar
						actualizacion = true; //Esto pone fin a este bucle
					}
					else {
						/*
						 * Esta posición no se puede incrementar porque ya tiene el valor máximo.
						 * Habrá que revisar la próxima posición (hacia atrás).
						 * Pero antes, vamos a comprobar si esta posición actual, es necesario
						 * reiniciarla a 0.
						 * Esto depende de si la próxima posición es incrementable o no, y debemos
						 * comprobarlo previamente.
						 */
						if (posicion > 0) { //Aun queda una posición próxima (hacia atrás) que comprobar
							if (indices[posicion-1] < valorMaximoDeIndice) {
								/*
								 * Es incrementable.
								 * La posicion actual y las siguientes (hacia delante)
								 * han de resetearse a valor 0
								 */
								for (int i = posicion; i < indices.length; i++)
									indices[i] = 0;
							}
						}
						//Comprobación realizada, nos vamos a la próxima posición(hacia atrás)
						posicion--;
					}
 
				}
			}
 
			/*
			 * Bucle while que actualiza la tabla de indices ha terminado.
			 * Si tras terminar no ha actualizado ningún indice, es que
			 * ya no quedan combinaciones por hacer
			 */
			if (!actualizacion)
				indicesRecorridos = true;
 
		}
 
	}
 
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil
Val: 15
Ha aumentado su posición en 6 puestos en Java (en relación al último mes)
Gráfica de Java

For anidados dependiendo de una variable

Publicado por Raul (4 intervenciones) el 15/11/2020 17:21:22
Muy buena solución y muy bien explicada. Funciona perfectamente y me ha quedado muy claro.
Muchas gracias.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar