Java - programa para ver si las campañas del instituto son viables o no

 
Vista:

programa para ver si las campañas del instituto son viables o no

Publicado por Rodrigo (1 intervención) el 14/11/2018 11:47:21
Hola, llevo tiempo intentando realizar este ejercicio en Netbeans, en java, pero no consigo hacerlo al 100%, podría ayudarme alguien? Gracias

"En un colegio han empezado regalando un bombón por cada cinco envoltorios. Eso significa que si compramos en la cafetería 25 bombones, en realidad tendremos 5 bombones más gracias a esos 25 envoltorios. Y además después de habernos comido esos 5 últimos nos regalarán uno más, de forma que en total nos hemos comido 31 bombones y nos ha sobrado un envoltorio, que ya no podemos canjear. Si la estrategia funciona, el instituto se plantea realizar otras campañas.

Realizar un programa para ver si las campañas del instituto son viables o no. El programa solicitará al jefe de estudios que introduzca tres datos:

-Número de envoltorios necesarios para que nos regalen más bombones
-Número de bombones a regalar en función del número anterior
-Número de bombones que se han comprado en la cafetería.

Para cada entrada de datos, se generará un mensaje por consola indicando si la campaña es inviable o si es viable, en tal caso se mostrará el total de bombones que se come el/la alumno/a y el número de envoltorios que le sobran y no puede canjear. Se considera que una campaña es inviable si se regalan bombones de forma indefinida. El programa se repetirá hasta que el jefe de estudios decida terminar."
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
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

programa para ver si las campañas del instituto son viables o no

Publicado por Kabuto (1381 intervenciones) el 15/11/2018 01:45:57
Hola,
al principio no me quedaba claro lo que había que hacer, pero creo ya lo he pillado y dado con una solución.

Aquí el problema reside en que, según las condiciones que pongamos para obtener bombones regalo, es posible que sigamos obteniendo bombones suficientes para más regalo un número indeterminado de veces.

Y ese el problema --> un número indeterminado de veces no hay forma de saber cuantas veces vamos a tener que estar calculando cuantos bombones de regalo va a obtener.

En situaciones de este tipo, suele ser buena idea elaborar un método "recursivo", es decir, un método que se llama a sí mismo para seguir repitiendo cálculos con los datos obtenidos de la llamada anterior, hasta llegar a una conclusión.

Y bién, eso es lo que he hecho, un método recursivo que en cada iteración calcula los bombones extra que obtiene el alumno.

La primera vez que se ejecuta, estos "bombones extra" los calcula a partir de los bombones que ha comprado el alumno.
Si obtiene menos bombones extra de los necesarios para poder seguir canjeando, entonces es que la campaña es viable y el metodo devuelve el valor TRUE.
En caso contrario, es decir, ha obtenido suficientes "bombones extra" como para seguir canjeando por más bombones, entonces hacemos una llamada recursiva, volviendole a pasar los datos para que vuelva a hacer los cálculos, solo que esta vez los hará a partir de estos "bombones extra" que ha conseguido.

Las llamadas recursivas se irán repitiendo hasta que deje de obtener bombones extra y entonces se considera viable.

El método incluye otro parámetro que acumula los bombones que consigue comer el alumno, ya que se pide que informemos en pantalla de este dato si la campaña resulta viable. Así que este parámetro irá sumando todos los bombones extra que consiga, más los que haya comprado inicialmente.

Puede ocurrir, si ponemos condiciones poco "inteligentes" que el alumno reciba montones de bombones extra tras cada canje y entonces las llamadas recursivas podrían ser muy numerosas, incluso infinitas.
Para controlar esto, he puesto un parámetro en el método que hace de contador de iteraciones. He puesto el tope en 1000, es decir, si se alcanzan 1000 llamadas recursivas, significa que se están regalando miles de bombones y por lo tanto la campaña no es viable, así que cuando se alcanzan las 1000 iteraciones, el método devuelve FALSE.

Al hacer pruebas de este método, creo que el tope de 1000 llamadas recurisvas me ha quedado demasiado alto, pues varias veces me ha ocurrido que el programa petaba al producirse la excepción Stack Overflow (desbordamiento de pila), es decir, se acumulaban más bombones de los que el sistema puede contar....
En lugar de reducir este tope, lo que he hecho ha sido manejar esa excepción con un try catch cuando llamo al método en el main()
Así que en realidad, hay dos posibles condiciones para las que podemos considerar la campaña como NO VIABLE:
1 - El método recursivo se llama así mismo 1000 veces.
2 - La pila de datos se ha desbordado ante la gran cantidad de bombones contabilizados.

El método parece funcionar bien y cumplir con su cometido. No me gusta crear métodos que necesiten tantos parámetros (5 en este caso), pero no he sabido simplificarlo más.

En fin te pongo aquí el código. También te lo adjunto en un archivo zip para descargar directamente.
Tiene montones de lineas de comentarios, dando todas las explicaciones necesarias.
Aún así, no dudes en preguntar cualquier duda que tengas.
La recursividad puede resultar difícil de comprender, incluso para mí, no vayas a pensar que lo he resuelto fácilmente a la primera, sin haberme dejado unas cuantas neuronas fritas xDDD

Un saludo.

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//https://www.lawebdelprogramador.com/foros/Java/1675047-programa-para-ver-si-las-campanas-del-instituto-son-viables-o-no.html
package bombones;
 
import java.util.Scanner;
 
public final class Test {
 
