UD02 · Ejercicios
Seis bloques, de menos a más. Haz cada bloque cuando hayas leído su apartado de la teoría, sin esperar a tenerla entera.
Todas las soluciones están plegadas y escritas con la sintaxis de Java 25. Si la tuya es distinta pero funciona y se entiende, es igual de válida: en programación casi nunca hay una única respuesta correcta.
Bloque 1 · Salida por pantalla
Sección titulada «Bloque 1 · Salida por pantalla»1. Ficha personal
Sección titulada «1. Ficha personal»Muestra por pantalla tu nombre, tu dirección y tu teléfono, cada uno en una línea.
Ver solución
void main() { IO.println("Lucía Martín Ruiz"); IO.println("Calle Real, 14 - Martos"); IO.println("600 123 456");}También vale con un bloque de texto, que para varias líneas seguidas queda más limpio:
void main() { IO.println(""" Lucía Martín Ruiz Calle Real, 14 - Martos 600 123 456 """);}2. Diccionario en dos columnas
Sección titulada «2. Diccionario en dos columnas»Muestra diez palabras en inglés con su traducción, en dos columnas alineadas a la izquierda.
Ver solución
void main() { IO.println("%-12s%s".formatted("INGLÉS", "CASTELLANO")); IO.println("%-12s%s".formatted("house", "casa")); IO.println("%-12s%s".formatted("computer", "ordenador")); IO.println("%-12s%s".formatted("keyboard", "teclado")); IO.println("%-12s%s".formatted("screen", "pantalla")); IO.println("%-12s%s".formatted("file", "fichero"));}El \t de la pista funciona, pero descuadra en cuanto una palabra es más larga
que el tabulador. %-12s reserva siempre 12 huecos y por eso las columnas quedan
rectas.
3. Tu horario
Sección titulada «3. Tu horario»Muestra tu horario de clase de la semana en forma de tabla, con los días como columnas.
Ver solución
void main() { IO.println("%-10s%-14s%-14s%-14s".formatted("HORA", "LUNES", "MARTES", "MIÉRCOLES")); IO.println("%-10s%-14s%-14s%-14s".formatted("08:15", "Programación", "Bases Datos", "Programación")); IO.println("%-10s%-14s%-14s%-14s".formatted("09:15", "Sistemas", "Programación", "Entornos")); IO.println("%-10s%-14s%-14s%-14s".formatted("10:15", "Markup", "Sistemas", "Bases Datos"));}Repetir la misma cadena de formato cuatro veces canta un poco. Cuando lleguen los métodos (UD04) y los arrays (UD05) esto se escribirá en tres líneas.
4. Dibujo libre
Sección titulada «4. Dibujo libre»Dibuja algo por pantalla con caracteres: un coche, un gato, una casa. Usa *,
+, <, #, @…
Sobre este ejercicio
No hay solución única, y esa es la gracia. Dos consejos: escríbelo con un bloque
de texto """ en lugar de veinte IO.println, y recuerda que la barra invertida
\ hay que escribirla doble (\\) porque suelta significa otra cosa.
Bloque 2 · Variables, tipos e identificadores
Sección titulada «Bloque 2 · Variables, tipos e identificadores»5. ¿Identificador válido?
Sección titulada «5. ¿Identificador válido?»Di cuáles de estos identificadores son válidos en Java y por qué:
mi variable · num_de_cte · ____programa · $alguna · 3tema · cierto? ·
numeroDeCliente · jose~ · ano · PI · int
Ver solución
| Identificador | ¿Válido? | Motivo |
|---|---|---|
mi variable |
✗ | Lleva un espacio |
num_de_cte |
✓ | El guion bajo está permitido |
____programa |
✓ | Válido, aunque cuatro guiones no aporten nada |
$alguna |
✓ | El $ se permite (se reserva para código generado) |
3tema |
✗ | No puede empezar por un dígito |
cierto? |
✗ | El ? no es un carácter válido |
numeroDeCliente |
✓ | Válido, y además con el convenio correcto |
jose~ |
✗ | La ~ no es válida |
ano |
✓ | Válido… pero ponle anio o curso y evita el malentendido |
PI |
✓ | Válido; por convenio, mayúsculas es una constante |
int |
✗ | Es una palabra reservada del lenguaje |
6. Elige el tipo
Sección titulada «6. Elige el tipo»Declara una variable para cada dato, con el tipo más pequeño que pueda representarlo, y justifica la elección.
- Si un empleado está casado o no.
- Un valor máximo que no se puede modificar: 999999.
- Día de la semana.
- Día del año.
- Sexo, con dos valores posibles:
'V'o'M'. - Milisegundos transcurridos desde el 01/01/1970.
- El total de una factura.
- La población mundial.
Ver solución
void main() { boolean casado = true; // solo cierto o falso final int MAXIMO = 999999; // no cabe en short (máx. 32.767); final porque no cambia byte diaSemana = 1; // de 1 a 7, sobra de sobra short diaAnual = 300; // hasta 366: no cabe en byte, sí en short char sexo = 'M'; // un único carácter long milisegundos = 1298332800000L; // desborda int: hace falta long y sufijo L double totalFactura = 10350.678; // decimales long poblacion = 6775235741L; // más de 2.147 millones: no cabe en int
IO.println("Casado: " + casado); IO.println("Máximo: " + MAXIMO); IO.println("Total factura: %.2f €".formatted(totalFactura));}Las dos decisiones que importan: cuándo se sale de int (milisegundos y
población desbordan) y cuándo hace falta final (el máximo no debe cambiar).
En un programa real usarías int para el día de la semana y del año sin
pensarlo: ahorrar tres bytes no compensa la letra pequeña. La pregunta tiene
sentido cuando hablamos de millones de datos.
7. Encuentra los errores
Sección titulada «7. Encuentra los errores»Este programa tiene seis errores. Encuéntralos y corrígelo.
void main() { int x = 7 int y = 5; float f1 = 13.5; String nombre = 'Carlos'; IO.println("El valor de x es ", x); IO.println("La división es " + x / y); IO.println("¿Iguales? " + nombre == "Carlos");}Ver solución
int x = 7— falta el punto y coma.float f1 = 13.5;—13.5es undouble; para unfloathace falta13.5f.String nombre = 'Carlos';— las comillas simples son parachar; una cadena va con dobles.IO.println("El valor de x es ", x);— no se separan con coma, se concatena con+.x / ycon dos enteros da1, no1.4. Si querías el decimal, fuerza la conversión.nombre == "Carlos"compara referencias, no contenido. Y encima, por precedencia, se evalúa antes la concatenación: hay que usarnombre.equals("Carlos")entre paréntesis.
void main() { int x = 7; int y = 5; float f1 = 13.5f; String nombre = "Carlos";
IO.println("El valor de x es " + x); IO.println("La división entera es " + (x / y)); IO.println("La división real es " + ((double) x / y)); IO.println("¿Iguales? " + nombre.equals("Carlos"));}Bloque 3 · Operadores y conversiones
Sección titulada «Bloque 3 · Operadores y conversiones»8. Operaciones básicas
Sección titulada «8. Operaciones básicas»Declara dos variables enteras con los valores 144 y 999. Muestra su suma, resta, multiplicación, división entera y resto.
Ver solución
void main() { int x = 144; int y = 999;
IO.println("x = " + x + ", y = " + y); IO.println("Suma: " + (x + y)); IO.println("Resta: " + (x - y)); IO.println("Producto: " + (x * y)); IO.println("División entera: " + (x / y)); // 0 IO.println("Resto: " + (x % y)); // 144 IO.println("División real: " + ((double) x / y)); // 0.1441...}Fíjate en que 144 / 999 da 0, no 0,14. Los paréntesis en las
concatenaciones tampoco son opcionales: sin ellos, "Suma: " + x + y escribiría
Suma: 144999.
9. Total de una factura
Sección titulada «9. Total de una factura»Pide la base imponible y muestra el IVA (21 %) y el total, con dos decimales.
Ver solución
void main() { final double IVA = 0.21;
double base = Double.parseDouble(IO.readln("Base imponible: ")); double cuota = base * IVA; double total = base + cuota;
IO.println("Base: %8.2f €".formatted(base)); IO.println("IVA: %8.2f €".formatted(cuota)); IO.println("TOTAL: %8.2f €".formatted(total));}10. De segundos a horas
Sección titulada «10. De segundos a horas»Pide una cantidad de segundos y muéstrala como horas, minutos y segundos. Por
ejemplo, 3725 → 1 h 2 min 5 s.
Ver solución
void main() { int total = Integer.parseInt(IO.readln("Segundos: "));
int horas = total / 3600; int minutos = (total % 3600) / 60; int segundos = total % 60;
IO.println(horas + " h " + minutos + " min " + segundos + " s");}Este es el ejercicio que enseña para qué sirven de verdad la división entera y el módulo: uno te da los grupos completos y el otro, lo que sobra.
11. Primera y última cifra
Sección titulada «11. Primera y última cifra»Pide un número entero de hasta cinco cifras y muestra su última cifra y su primera cifra.
Ver solución
void main() { int numero = Integer.parseInt(IO.readln("Número (hasta 5 cifras): "));
int ultima = numero % 10;
int primera = numero; while (primera >= 10) { primera = primera / 10; }
IO.println("Última cifra: " + ultima); IO.println("Primera cifra: " + primera);}La última sale con un módulo. La primera, dividiendo entre 10 hasta que solo queda una cifra — y ese bucle es el mismo truco que necesitarás para contar dígitos o detectar capicúas.
Bloque 4 · Entrada de datos
Sección titulada «Bloque 4 · Entrada de datos»12. Calculadora
Sección titulada «12. Calculadora»Pide dos números y muestra su suma, resta, producto, división, la potencia del primero elevado al segundo, y la raíz cuadrada del primero.
Ver solución
void main() { double x = Double.parseDouble(IO.readln("Primer número: ")); double y = Double.parseDouble(IO.readln("Segundo número: "));
IO.println("x + y = " + (x + y)); IO.println("x - y = " + (x - y)); IO.println("x * y = " + (x * y)); IO.println("x / y = " + (x / y)); IO.println("x ^ y = " + Math.pow(x, y)); IO.println("√x = " + Math.sqrt(x));}Math trae hechas las operaciones matemáticas habituales: pow, sqrt, abs,
round, max, min, random. No reinventes ninguna.
13. Rectángulo
Sección titulada «13. Rectángulo»Pide la base y la altura de un rectángulo y calcula su área y su perímetro.
Ver solución
void main() { double base = Double.parseDouble(IO.readln("Base: ")); double altura = Double.parseDouble(IO.readln("Altura: "));
IO.println("Área: %.2f".formatted(base * altura)); IO.println("Perímetro: %.2f".formatted(2 * (base + altura)));}14. Hasta medianoche
Sección titulada «14. Hasta medianoche»Pide una hora (horas y minutos) y calcula cuántos segundos faltan para medianoche.
Ver solución
void main() { int horas = Integer.parseInt(IO.readln("Hora (0-23): ")); int minutos = Integer.parseInt(IO.readln("Minutos (0-59): "));
int segundosTranscurridos = horas * 3600 + minutos * 60; int segundosDelDia = 24 * 3600;
IO.println("Faltan " + (segundosDelDia - segundosTranscurridos) + " segundos");}15. Ecuación de primer grado
Sección titulada «15. Ecuación de primer grado»Resuelve ax + b = 0 pidiendo a y b por teclado. Cuidado con el caso en que
a valga 0.
Ver solución
void main() { double a = Double.parseDouble(IO.readln("Coeficiente a: ")); double b = Double.parseDouble(IO.readln("Coeficiente b: "));
if (a == 0 && b == 0) { IO.println("Cualquier valor de x es solución"); } else if (a == 0) { IO.println("La ecuación no tiene solución"); } else { IO.println("x = " + (-b / a)); }}Si divides sin comprobar que a no es cero, con double no obtienes un error:
obtienes Infinity o NaN, que es peor, porque el programa sigue como si nada.
Bloque 5 · Selección
Sección titulada «Bloque 5 · Selección»16. El mayor de dos
Sección titulada «16. El mayor de dos»Pide dos números y di cuál es mayor, usando el operador ternario.
Ver solución
void main() { int a = Integer.parseInt(IO.readln("Primer número: ")); int b = Integer.parseInt(IO.readln("Segundo número: "));
int mayor = (a > b) ? a : b; IO.println("El mayor es " + mayor);}Si son iguales, este código dice que el mayor es b. ¿Es aceptable? Depende del
enunciado — y esa es justo la clase de pregunta que hay que hacer en la fase de
análisis.
17. Buenos días
Sección titulada «17. Buenos días»Pide una hora (solo la hora, sin minutos) y saluda: buenos días de 6 a 12, buenas tardes de 13 a 20, y buenas noches de 21 a 5.
Ver solución
void main() { int hora = Integer.parseInt(IO.readln("¿Qué hora es? (0-23) "));
if (hora < 0 || hora > 23) { IO.println("Esa hora no existe"); } else if (hora >= 6 && hora <= 12) { IO.println("Buenos días"); } else if (hora >= 13 && hora <= 20) { IO.println("Buenas tardes"); } else { IO.println("Buenas noches"); }}El tramo de noche es el interesante: va de 21 a 5 pasando por medianoche, así que
no se puede escribir como un intervalo normal. Al dejarlo en el else final, el
problema desaparece.
18. Nota del boletín
Sección titulada «18. Nota del boletín»Pide una nota del 0 al 10 y muestra la calificación: insuficiente, suficiente, bien, notable o sobresaliente.
Ver solución
void main() { double nota = Double.parseDouble(IO.readln("Nota (0-10): "));
String calificacion;
if (nota < 0 || nota > 10) { calificacion = "Nota no válida"; } else if (nota < 5) { calificacion = "Insuficiente"; } else if (nota < 6) { calificacion = "Suficiente"; } else if (nota < 7) { calificacion = "Bien"; } else if (nota < 9) { calificacion = "Notable"; } else { calificacion = "Sobresaliente"; }
IO.println(calificacion);}Aquí el switch no sirve: no comparamos con valores sueltos, sino con
intervalos. Ese es el criterio para elegir entre uno y otro.
19. Descuentos de la tienda
Sección titulada «19. Descuentos de la tienda»Pide el importe de una compra y aplica el descuento correspondiente: menos de 200 €, ninguno; de 200 a 500, un 5 %; de 501 a 1000, un 10 %; más de 1000, un 15 %. Muestra el descuento aplicado y el total.
Ver solución
void main() { double importe = Double.parseDouble(IO.readln("Importe de la compra: "));
double descuento;
if (importe < 200) { descuento = 0; } else if (importe <= 500) { descuento = 0.05; } else if (importe <= 1000) { descuento = 0.10; } else { descuento = 0.15; }
double rebaja = importe * descuento;
IO.println("Descuento: %.0f%% (%.2f €)".formatted(descuento * 100, rebaja)); IO.println("Total a pagar: %.2f €".formatted(importe - rebaja));}Fíjate en el enunciado: dice «de 501 a 1000», pero ¿y una compra de 500,40 €? El
enunciado se ha escrito pensando en euros enteros. Usando <= en cascada, ese
hueco desaparece.
Para escribir un % literal en una cadena con formato hay que doblarlo: %%.
20. Año bisiesto
Sección titulada «20. Año bisiesto»Pide un año y di si es bisiesto. Un año es bisiesto si es divisible entre 4, salvo que sea divisible entre 100 y no entre 400.
Ver solución
void main() { int anio = Integer.parseInt(IO.readln("Año: "));
boolean bisiesto = (anio % 4 == 0 && anio % 100 != 0) || (anio % 400 == 0);
IO.println(anio + (bisiesto ? " es bisiesto" : " no es bisiesto"));}Toda la regla cabe en una expresión booleana. Pruébalo con 2024 (sí), 1900 (no) y 2000 (sí): esos tres casos son los que distinguen una solución correcta de una que solo mira el múltiplo de 4.
21. Día de la semana
Sección titulada «21. Día de la semana»Pide un número del 1 al 7 y muestra el nombre del día correspondiente. Usa
switch.
Ver solución
void main() { int dia = Integer.parseInt(IO.readln("Día (1-7): "));
String nombre = switch (dia) { case 1 -> "Lunes"; case 2 -> "Martes"; case 3 -> "Miércoles"; case 4 -> "Jueves"; case 5 -> "Viernes"; case 6 -> "Sábado"; case 7 -> "Domingo"; default -> "Día no válido"; };
IO.println(nombre);}22. Ecuación de segundo grado
Sección titulada «22. Ecuación de segundo grado»Resuelve ax² + bx + c = 0. Contempla los tres casos según el discriminante:
dos soluciones, una o ninguna real.
Ver solución
void main() { double a = Double.parseDouble(IO.readln("Coeficiente a: ")); double b = Double.parseDouble(IO.readln("Coeficiente b: ")); double c = Double.parseDouble(IO.readln("Coeficiente c: "));
if (a == 0) { IO.println("No es una ecuación de segundo grado"); return; }
double discriminante = b * b - 4 * a * c;
if (discriminante > 0) { double x1 = (-b + Math.sqrt(discriminante)) / (2 * a); double x2 = (-b - Math.sqrt(discriminante)) / (2 * a); IO.println("Dos soluciones: x1 = %.4f, x2 = %.4f".formatted(x1, x2)); } else if (discriminante == 0) { IO.println("Una solución: x = %.4f".formatted(-b / (2 * a))); } else { IO.println("No tiene soluciones reales"); }}return dentro de main termina el programa ahí mismo. Es la forma más limpia
de salir cuando los datos no son válidos y no tiene sentido seguir.
Bloque 6 · Repetición
Sección titulada «Bloque 6 · Repetición»23. Cuenta atrás, tres veces
Sección titulada «23. Cuenta atrás, tres veces»Muestra los números del 320 al 160, de 20 en 20 hacia atrás. Hazlo tres veces:
con for, con while y con do-while.
Ver solución
void main() { IO.println("Con for:"); for (int i = 320; i >= 160; i -= 20) { IO.print(i + " "); } IO.println();
IO.println("Con while:"); int j = 320; while (j >= 160) { IO.print(j + " "); j -= 20; } IO.println();
IO.println("Con do-while:"); int k = 320; do { IO.print(k + " "); k -= 20; } while (k >= 160); IO.println();}Los tres hacen lo mismo. La diferencia está en dónde vive el contador: el for
lo tiene todo junto en una línea, y por eso es el que menos se olvida de
actualizar.
24. La caja fuerte
Sección titulada «24. La caja fuerte»La combinación es un número de cuatro cifras. Pídela hasta cuatro veces. Si acierta, «La caja fuerte se ha abierto satisfactoriamente»; si agota los intentos, avísale de que se ha bloqueado.
Ver solución
void main() { final String COMBINACION = "2468"; final int INTENTOS = 4;
boolean abierta = false; int intento = 0;
while (intento < INTENTOS && !abierta) { String clave = IO.readln("Combinación: ");
if (clave.equals(COMBINACION)) { abierta = true; } else { intento++; IO.println("Lo siento, esa no es la combinación. Te quedan " + (INTENTOS - intento) + " intentos."); } }
if (abierta) { IO.println("La caja fuerte se ha abierto satisfactoriamente"); } else { IO.println("Caja bloqueada"); }}Con la variable abierta en la condición, el bucle termina solo y no hacen falta
break. Es más largo de escribir y mucho más fácil de seguir.
25. Media hasta que quieras
Sección titulada «25. Media hasta que quieras»Pide números positivos y calcula su media. El usuario termina metiendo un número negativo, que no cuenta.
Ver solución
void main() { double suma = 0; int cantidad = 0;
double numero = Double.parseDouble(IO.readln("Número (negativo para terminar): "));
while (numero >= 0) { suma += numero; cantidad++; numero = Double.parseDouble(IO.readln("Número (negativo para terminar): ")); }
if (cantidad == 0) { IO.println("No has introducido ningún número"); } else { IO.println("Has introducido %d números. Media: %.2f".formatted(cantidad, suma / cantidad)); }}Dos cosas que suspenden este ejercicio: contar el número negativo dentro de la media, y dividir entre cero cuando el usuario sale a la primera.
26. Factorial
Sección titulada «26. Factorial»Pide un número entero positivo y calcula su factorial. Recuerda que
5! = 5 × 4 × 3 × 2 × 1.
Ver solución
void main() { int n = Integer.parseInt(IO.readln("Número: "));
if (n < 0) { IO.println("El factorial no está definido para negativos"); return; }
long factorial = 1;
for (int i = 2; i <= n; i++) { factorial *= i; }
IO.println(n + "! = " + factorial);}long y no int: el factorial crece disparado y a partir de 13 ya no cabe en un
int. Pruébalo con 20 y con 21, y verás que ni siquiera long aguanta mucho.
27. ¿Es primo?
Sección titulada «27. ¿Es primo?»Pide un número y di si es primo.
Ver solución
void main() { int n = Integer.parseInt(IO.readln("Número: "));
boolean primo = n > 1;
for (int divisor = 2; divisor <= Math.sqrt(n); divisor++) { if (n % divisor == 0) { primo = false; break; } }
IO.println(n + (primo ? " es primo" : " no es primo"));}No hace falta probar todos los divisores hasta n: si un número tiene un divisor
mayor que su raíz cuadrada, necesariamente tiene otro menor, que ya habríamos
encontrado. Con 1.000.000 la diferencia es de un millón de vueltas a mil.
28. Fibonacci
Sección titulada «28. Fibonacci»Pide un número n y muestra los n primeros términos de la serie de Fibonacci:
0, 1, 1, 2, 3, 5, 8, 13…
Ver solución
void main() { int n = Integer.parseInt(IO.readln("¿Cuántos términos? "));
long anterior = 0; long actual = 1;
for (int i = 1; i <= n; i++) { IO.print(anterior + " ");
long siguiente = anterior + actual; anterior = actual; actual = siguiente; }
IO.println();}La clave es la variable siguiente: sin ella, al asignar anterior = actual
pierdes el valor que necesitabas justo después.
29. Pirámide a medida
Sección titulada «29. Pirámide a medida»Pide la altura y el carácter, y dibuja una pirámide rellena.
Ver solución
void main() { int altura = Integer.parseInt(IO.readln("Altura: ")); String simbolo = IO.readln("Carácter: ");
for (int fila = 1; fila <= altura; fila++) { for (int espacio = 1; espacio <= altura - fila; espacio++) { IO.print(" "); } for (int i = 1; i <= 2 * fila - 1; i++) { IO.print(simbolo); } IO.println(); }}Dos bucles anidados dentro del principal: uno pinta los espacios que centran la
figura y otro los símbolos. La fórmula 2 * fila - 1 da la serie 1, 3, 5, 7…,
que es lo que hace que quede triangular.
30. Capicúa
Sección titulada «30. Capicúa»Pide un número de cinco cifras y di si es capicúa (se lee igual del derecho que del revés).
Ver solución
void main() { int numero = Integer.parseInt(IO.readln("Número: "));
int original = numero; int alReves = 0;
while (numero > 0) { alReves = alReves * 10 + numero % 10; numero /= 10; }
IO.println(original + (original == alReves ? " es capicúa" : " no es capicúa"));}Le vamos quitando la última cifra al número (% 10) y construyendo el número al
revés (* 10 +). Después basta comparar. Guarda el valor original antes del
bucle: al terminar, numero vale 0.
31. Menú que no se acaba
Sección titulada «31. Menú que no se acaba»Escribe un menú con cuatro opciones (vender, consultar, administrar, salir) que se repita hasta que el usuario elija salir. Si mete una opción que no existe, avisa y vuelve a mostrarlo.
Ver solución
void main() { int opcion;
do { IO.println("""
=== AUDITORIO DE MARTOS === 1. Vender entradas 2. Consultar evento 3. Administración 4. Salir """);
opcion = Integer.parseInt(IO.readln("Elige una opción: "));
switch (opcion) { case 1 -> IO.println("Vendiendo entradas…"); case 2 -> IO.println("Consultando evento…"); case 3 -> IO.println("Entrando en administración…"); case 4 -> IO.println("Hasta luego"); default -> IO.println("Esa opción no existe"); } } while (opcion != 4);}Este ejercicio es el esqueleto de la práctica de la unidad: si lo tienes claro,
la práctica es ir rellenando cada case.
© 2026 Carlos Barroso · Contenido bajo CC BY-NC-SA 4.0

