138 ejercicios de Java de los módulos de Entornos de Desarrollo, Programación, Acceso a Datos, Desarrollo de Interfaces, Programación Multimedia y Dispositivos Móviles, Programación de Servicios y Procesos. Desde los primeros programas con bucles, arrays y cadenas hasta clases, herencia, colecciones, ficheros, pruebas, acceso a datos e hilos.
Cada ejercicio trae enunciado, pistas y pruebas automáticas: escribes el código aquí mismo, lo ejecutas y ves al momento si es correcto. Tu progreso se guarda en el tema del que sale cada ejercicio.
Gráfico de trabajo pendiente (burndown) de un sprint
Difícil
En Scrum, el burndown muestra cada día cuántos puntos de historia quedan por terminar. La entrada es la duración del sprint en días y, después, cada historia con su identificador, sus puntos y el día en que se terminó (0 si no se terminó). Muestra la cabecera …
Planificación con dependencias y camino crítico
Muy difícil
Para planificar un proyecto se descompone en tareas con su duración y las tareas que deben terminar antes (como en un diagrama de Gantt o PERT). Cada línea de la entrada es «ID duración» y, opcionalmente, la lista de tareas previas separadas por comas. Si una …
El método resumen debería calcular la media (con decimales), cuántas notas son aprobados (5 o más), la nota máxima y la mínima de un grupo de notas enteras de 0 a 10. Compila y parece funcionar, pero tiene cuatro errores. Usa el depurador de tu IDE (pon un pun…
Depura una búsqueda binaria
Muy difícil
primeraMayorOIgual debe devolver la primera posición de un array ordenado cuyo valor es mayor o igual que x, o a.length si todos son menores (es el «lower bound» que usan Arrays.binarySearch y las bases de datos en sus índices). Con ella, contar calcula cuánta…
Entornos · Diseño y realización de pruebas ver el tema
Valores límite: casos que detectan errores
Difícil
La técnica de valores límite dice que los errores se esconden en las fronteras entre clases de equivalencia. El método tarifa ya está bien hecho; tu trabajo es escribir en CASOS las pruebas, cada una con un peso y la tarifa esperada. El programa comprueba que …
Matar mutantes con varias condiciones
Muy difícil
El precio de la entrada de un museo depende de la edad, de si se es socio y de si es fin de semana (las reglas están en el comentario de ORIGINAL). Escribe en CASOS las pruebas necesarias, cada una con la edad, si es socio (1/0), si es fin de semana (1/0) y el…
Entornos · Optimización y Documentación ver el tema
Un analizador de código en miniatura
Difícil
Herramientas como Checkstyle o PMD leen el código fuente y avisan de los «malos olores». Implementa analizar con cuatro reglas, recorriendo las líneas en orden. Detecta la cabecera de un método con la expresión regular METODO (el grupo 2 es el nombre y el 3, l…
Un Git en miniatura: base de fusión
Muy difícil
En Git, cada commit apunta a sus padres (uno normalmente, dos si es una fusión) y una rama es solo un nombre que apunta a un commit. Para fusionar, Git busca la base de fusión: el antepasado común más reciente de los dos commits. Implementa antepasados (el pro…
Entornos · Pruebas con JUnit y Mockito ver el tema
Dobles de prueba escritos a mano
Difícil
Para probar ServicioPedidos sin una base de datos ni un servidor de correo reales se usan dobles de prueba: objetos que implementan las mismas interfaces. Completa InventarioFalso, cuyo constructor recibe el stock que devolverá stock() para cualquier producto …
Tu propio JUnit con reflexión
Muy difícil
¿Cómo encuentra JUnit los métodos de prueba? Con reflexión: inspecciona la clase en tiempo de ejecución y busca los métodos con la anotación @Test. Implementa ejecutar: localiza los métodos anotados con @Prueba y @Antes de la clase, ordena las pruebas por nomb…
El comentario de la clase describe el diagrama de estados de un pedido: sus estados, los eventos que provocan cada transición y las acciones asociadas. Implementa aplicar para que, según el estado actual y el evento, cambie de estado y devuelva el nuevo estado…
Ingeniería inversa: de las clases al diagrama
Muy difícil
Herramientas como IntelliJ o PlantUML pueden generar el diagrama de clases a partir del código. Hazlo tú con reflexión: para cada clase de la lista, en orden, escribe su bloque de PlantUML («interface X {», «abstract class X {» o «class X {»). Dentro, los atri…
Entornos · Ejercicios de Entornos de Desarrollo ver el tema
Depura el programa de notas
Fácil
Este programa lee N notas y debe mostrar su media con dos decimales y la nota máxima, pero tiene tres errores. Usa el depurador (o trazas) para encontrarlos y corrígelos sin reescribir el programa. Entrada: N y después las N notas.
Valores límite: clasificar edades
Fácil
Implementa clasificar(edad) según esta especificación: edad < 0 o > 120 → "Error"; 0–11 → "Niño"; 12–17 → "Adolescente"; 18–64 → "Adulto"; 65–120 → "Jubilado". Los tests usan justo los valores límite de cada clase de equivalencia, que es donde suelen esconders…
Caja negra: el problema del triángulo
Medio
Clásico de las pruebas de caja negra. Implementa tipo(a, b, c), que recibe las longitudes de tres lados enteros y devuelve "Equilátero", "Isósceles", "Escaleno" o "No es triángulo" (si algún lado es ≤ 0 o si un lado es mayor o igual que la suma de los otros do…
Refactoriza: extraer método
Medio
El cálculo original del precio estaba en un único bloque lleno de números mágicos: p = base * unidades; si VIP p -= 15 %; si SOCIO p -= 5 %; si unidades >= 10 p -= 10 %; p += 21 % de IVA. Ya se ha extraído la estructura en métodos pequeños. Completa descuentoC…
Del diagrama de clases al código
Medio
Implementa el diagrama de clases: la clase abstracta Figura (nombre, area() abstracto y toString() ya hechos) y sus subclases Circulo (radio) y Rectangulo (base, altura), que heredan de ella. El programa lee figuras (C radio o R base altura), las muestra y sum…
Programación · Fundamentos de la Programación ver el tema
Del pseudocódigo a Java
Fácil
Traduce a Java este pseudocódigo: Leer n Si n = 0 entonces Escribir «cero» Si no Si n > 0 entonces signo ← «positivo» si no signo ← «negativo» Si n mod 2 = 0 entonces paridad ← «par» si no paridad ← «impar» Escribir signo, « », paridad Fin si Por ejemplo, para…
Traza del algoritmo de Euclides
Medio
El algoritmo de Euclides, de hace más de 2000 años, calcula el máximo común divisor de dos números: mientras b no sea 0, se divide a entre b, a pasa a valer b y b pasa a valer el resto. Lee a y b (enteros positivos) y muestra la traza: en cada paso, «Paso k: a…
Conversor de bases sin atajos
Difícil
Los ordenadores trabajan en binario y los programadores leemos a menudo hexadecimal (colores #FF8800, direcciones de memoria). Implementa aBase(n, base), que convierte un entero no negativo a cualquier base de 2 a 16 sin usar Integer.toBinaryString ni similare…
Simula una máquina con su propio ensamblador
Muy difícil
Un procesador repite sin parar el ciclo de captación y ejecución: lee la instrucción a la que apunta el contador de programa (PC), la ejecuta y pasa a la siguiente (o salta). Simula una máquina con un acumulador, 16 posiciones de memoria (a 0) y estas instrucc…
Lee un número de segundos y desglósalo en días, horas, minutos y segundos usando la división entera (/) y el resto (%). Muestra «N s = d d h h m min s s» y después «Formato reloj: hh:mm:ss (+d días)» («+1 día» en singular) con dos cifras en horas, minutos y se…
Las trampas de los tipos numéricos
Medio
Los tipos de Java tienen límites y reglas que causan errores muy habituales. Lee dos enteros a y b (b distinto de 0) y muestra, en este orden: «int: a * b = r» calculado con int (puede desbordarse); «long: a * b = r» convirtiendo antes a long; «división entera…
La cuota de un préstamo
Difícil
Lee el capital de un préstamo, el interés anual en % y los años. La cuota mensual (sistema francés) es C · i / (1 − (1 + i)^−n), con i el interés mensual (anual / 100 / 12) y n el número de meses; si el interés es 0, la cuota es C / n. Muestra «Cuota mensual: …
Permisos de Unix con operadores de bits
Muy difícil
Los permisos de un fichero en Linux son 9 bits: lectura, escritura y ejecución (r = 4, w = 2, x = 1) para el usuario (bits 8-6), el grupo (5-3) y los demás (2-0); por eso se escriben en octal, como 754. La entrada empieza con los permisos en octal y sigue con …
Programación · Estructuras Condicionales ver el tema
Calificación a partir de la nota
Fácil
Lee una nota entera por teclado y muestra su calificación: Suspenso (0-4), Aprobado (5), Bien (6), Notable (7-8) o Sobresaliente (9-10). Si la nota no está entre 0 y 10, muestra 'Nota no valida'.
Encuentra el fallo: años bisiestos
Fácil
El programa lee varios años y debe decir si cada uno es bisiesto: lo es si es divisible entre 4, salvo los divisibles entre 100 que no lo son entre 400 (1900 no es bisiesto; 2000 sí). Hay años que salen mal. Corrige la condición.
Encuentra el fallo: la nota en palabras
Fácil
El programa convierte una nota entera (0 a 10) en su calificación: 0-4 Insuficiente, 5 Suficiente, 6 Bien, 7-8 Notable, 9-10 Sobresaliente. Con un 6 escribe varias palabras en lugar de una. Corrígelo.
Año bisiesto
Medio
Lee un año y di si es bisiesto. Un año es bisiesto si es divisible entre 4, excepto los divisibles entre 100, salvo que también lo sean entre 400. Formato: '2024 es bisiesto' o '2023 no es bisiesto'.
Validar una fecha y calcular el día siguiente
Difícil
Lee fechas «día mes año» (una por línea) y, para cada una, muestra «dd/mm/aaaa: no válida (el mes debe estar entre 1 y 12)», «dd/mm/aaaa: no válida (ese mes tiene N días)» o «dd/mm/aaaa → siguiente: dd/mm/aaaa», añadiendo « (año bisiesto)» si el año de la fech…
IRPF por tramos (simplificado)
Muy difícil
El IRPF es progresivo: cada tramo de la base se grava a un tipo distinto. Implementa escala(base) con la escala estatal y autonómica sumadas (simplificada): hasta 12 450 € al 19 %; de 12 450 a 20 200 al 24 %; hasta 35 200 al 30 %; hasta 60 000 al 37 %; hasta 3…
Lee un número n y muestra su tabla de multiplicar del 1 al 10 con el formato 'n x i = resultado', una línea por operación.
Encuentra el fallo: la suma de 1 a n
Fácil
El programa lee n y debe mostrar la suma 1 + 2 + … + n. Para n = 4 debería salir 10, pero sale 6. Corrige el bucle.
Suma de los dígitos
Medio
Lee un número entero positivo y calcula la suma de sus dígitos usando un bucle while. Formato: 'Suma: X'.
Encuentra el fallo: la media que pierde decimales
Medio
El programa lee números enteros hasta un 0 y muestra su media con dos decimales. Con 7, 8 y 8 debería salir 7,67 (en formato 7.67) pero sale 7.00. Corrígelo sin cambiar el tipo de los números leídos.
La conjetura de Collatz
Difícil
Toma un número: si es par, divídelo entre 2; si es impar, multiplícalo por 3 y súmale 1. Repite. La conjetura de Collatz dice que siempre se acaba llegando a 1, y nadie ha conseguido demostrarlo. Lee a y b (1 ≤ a ≤ b). Muestra la secuencia de a separada por « …
El calendario de un mes
Muy difícil
Lee un año y un mes y muestra su calendario como el de la orden cal de Linux, empezando la semana en lunes: el nombre del mes y el año; la cabecera «Lu Ma Mi Ju Vi Sá Do»; y las semanas, cada día con dos caracteres alineado a la derecha y separado por un espac…
Completa la función esPrimo(int n) y úsala para mostrar, separados por espacios, todos los números primos desde 2 hasta el número leído.
Factorial recursivo
Medio
Implementa la función recursiva factorial(int n) que devuelva n! como long. El programa muestra 'n! = resultado'. Recuerda que 0! = 1.
Encuentra el fallo: el método que no cambia nada
Medio
El método aplicarDescuento debería rebajar el precio un porcentaje, pero el programa sigue mostrando el precio original. Corrige el método y su llamada para que el precio cambie.
Las torres de Hanói
Difícil
Hay tres postes (A, B y C) y n discos de distinto tamaño apilados en A, del mayor abajo al menor arriba. Hay que pasarlos todos a C moviendo un disco cada vez y sin poner nunca uno grande encima de uno pequeño. La solución recursiva es sorprendentemente corta:…
Una calculadora con descenso recursivo
Muy difícil
Los compiladores leen las expresiones con analizadores recursivos. Implementa uno para expresiones de enteros (long) con +, −, *, / (división entera), % , paréntesis y el signo menos delante de un número o de un paréntesis, respetando la prioridad: primero par…
Dado un array de enteros, encuentra el valor máximo, el valor mínimo y las posiciones donde se encuentran. Imprime cada resultado en una línea separada con el formato: 'Maximo: X (posicion Y)' y 'Minimo: X (posicion Y)'.
Encuentra el fallo: el máximo de temperaturas bajo cero
Fácil
El programa lee varias temperaturas y muestra la más alta. Funciona en verano, pero en invierno, con todas bajo cero, dice que la máxima es 0. Corrígelo.
Invertir un array
Medio
Invierte el contenido de un array sin usar un segundo array auxiliar. El programa debe imprimir el array original y el array invertido usando Arrays.toString().
Estadísticas completas de notas
Medio
Dado un array de notas (valores entre 0 y 10), calcula y muestra: la media con dos decimales, cuántos alumnos han aprobado (nota >= 5), cuántos han suspendido, la nota más alta y la nota más baja.
Suma de filas y columnas de una matriz
Difícil
Dada una matriz de enteros 3x3, calcula e imprime la suma de cada fila y la suma de cada columna. Formato: 'Fila 0: X', 'Fila 1: Y', 'Fila 2: Z', 'Col 0: A', 'Col 1: B', 'Col 2: C'.
El juego de la vida de Conway
Muy difícil
En una cuadrícula, cada célula está viva (#) o muerta (.). En cada generación, todas cambian a la vez según sus 8 vecinas: una viva sigue viva si tiene 2 o 3 vecinas vivas (si no, muere); una muerta nace si tiene exactamente 3. Fuera de la cuadrícula no hay cé…
Lee una frase y cuenta cuántas vocales (a, e, i, o, u, en mayúscula o minúscula) contiene. Formato: 'Vocales: N'.
Encuentra el fallo: la contraseña que nunca es correcta
Fácil
El programa lee una contraseña y debe decir «Acceso concedido» si es «java2025». Aunque se escriba bien, siempre dice «Acceso denegado». Corrígelo.
Palíndromos
Medio
Lee una frase y di si es palíndroma ignorando espacios y mayúsculas. Muestra 'Es palindromo' o 'No es palindromo'.
Encuentra el fallo: el palíndromo exigente
Medio
Una frase es palíndroma si se lee igual al revés sin contar mayúsculas ni espacios. El programa dice que «Anita lava la tina» no lo es. Corrígelo para que ignore mayúsculas y espacios.
El cifrado de Vigenère
Difícil
El cifrado de Vigenère (siglo XVI) desplaza cada letra tantas posiciones como indica la letra de una clave que se repite: con la clave LIMON, la primera letra se desplaza 11 (L), la segunda 8 (I), etc. La entrada es «cifrar» o «descifrar», la clave (solo letra…
Justificar un texto
Muy difícil
Los procesadores de textos justifican los párrafos: reparten los espacios para que todas las líneas ocupen el mismo ancho. La primera línea de la entrada es el ancho y el resto, el texto (que puede venir en varias líneas). Reparte las palabras en líneas metien…
La clase Alumno guarda el nombre y la nota, pero al imprimir un alumno sale «null: 0.0». Corrige el constructor.
Una clase Fraccion inmutable
Difícil
Completa la clase Fraccion. El constructor debe lanzar IllegalArgumentException("denominador 0") si el denominador es 0, dejar el signo en el numerador (1/-2 pasa a -1/2) y simplificar con el máximo común divisor (4/8 pasa a 1/2). Los métodos sumar, restar, mu…
Máquina expendedora
Muy difícil
Completa la clase Maquina (los precios y las monedas van en céntimos). insertar acepta monedas de 5, 10, 20, 50, 100 y 200 y responde «Crédito: 1,50 €»; cualquier otra da «Moneda no válida: 3». comprar comprueba, en este orden, que el producto existe («No exis…
La clase abstracta Cuenta ya guarda el IBAN y el saldo y sabe ingresar. Completa sus dos subclases. CuentaCorriente permite quedarse en descubierto hasta −300 € (si una retirada lo supera lanza IllegalStateException("supera el descubierto")) y al cierre de mes…
Encuentra el fallo: el producto que no está en la lista
Difícil
La clase Producto define equals para que dos productos con el mismo código sean iguales, pero lista.contains(...) dice que no encuentra uno que sí está. Corrige equals (y lo que haga falta) para que contains funcione.
Expresiones matemáticas con polimorfismo
Muy difícil
Una expresión como (2 · x) + 3 se puede representar como un árbol de objetos: una Suma cuyo operando izquierdo es un Producto de Num(2) y Var(x), y cuyo derecho es Num(3). Num, Var y la clase abstracta Binaria (que ya sabe escribirse entre paréntesis) están he…
Cada línea de la entrada es un partido con el formato «Local 2-1 Visitante». Completa registrar, que actualiza las estadísticas de un equipo con los goles a favor y en contra de un partido (3 puntos por victoria y 1 por empate), y el Comparator CLASIFICACION, …
Reglas de contraseñas componibles
Muy difícil
Regla es una interfaz funcional: su único método abstracto, comprobar, devuelve la lista de errores de un texto (vacía si lo cumple). Completa sus métodos default y static para poder combinar reglas como piezas. y(otra) devuelve una regla que exige las dos y j…
La entrada es un fichero CSV (separado por «;», con decimales con coma) con la cabecera fecha;producto;unidades;precio y una venta por línea. Valida cada línea y muestra sus errores con su número de línea en el fichero (la cabecera es la 1; las líneas en blanc…
Comparar dos ficheros (diff)
Muy difícil
Herramientas como git diff muestran qué ha cambiado entre dos versiones de un fichero. La entrada contiene las líneas de la versión antigua, una línea «=====» y las de la nueva. Implementa diff: debe conservar el mayor número posible de líneas comunes en orden…
El programa debe quitar de la lista las tareas terminadas (las que empiezan por «x ») y mostrar las pendientes. En lugar de eso, termina con ConcurrentModificationException. Corrígelo.
Encuentra el fallo: el contador de palabras olvidadizo
Medio
El programa cuenta cuántas veces aparece cada palabra de una frase y las muestra en orden alfabético. Todas salen con 1 aunque se repitan. Corrígelo.
Agrupar anagramas
Difícil
Dos palabras son anagramas si tienen las mismas letras en distinto orden (amor, mora, Roma, ramo). La entrada es una lista de palabras. Implementa agrupar: trabaja en minúsculas (las letras con tilde cuentan como distintas: lámina no es anagrama de animal), ig…
Ruta más corta en el metro
Muy difícil
Cada línea «LINEA nombre e1 e2 e3…» conecta estaciones consecutivas en los dos sentidos. Cada «RUTA origen destino» pide el camino con menos paradas. Implementa ruta con una búsqueda en anchura (BFS): una cola con las estaciones por explorar y un mapa que guar…
El programa guarda en notas.csv las líneas recibidas por teclado (formato nombre;nota). Completa leerMedia() para que lea el fichero línea a línea con BufferedReader y devuelva la media de las notas. Se imprime con dos decimales.
Serializar una lista de productos
Medio
Completa guardar() y cargar() para escribir la lista de productos en productos.obj con ObjectOutputStream y volver a leerla con ObjectInputStream. El programa lee los productos por teclado (nombre;precio), los guarda, los carga de nuevo y muestra cuántos hay y…
Leer un XML con DOM
Medio
El programa guarda en biblioteca.xml el documento recibido por teclado. Completa procesar() para cargarlo con DOM, recorrer los elementos <libro> y mostrar cuántos libros hay y cuántos están disponibles (atributo disponible="si").
Acceso aleatorio a registros
Difícil
El programa crea empleados.dat con registros de tamaño fijo: id (int, 4 bytes), nombre (10 caracteres = 20 bytes) y salario (double, 8 bytes). Completa leerRegistro() para que use seek() y lea directamente el registro número n (empezando en 1) sin recorrer los…
Un CSV de verdad: comillas, separadores y saltos de línea
Difícil
Partir cada línea por el separador falla con CSV reales: un campo entre comillas dobles puede contener el separador, saltos de línea y comillas (escritas dos veces: ""). Lee todo el texto (separador ; como el Excel en español) y analízalo carácter a carácter s…
Leer un formato binario propio con versión y CRC
Muy difícil
Muchas aplicaciones guardan sus datos en un formato binario propio. Este guarda alumnos así (todo en big-endian, como DataOutputStream): 4 bytes ASCII «ALUM»; un short con la versión (1 o 2); un int con el número de registros; por cada registro, un int id, un …
Un PreparedStatement envía la sentencia y los datos por separado, así que un dato nunca puede convertirse en código SQL. Para verlo, simula lo que pasaría al concatenar. La primera línea es la plantilla con ? como marcadores; cada línea siguiente es un parámet…
Un pool de conexiones por dentro
Difícil
Abrir una conexión a la base de datos cuesta decenas de milisegundos, así que las aplicaciones usan un pool (HikariCP, el de Tomcat…) que las reutiliza. La primera línea es «max M espera W» y las siguientes, ordenadas por tiempo, «t pedir cliente» o «t devolve…
Transacciones con puntos de guardado y bloqueos
Muy difícil
Simula dos conexiones JDBC (sesiones A y B) sobre unas cuentas, como haría una base de datos con nivel de aislamiento READ COMMITTED. La primera línea es «cuentas C1=v1 C2=v2 …» y cada línea siguiente «S orden»: BEGIN (abre una transacción: setAutoCommit(false…
Acceso Datos · Mapeo Objeto-Relacional (Hibernate/JPA) ver el tema
El problema N+1 y las estrategias de carga
Medio
Con JPA, una consulta inocente como «SELECT a FROM Autor a» seguida de a.getLibros() en un bucle puede lanzar una consulta por autor: el problema N+1. Simula lo que hace Hibernate. La entrada tiene líneas «autor id nombre», «libro id idAutor título» y «estrate…
Los estados de una entidad JPA
Difícil
En JPA una entidad puede estar NUEVA (transient), GESTIONADA (managed: el EntityManager vigila sus cambios), SEPARADA (detached) o ELIMINADA (removed), y el SQL no se lanza cuando llamas a los métodos sino en el flush. Simula un EntityManager con una única tab…
Acceso Datos · BD Objeto-Relacionales y Orientadas a Objetos ver el tema
Arrays y tipos compuestos de PostgreSQL
Medio
PostgreSQL permite columnas de tipo array (text[]) y tipos compuestos (CREATE TYPE direccion AS (calle text, cp text, ciudad text)). Si se leen por JDBC con getString, llegan en su formato de texto y hay que interpretarlo. Cada línea de la entrada es «array {……
Profundidad de activación en una base de objetos
Difícil
Las bases de datos orientadas a objetos (db4o, ObjectDB) guardan grafos de objetos con referencias entre ellos. Al recuperar un objeto no cargan todo el grafo: lo «activan» solo hasta cierta profundidad, y los objetos más lejanos quedan como referencias sin re…
Herencia de tablas en PostgreSQL
Muy difícil
PostgreSQL permite que una tabla herede de otra (CREATE TABLE alumno (curso text) INHERITS (persona)): la hija tiene las columnas del padre más las suyas y, al consultar el padre, también salen las filas de las hijas. Pero las restricciones UNIQUE (y las clave…
Acceso Datos · Componentes de Acceso a Datos ver el tema
Propiedad ligada (bound property)
Fácil
Completa el JavaBean Termostato para que su propiedad temperatura sea ligada: cada vez que cambie de valor debe avisar a los oyentes con firePropertyChange. El programa lee temperaturas por teclado y los oyentes imprimen cada cambio (si el valor no cambia, no …
Propiedad restringida (constrained)
Medio
El componente CuentaBancaria tiene una propiedad saldo restringida: antes de cambiarla pregunta a los oyentes con fireVetoableChange, y cualquiera puede vetar el cambio lanzando PropertyVetoException. Completa setSaldo. El programa registra un oyente que veta …
Persistencia de un JavaBean en XML
Medio
Los JavaBeans pueden guardarse en XML con XMLEncoder y recuperarse con XMLDecoder, siempre que sigan las convenciones (constructor vacío, getters y setters). Completa guardar() y cargar() para el bean Configuracion. El programa lee el tema y el tamaño de letra…
Componente DAO con eventos
Difícil
Implementa AlumnoDaoMemoria, un componente de acceso a datos que cumple la interfaz AlumnoDao y además avisa a sus oyentes (DaoListener) cada vez que se guarda o se borra un alumno. El programa ejecuta las órdenes leídas por teclado: 'G nombre nota' guarda, 'B…
Un contenedor de inyección de dependencias
Muy difícil
Spring, Jakarta CDI o Micronaut son contenedores de componentes: el programa declara qué componentes hay y de qué dependen, y el contenedor los crea en el orden correcto y los inyecta. Simula uno. «componente N [depende=A,B] [ambito=prototype]» declara un comp…
Acceso Datos · Ejercicios de Acceso a Datos ver el tema
Filtrar un fichero de log
Fácil
El programa guarda en app.log las líneas recibidas por teclado. Completa filtrar() para que lea app.log y escriba en errores.log solo las líneas que contienen "ERROR", devolviendo cuántas ha copiado. Después se muestra el número y el contenido de errores.log.
Conversor de CSV a JSON
Medio
Convierte un fichero CSV con cabecera (nombre;ciudad;edad) en un array JSON, sin librerías externas. El programa guarda la entrada en personas.csv; completa convertir() para que devuelva el JSON con el formato exacto del ejemplo: [{"nombre":"Ana","ciudad":"Log…
Media de precios por categoría (DOM)
Difícil
El programa guarda el XML recibido en catalogo.xml. Cada <producto> tiene un atributo categoria y un elemento <precio>. Completa medias() para devolver un mapa ordenado categoría → precio medio. Se imprime cada categoría con su media con dos decimales.
Interfaces · Generación de Interfaces Gráficas ver el tema
La validación de un formulario de registro
Medio
Antes de habilitar el botón «Registrar», una interfaz valida cada campo y muestra un mensaje junto a él. Cada línea de la entrada es «campo=valor» (nombre, email, edad, clave y repetir; puede faltar alguno, y entonces vale vacío). Comprueba, en este orden: nom…
Repartir el ancho como un GridPane
Difícil
Un contenedor de rejilla (GridPane de JavaFX, GridBagLayout de Swing o grid de CSS) reparte su ancho entre columnas. La entrada es «ancho W», «hueco H» (separación entre columnas) y una línea por columna: «nombre fija N» (N píxeles), «nombre porcentaje P» (P %…
Captura y burbuja de un evento
Muy difícil
En JavaFX (y en el DOM), un evento recorre la jerarquía de nodos en dos fases: en la de captura se ejecutan los filtros (addEventFilter) desde la raíz hasta el nodo objetivo, y en la de burbuja los manejadores (addEventHandler / setOnAction) desde el objetivo …
Interfaces · Interfaces Naturales de Usuario ver el tema
Un intérprete de órdenes de voz
Medio
El reconocedor de voz (SpeechRecognizer en Android) devuelve texto; la aplicación debe extraer la intención y sus datos. Cada línea es una transcripción. Normalízala (la función normalizar quita tildes, signos y espacios de más) y reconoce, en este orden: una …
Clasificar gestos táctiles
Difícil
Un detector de gestos (GestureDetector en Android, o los eventos de puntero en JavaFX y en la web) decide qué ha hecho el dedo a partir de sus posiciones. Cada gesto es un bloque de líneas «tiempo_ms x y» (de que el dedo toca a que se levanta), y los gestos se…
¿Qué gesto hace la mano?
Muy difícil
Los detectores de manos (MediaPipe Hands, ML Kit) devuelven las coordenadas de 21 puntos de la mano. Aquí recibes 11 por mano, en coordenadas normalizadas (de 0 a 1, la y hacia abajo): «muneca x y» y, para cada dedo (pulgar, indice, corazon, anular, menique), …
Interfaces · Creación de Componentes Visuales ver el tema
Un componente de valoración por estrellas
Medio
Completa la clase Valoracion, un componente reutilizable como los que se crean extendiendo un control (JavaFX) o una View (Android). Tiene un valor entre 0 y 5 en medios puntos. setValor recorta el valor al rango [0, 5] y lo redondea al medio punto más cercano…
Propiedades observables y bindings
Difícil
Las propiedades de JavaFX (IntegerProperty, StringProperty…) avisan a sus oyentes cuando cambian y se pueden enlazar: una propiedad enlazada con bind sigue siempre el valor de otra. Implementa Propiedad (valor inicial 0) para que funcionen las órdenes: «set P …
Un campo de texto con máscara
Muy difícil
Los componentes de entrada con máscara (fechas, teléfonos, matrículas) solo aceptan caracteres válidos e insertan solos los separadores. La primera línea es «mascara M», donde en M # es un dígito, A una letra (se guarda en mayúscula), ? cualquier carácter y el…
Interfaces · Usabilidad y Accesibilidad ver el tema
Contraste de colores según WCAG
Medio
Cada línea tiene dos colores en hexadecimal (#rrggbb o #rgb): el del texto y el del fondo. Implementa la luminancia relativa de WCAG (cada canal se divide entre 255 y se linealiza: v ≤ 0.03928 → v / 12.92; si no, ((v + 0.055) / 1.055)^2.4; después L = 0.2126 R…
El orden de tabulación de un formulario
Difícil
Quien usa el teclado recorre la interfaz con Tab, así que el orden del foco debe ser lógico. Cada línea es un control «id x y tabindex habilitado» (habilitado vale si o no). Calcula el orden como lo hacen los navegadores y la mayoría de frameworks: primero los…
¿Se entiende este texto?
Muy difícil
La claridad del lenguaje también es accesibilidad. El índice de Fernández Huerta mide la legibilidad de un texto en castellano: L = 206.84 − 0.60 · P − 1.02 · F, donde P son las sílabas por cada 100 palabras y F la media de palabras por frase: cuanto más alto,…
Interfaces · Documentación de Aplicaciones ver el tema
El CHANGELOG a partir de los commits
Medio
Con la convención Conventional Commits, cada mensaje de commit tiene la forma «tipo(ámbito opcional)!opcional: descripción», y de ellos se deducen la siguiente versión semántica y el CHANGELOG. La primera línea es «version X.Y.Z»; las siguientes, los commits. …
De Javadoc a una página de documentación
Difícil
Las herramientas como javadoc o Dokka generan la documentación de una API a partir de los comentarios /** … */. La entrada es el código de una clase Java. Para cada método público (una línea que empieza por «public», contiene «(» y no es la declaración de la c…
Un revisor automático de manuales
Muy difícil
Igual que se pasa un linter al código, se puede revisar la documentación. La entrada es un manual en Markdown. Ignorando lo que hay dentro de bloques de código (entre líneas que empiezan por `), detecta en este orden: (1) en una primera pasada por los títulos,…
Interfaces · Distribución de Aplicaciones ver el tema
Versiones semánticas y rangos de dependencias
Medio
Los gestores de paquetes (Maven, npm, Gradle) eligen versiones comparándolas según el versionado semántico. La primera línea es una lista de versiones separadas por espacios, que pueden tener una etiqueta de prelanzamiento («1.2.0-beta.2»); el programa las ord…
¿Puedo distribuir mi aplicación con estas librerías?
Difícil
Antes de distribuir hay que revisar las licencias de las dependencias. La primera línea es «proyecto LICENCIA» (MIT, Apache-2.0, GPL-3.0, GPL-2.0 o Propietaria) y cada línea siguiente una dependencia «nombre licencia enlace», con enlace estatico (incluida en e…
Un actualizador incremental con despliegue escalonado
Muy difícil
Las aplicaciones de escritorio modernas se actualizan solas descargando solo lo que ha cambiado y publicando la versión nueva poco a poco. La entrada tiene una configuración «clave valor» (version_instalada, version_nueva, minima, porcentaje y usuario) y dos m…
Los errores se esconden en los bordes. Cada línea describe un campo de un formulario: «campo tipo min max», con tipo entero (el valor debe estar entre min y max) o texto (la longitud debe estar entre min y max). Genera sus casos de prueba: «== campo (tipo, min…
Un mini ejecutor de pruebas unitarias
Difícil
Implementa precioFinal(importe, código, socio) según esta especificación y un pequeño ejecutor de pruebas al estilo de JUnit. Especificación: un importe negativo lanza IllegalArgumentException; el código VERANO10 descuenta un 10 % y VIP25 un 25 % solo si el im…
Pruebas de interfaz guionizadas
Muy difícil
Las herramientas de pruebas de extremo a extremo (Playwright, Selenium, TestFX) siguen un guion: escribir, pulsar y esperar un resultado. Completa el modelo de PantallaAcceso y el ejecutor. Reglas de la pantalla: el botón Entrar se habilita cuando el usuario n…
Interfaces · Ejercicios de Desarrollo de Interfaces ver el tema
Validar un NIF en un formulario
Fácil
Antes de guardar un formulario hay que validar el NIF. Implementa nifValido: 8 dígitos y una letra (mayúscula o minúscula) cuya letra de control sea la correcta (TRWAGMYFPDXBNJZSQVHLCKE[número % 23]). Se ignoran espacios y guiones. El programa lee un NIF por l…
Informe agrupado con subtotales
Medio
Una pantalla de informes recibe líneas «categoría;importe». Muestra las categorías en orden alfabético con su subtotal y al final el total, con dos decimales y coma decimal: Audio: 104,95 Informática: 179,00 TOTAL: 283,95
Paginación de una tabla
Medio
Una tabla muestra los resultados en páginas. La primera línea de la entrada tiene el tamaño de página y la página pedida (empezando en 1); después, un elemento por línea. Muestra los elementos de esa página y al final «Página X de Y». Si la página no existe, m…
Comparar versiones semánticas
Medio
El actualizador de la aplicación compara la versión instalada con la publicada. Cada línea tiene dos versiones MAYOR.MENOR.PARCHE separadas por un espacio. Muestra «<», «>» o «=» según la primera sea menor, mayor o igual que la segunda. Ojo: 2.10.0 es mayor qu…
Multimedia · Tecnologías y Plataformas Móviles ver el tema
Densidades de pantalla y recursos de Android
Medio
Android agrupa las pantallas por densidad para escoger imágenes y por anchura mínima (smallest width) para escoger diseños. Cada línea es un dispositivo «nombre anchoPx altoPx pulgadas». Calcula su densidad real (diagonal en píxeles / pulgadas), el grupo de de…
El ciclo de vida de una Activity
Difícil
Entender cuándo llama Android a cada método del ciclo de vida evita perder datos. Cada línea es un evento; simula las llamadas y el estado de la pantalla con un campo de texto: «abrir» (onCreate → onStart → onResume), «escribir TEXTO» (el usuario escribe, sin …
Elegir el minSdk de una app
Muy difícil
Subir el minSdk permite usar APIs más nuevas sin comprobaciones, pero deja fuera a quienes tienen móviles antiguos. La entrada tiene líneas «cuota NIVEL PORCENTAJE» (dispositivos activos con cada nivel de API; puede que no sumen 100, así que hay que normalizar…
Multimedia · Desarrollo de Aplicaciones Móviles ver el tema
Las diferencias de una lista, como DiffUtil
Medio
Para no redibujar una lista entera (RecyclerView o LazyColumn) cada vez que cambian los datos, Android calcula las diferencias entre la lista vieja y la nueva (DiffUtil, ListAdapter). La primera línea es la lista antigua y la segunda la nueva, como elementos «…
La pila de navegación de una app
Difícil
El componente Navigation de Android mantiene una pila de pantallas (back stack). La primera línea es «inicio DESTINO»; después vienen órdenes «navigate DESTINO [popUpTo=X] [inclusive] [singleTop]» y «back». navigate apila el destino; con popUpTo=X, antes se de…
Sincronización sin conexión con conflictos
Muy difícil
Una app «offline first» guarda los cambios hechos sin conexión y los envía al recuperarla. La entrada tiene tres secciones: [servidor] con el estado actual «id valor tiempo», [base] con la versión que tenía el móvil cuando se quedó sin conexión, y [cambios] co…
Los motores dibujan a la frecuencia que pueden, pero calculan la física en pasos fijos (FixedUpdate en Unity, _physics_process en Godot). La entrada tiene «paso P» (ms de cada paso de física), «velocidad V» (px/s de un objeto que avanza en x desde 0) y una lín…
Colisiones con rejilla espacial
Difícil
Comprobar todos los objetos contra todos cuesta n·(n−1)/2 comprobaciones: con 1000 balas y enemigos, medio millón por fotograma. Los motores primero descartan los pares lejanos (fase amplia) con estructuras como una rejilla espacial. La primera línea es «celda…
El efecto túnel: detección discreta frente a continua
Muy difícil
Si una bala avanza 25 píxeles por fotograma y la pared mide 10, puede estar delante en un fotograma y detrás en el siguiente sin que nunca se detecte el choque (efecto túnel). Por eso los motores ofrecen detección continua (Continuous en el Rigidbody de Unity,…
Multimedia · Ejercicios de Programación Multimedia y Dispositivos Móviles ver el tema
¿Quién gana al tres en raya?
Fácil
La entrada son 3 líneas con el tablero (X, O o . para las casillas vacías). Muestra «Gana X», «Gana O», «Empate» (tablero lleno sin ganador) o «Sigue la partida».
Una generación del juego de la vida
Medio
La primera línea tiene filas y columnas; después, el tablero con # (célula viva) y . (muerta). Calcula la siguiente generación del juego de la vida de Conway y muéstrala: una célula viva con 2 o 3 vecinas vivas sobrevive; una muerta con exactamente 3 vecinas v…
Puntuación con combos
Medio
Por la entrada llega la secuencia de eventos de una partida, uno por línea: MONEDA (10 puntos), ENEMIGO (50 puntos), GOLPE (pierdes una vida y el combo vuelve a 0). Cada MONEDA o ENEMIGO seguidos aumentan el combo en 1 y los puntos del evento se multiplican po…
Camino más corto en un laberinto
Difícil
La IA de un enemigo necesita saber cuántos pasos hay hasta el jugador. La primera línea tiene filas y columnas; después el mapa con # (muro), . (suelo), E (enemigo) y J (jugador). Moviéndose en 4 direcciones, muestra el número mínimo de pasos de E a J, o «Sin …
El programa puede funcionar en dos modos. Si recibe los argumentos «trabajador desde hasta», es un proceso hijo: cuenta los primos de ese tramo y escribe el número (ya está hecho). Si no, es el coordinador: lee un límite y un número de procesos, reparte el int…
Planificador de CPU: FCFS, SJF y Round Robin
Muy difícil
El sistema operativo decide qué proceso usa la CPU en cada momento. La entrada es el quantum y, después, cada proceso con su identificador (una letra), su instante de llegada y su ráfaga de CPU. Implementa los tres algoritmos devolviendo la línea de tiempo: un…
Servicios · Hilos y Multithreading en Java ver el tema
Suma en paralelo con hilos
Difícil
La primera cifra de la entrada es el número de hilos y el resto, los números que hay que sumar. Reparte el array en tantos bloques consecutivos como hilos, lo más iguales posible: si no es divisible, los primeros bloques tienen un elemento más (con 10 números …
Productor-consumidor con un búfer acotado
Muy difícil
Varios productores dejan números en un búfer de capacidad limitada y un consumidor los va sacando. Implementa los métodos sincronizados de BufferAcotado con wait y notifyAll: poner espera mientras el búfer está lleno y sacar espera mientras está vacío; los dos…
El main ya arranca un servidor TCP en un puerto libre y un cliente que le envía cada línea de la entrada y muestra la respuesta. Implementa atender, que gestiona la conexión de un cliente siguiendo este protocolo (una orden por línea, una respuesta por línea):…
Mensajes fiables sobre UDP
Muy difícil
UDP no garantiza que los paquetes lleguen. El servidor de este reto lo simula: pierde uno de cada cuatro paquetes que recibe y una de cada tres respuestas. Implementa enviarFiable con el protocolo de parada y espera (stop-and-wait) que usan TCP y muchos juegos…
Servicios · Desarrollo de Servicios en Red ver el tema
Una API REST con HttpServer
Difícil
Completa manejar para que el servidor ofrezca una API REST de tareas. GET /tareas devuelve 200 y la lista en JSON, ordenada por id: [{"id":1,"texto":"..."}]. POST /tareas con el texto como cuerpo crea una tarea con el siguiente id, responde 201 con la tarea en…
Disyuntor (circuit breaker) para un servicio inestable
Muy difícil
Cuando un servicio remoto se cae, seguir llamándolo empeora las cosas: cada petición espera un tiempo de espera completo y sobrecarga al servicio cuando intenta recuperarse. El patrón disyuntor lo evita con tres estados. CERRADO: las llamadas pasan; tras umbra…
Servicios · Programación Segura en Java ver el tema
Guardar contraseñas con PBKDF2
Difícil
Nunca se guarda una contraseña, ni cifrada: se guarda un hash lento con sal. Implementa guardar, que genera una sal aleatoria de 16 bytes con SecureRandom, deriva el hash con el método derivar (PBKDF2-HMAC-SHA256, 32 bytes) usando ITERACIONES y devuelve el tex…
Tokens firmados con HMAC (como un JWT)
Muy difícil
Tras iniciar sesión, muchas APIs entregan un token que el cliente envía en cada petición. Para que no se pueda falsificar, va firmado. Implementa crear: el token son tres partes separadas por puntos, cada una en Base64URL sin relleno: la cabecera {"alg":"HS256…