	/**
	 * Método recursivo que comprueba si la campaña de bombones regalo es viable.<br>
	 * En cada iteracion del método, este calcula los bombones extra que obtiene el alumno
	 * según las condiciones de la campaña.<br>Si los bombones extra calculados son inferiores
	 * al numero de envoltorios necesarios para obtener un regalo, la campaña se considera <b>VIABLE</b>
	 * y se informa por pantalla del total de bombones que ha conseguido comer el alumno y cuantos envoltorios
	 * no canjeables le han sobrado.<br>En cambio, si los bombones extra calculados igualan o superan al número de
	 * envoltorios necesarios para canjear, significa que aún no sabemos si la campaña es viable y entonces se hará
	 * una llamada recursiva a este método pasándole los parámetros actualizados tras los cálculos realizados.<br>
	 * Este método lleva la cuenta de cuantas llamadas recursivas se ha realizado, en caso de llegar a las 1000 llamadas
	 * se considera que la campaña <b>NO ES VIABLE</b> ya que el alumno habría obtenido miles de bombones gratuitos y 
	 * parece que aún seguiría obteniendo muchos más.<br>
	 * <b><u>--MUY IMPORTANTE--</u></b> A pesar de llevar un control de iteraciones, es muy probable que ocurra una 
	 * excepción por <i>desbordamiento de pila</i>(StackOverflowError) según las condiciones de la campaña ya que se pueden
	 * acumular más bombones de los que son posibles contar.<br>Debido a esto se hace necesario controlar esta excepcion
	 * cuando se llame a este método.<br>Obviamente, si ocurre esta excepción, habrá que considerar la campaña <b>NO VIABLE</b>
	 * @param envol Número de envoltorios necesarios para obtener más bombones.
	 * @param bombRegalo Número de bombones que se regalan en cada canje de envoltorios.
	 * @param bombComprados Este parámetro representará dos valores distintos:<br>
	 * <ul><li>La primera vez que llamamos al método, representa los bombones que ha comprado el alumno</li>
	 * <li>Las siguientes veces que este metodo sea llamado recursivamente, este parámetro representa los "bombones
	 * extra" que se han conseguido con el último canje de envoltorios.</li></ul>
	 * @param bombComidos Número de bombones totales que ha conseguido comer el alumno gracias a la campaña
	 * @param iteraciones Número de veces que este método se ha llamado así mismo recursivamente.
	 * @return <b>true</b> si la campaña se considera viable, <b>false</b> en caso contrario.
	 */
	static boolean esViable(int envol, int bombRegalo, int bombComprados, int bombComidos, int iteraciones) {
 
		bombComidos += bombComprados;//La primera iteracion, el alumno come los que ha comprado.
		                             //En siguientes iteraciones, se irán sumando los bombones extra que pueda conseguir
 
		if (iteraciones == 1000)
			return false;//Tras mil llamada recursivas, podemos deducir que la campaña es un fracaso...
		else
		{
			int bombonesExtra = bombComprados / envol * bombRegalo;//Calculamos los bombones extra que consigue según condiciones
 
			if (bombonesExtra < envol)//En algun momento el alumno obtiene bombones insuficientes para seguir teniendo premio.
			{
				System.out.printf("\n\nEl alumno comería %d bombones en total.", (bombComidos+bombonesExtra));
				System.out.println("\nEnvoltorios sobrantes no canjeables: " + bombonesExtra);
				return true; //CAMPAÑA VIABLE
			}
			else //De momento, el alumno sigue obteniendo bombones suficientes para seguir canjeando..
				return esViable(envol, bombRegalo, bombonesExtra, bombComidos, iteraciones++);
		}
	}
 
	public static void main(String[] args) {
		Scanner teclado = new Scanner(System.in);
		int envoltorios = 0;
		int bombonesRegalo = 0;
		int bombonesComprados = 0;
		char continuar = 's';
 
		while(continuar == 's')
		{
			System.out.print("\nNumero de envoltorios necesarios para regalar mas bombones: ");
			envoltorios = Integer.parseInt(teclado.nextLine());
			System.out.print("Numero de bombones a regalar: ");
			bombonesRegalo = Integer.parseInt(teclado.nextLine());
			System.out.print("Numero de bombones comprados: ");
			bombonesComprados = Integer.parseInt(teclado.nextLine());
 
			/*
			 * El metodo recursivo esViable() es muy susceptible de provocar "desbordamiento de pila" si ponemos
			 * unas condiciones de campaña demasiado "generosas", ya que las continuas llamadas recursivas
			 * acumularán más bombones de los que el sistema puede contar.
			 * Se puede comprobar con los valores:
			 * Numero de envoltorios necesarios para regalar mas bombones: 1
			 * Numero de bombones a regalar: 1
			 * Numero de bombones comprados: 10
			 * Para controlar esta excepcion usamos try catch.
			 * En caso de ocurrir dicha excepcion, la campaña ha de ser considera NO VIABLE, pues semejante número de
			 * bombones de regalo serían la ruina del colegio, y probablemente la muerte del alumno por indigestion.
			 */
			try {
				System.out.println(esViable(envoltorios, bombonesRegalo, bombonesComprados, 0, 0)?"\nCAMPAÑA VIABLE":"\nCAMPAÑA NO VIABLE");
			} catch (StackOverflowError e) {
				System.out.println("\nCAMPAÑA NO VIABLE");
			}
 
			System.out.print("\n¿Desea continuar(s/n): ");
			continuar = teclado.nextLine().toLowerCase().charAt(0);
		}
		System.out.println("\n\tFIN DE PROGRAMA");
		teclado.close();
	}
 
}
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