Índice

Ejercicios Unidad 19 - Colecciones

Descargar estos ejercicios

Antes de empezar

Para realizar estos ejercicios, deberás descargar los recursos del enlace de proyecto_poo. Como puedes ver, la solución está compuesta de varios proyectos. Cada uno de ellos corresponde con un ejercicio, deberás implementar todo el código, tanto de la Main como de los métodos que se piden en cada ejercicio. Cada proyecto contiene el test correspondiente, que deberás pasar para comprobar que has hecho el ejercicio correctamente.

Ejercicio 1. Gestión de lista de Platos

Implementa un sistema para gestionar una colección de platos utilizando List<T> y métodos para realizar operaciones básicas como añadir, eliminar, buscar y filtrar platos según diferentes criterios.

Ejercicio 1. Gestión de lista de Platos

Lista de Platos:
1. Ensalada - 10,5 - Entrante
2. Solomillo - 20,0 - Principal
3. Tarta de Queso - 6,5 - Postre

Buscando plato Solomillo 20.0:
Plato encontrado en la posición: 1
Buscando plato Solomillo 25.0:
Plato no encontrado.

Eliminando plato en posición 0: Ensalada - 10,5 - Entrante
Lista de Platos:
1. Solomillo - 20,0 - Principal
2. Tarta de Queso - 6,5 - Postre

Plato añadido: Sopa - 8,0 - Entrante
Lista de Platos:
1. Solomillo - 20,0 - Principal
2. Tarta de Queso - 6,5 - Postre
3. Sopa - 8,0 - Entrante

Requisitos

Ejercicio 2. Gestión de lista de automóviles

Implementa un sistema para gestionar una colección de automóviles utilizando List<T> y métodos para realizar operaciones básicas como añadir, eliminar, buscar y filtrar automóviles según diferentes criterios.

Ejercicio 2: Gestión de lista de automóviles

=== LISTA INICIAL DE AUTOMÓVILES ===
Añadiendo automóviles a la lista...
Lista actual (5 automóviles):
1. Toyota Corolla - 1600cc - 2020 - Blanco
2. Honda Civic - 1800cc - 2019 - Negro
3. Ford Focus - 2000cc - 2020 - Rojo
4. Nissan Sentra - 1600cc - 2018 - Azul
5. Volkswagen Golf - 1400cc - 2020 - Blanco

=== BÚSQUEDA POR AÑO DE FABRICACIÓN ===
Automóviles del año 2020:
- Toyota Corolla - 1600cc - 2020 - Blanco
- Ford Focus - 2000cc - 2020 - Rojo
- Volkswagen Golf - 1400cc - 2020 - Blanco

=== BÚSQUEDA POR AÑO Y COLOR ===
Automóviles del año 2020 y color Blanco:
- Toyota Corolla - 1600cc - 2020 - Blanco
- Volkswagen Golf - 1400cc - 2020 - Blanco

=== ELIMINACIÓN DE AUTOMÓVIL ===
Eliminando automóvil en posición 2 (Honda Civic)...
Lista actualizada (4 automóviles):
1. Toyota Corolla - 1600cc - 2020 - Blanco
2. Ford Focus - 2000cc - 2020 - Rojo
3. Nissan Sentra - 1600cc - 2018 - Azul
4. Volkswagen Golf - 1400cc - 2020 - Blanco

=== AÑADIR NUEVO AUTOMÓVIL ===
Añadiendo: BMW Serie 3 - 2000cc - 2021 - Gris
Lista final (5 automóviles):
1. Toyota Corolla - 1600cc - 2020 - Blanco
2. Ford Focus - 2000cc - 2020 - Rojo
3. Nissan Sentra - 1600cc - 2018 - Azul
4. Volkswagen Golf - 1400cc - 2020 - Blanco
5. BMW Serie 3 - 2000cc - 2021 - Gris

Requisitos

Ejercicio 3. Comparación y Búsqueda en Colecciones

Vamos a trabajar con diferentes formas de comparación y búsqueda en colecciones.

Ejercicio 3. Comparación y Búsqueda en Colecciones

--- Parte 1: Búsqueda lineal con Contains ---
¿Existe la publicación 29/12/2025 9:11:00? True
¿Existe con EqualityComparer? True

--- Parte 2: Búsqueda de Usuarios ---
¿Existe el usuario user1? True

--- Parte 3: Búsqueda Binaria ---
Lista ordenada por fecha.
Posición encontrada (BinarySearch): 1
Posición encontrada (BinarySearch con IComparer): 1

Pulsar Enter para salir...

Requisitos

  1. Crea un tipo record Usuario con las propiedades: UserName, NombreCompleto y FechaRegistro (DateOnly).
  2. Crea una clase Publicacion con las propiedades: Id (DateTime con Fecha, hora, minutos y segundos), Autor (Usuario), Contenido, Likes (int) y una lista de cadenas Comentarios.

Parte 1: Búsqueda lineal con Contains

Queremos comprobar si una publicación específica está en la lista usando el método . Crea un Método EstaPublicación al que le llega una lista de publicaciones y una publicación y usa el método Contains para devolver si está el elemento en la lista.

Parte 2: Búsqueda de Usuarios
Crea un método EstaUsuario al que le llega una lista ade usuarios y un usuario y devuelve si el usuario pertenece a la lista.

Parte 3: Búsqueda Binaria
Crea un método BuscaPublicación al que le llega una lista de publicaciones y una publicación y devuelve la posición del elemento encontrado. Para ellos se deberá:

Crea un método BuscaPublicacionIComparer que realizará la búsqueda binaria pero usando la sobrecarga a la que se le pasa un objeto de tipo IComparer<T>

Completa el programa principal para probar todas las funcionalidades creadas.

Ejercicio 4. Diccionario contador de palabras

Utilizando la clase genérica Dictionary<K, V> definida en System.Collections.Generic,implementa un sencillo programa de consola que pida nombres por teclado hasta que introduzcamos la cadena "fin".

Ejercicio 4. Diccionario contador de palabras

Introduce nombres (escribe 'fin' para terminar):
Ana
Pablo
Maria
Ana
Juan
Sofia
Sofia
Laura
Pedro
Pablo
Ana
fin

Nombres introducidos (Claves):
Ana
Pablo
Maria
Juan
Sofia
Laura
Pedro

Conteo de nombres (Pares Clave-Valor):
Ana: 3
Pablo: 2
Maria: 1
Juan: 1
Sofia: 2
Laura: 1
Pedro: 1

Pulsar Enter para salir...

Requisitos

Idea

Para mostrar el resultado, deberás mostrar por un lado las claves y posteriormente el par clave valor. Para ello tendrás que recorre el diccionario 2 veces, una con un foreach para las claves y otra con un foreach para el diccionario obteniendo pares clave valor con la siguiente clase KeyValuePair<K, V>

Ejercicio 5. Diccionario con Clave Personalizada

Vamos a crear un inventario de productos donde la clave del diccionario será un objeto de tipo Producto y el valor será el stock disponible (un entero). Este ejercicio demostrará la importancia de implementar correctamente Equals y GetHashCode cuando se usan objetos propios como claves en un diccionario.

//Salida sin implementación correcta
Ejercicio 5. Diccionario con Clave Personalizada

Añadido p1: Laptop (A001) con stock 10
¿El inventario contiene p2 (misma info que p1)? False
No se pudo recuperar el stock con p2.

//Salida conn implementación correcta
Ejercicio 5. Diccionario con Clave Personalizada

Añadido p1: Laptop (A001) con stock 10
¿El inventario contiene p2 (misma info que p1)? True
Stock recuperado con p2: 10


Requisitos

  1. Crea una clase Producto con las propiedades: Codigo (string) y Nombre (string).
  2. En un método GestionInventario, crea un Dictionary<Producto, int> llamado inventario.
  3. Prueba inicial (sin implementar Equals/GetHashCode):
    • Crea dos instancias de Producto con el mismo código y nombre (por ejemplo, p1 y p2).
    • Añade p1 al diccionario con un stock de 10.
    • Intenta obtener el valor usando p2 como clave (inventario[p2]) o verifica si existe con inventario.ContainsKey(p2).
    • Observa y comenta qué sucede (debería fallar o no encontrarlo).
  4. Implementación correcta:
    • Modifica la clase Producto para que implemente la interfaz IEquatable<Producto>.
    • Sobrescribe el método Equals(object obj) y GetHashCode(). Dos productos deben considerarse iguales si tienen el mismo Codigo.
  5. Prueba final:
    • Repite la prueba del paso 3. Ahora inventario.ContainsKey(p2) debería devolver true y permitirte acceder al stock, demostrando que el diccionario identifica correctamente la clave por su contenido y no por su referencia.

Ejercicio 6. Red Social con Diccionarios

Vamos a crear una estructura básica para una red social utilizando las clases Usuario y Publicacion del ejercicio anterior, pero gestionándolas con diccionarios para un acceso eficiente.

Ejercicio 6. Red Social con Diccionarios

Usuarios registrados correctamente.
Publicaciones añadidas.

--- Todas las Publicaciones (Cronológico) ---
29/12/2025 13:35:15 - dev_master: Hola mundo! (5 likes)
29/12/2025 13:40:15 - code_ninja: Aprendiendo C# (10 likes)
29/12/2025 13:45:15 - dev_master: Diccionarios son útiles (3 likes)

--- Publicaciones de dev_master ---
29/12/2025 13:35:15 - dev_master: Hola mundo! (5 likes)
29/12/2025 13:45:15 - dev_master: Diccionarios son útiles (3 likes)

--- Publicaciones de code_ninja ---
29/12/2025 13:40:15 - code_ninja: Aprendiendo C# (10 likes)

Pulsar Enter para salir...

Requisitos

  1. Reutiliza las clases Usuario y Publicacion definidas en el Ejercicio 3.

  2. Crea una clase RedSocial que contenga las siguientes colecciones:

    • Dictionary<string, Usuario> usuarios: Donde la clave es el UserName y el valor es el objeto Usuario.
    • SortedDictionary<DateTime, Publicacion> publicaciones: Donde la clave es el Id de la publicación y el valor es el objeto Publicacion. Esto mantendrá las publicaciones ordenadas cronológicamente.
    • Dictionary<string, List<long>> publicacionesPorUsuario: Donde la clave es el UserName y el valor es una lista de enteros que representan los Id de las publicaciones de ese usuario.
  3. Implementa los siguientes métodos en la clase RedSocial:

    • RegistraUsuario(Usuario usuario): Añade un usuario al sistema. Debe verificar si el usuario ya existe, lanzando una excepción del tipo RedSocialExcepción indicando que ha ocurrido.
    • private void AñadePublicacionAUsuario(Usuario usuario, long idPublicacion): Método privado que añade el Id de la publicación a la lista de publicaciones del usuario correspondiente en el diccionario publicacionesPorUsuario. Deberá realizar las comprobaciones necesarias, para que no se repitan ID en el usuario.
    • public void AñadePublicacion(Publicacion publicacion): Añade una publicación al SortedDictionary de publicaciones y llama al método AñadePublicacionAUsuario para vincularla con su autor.
    • MostrarPublicacionesUsuario(string userName): Muestra todas las publicaciones de un usuario específico, recuperándolas a partir de sus IDs.
    • MostrarTodasPublicaciones(): Muestra todas las publicaciones ordenadas por fecha (gracias al SortedDictionary).
  4. En el método Main, instancia la RedSocial, registra varios usuarios, crea y añade publicaciones, y prueba los métodos de visualización.

Ejercicio 7. Lista de Reproducción Musical (LinkedList)

Vamos a simular una lista de reproducción de música donde el orden de las canciones es importante y queremos poder navegar entre ellas (siguiente, anterior) así como insertar canciones en posiciones específicas de forma eficiente. Para ello utilizaremos LinkedList<T>.

Ejercicio 7. Reproductor de Música con LinkedList

--- Reproduciendo (Inicio a Fin) ---
Reproduciendo: Imagine - John Lennon
Reproduciendo: Bohemian Rhapsody - Queen
Reproduciendo: Stairway to Heaven - Led Zeppelin

Insertando 'Hotel California' después de 'Imagine'...
--- Reproduciendo (Inicio a Fin) ---
Reproduciendo: Imagine - John Lennon
Reproduciendo: Hotel California - Eagles
Reproduciendo: Bohemian Rhapsody - Queen
Reproduciendo: Stairway to Heaven - Led Zeppelin

Eliminando 'Stairway to Heaven'...
--- Reproduciendo (Inicio a Fin) ---
Reproduciendo: Imagine - John Lennon
Reproduciendo: Hotel California - Eagles
Reproduciendo: Bohemian Rhapsody - Queen
--- Reproduciendo (Fin a Inicio) ---
Reproduciendo: Bohemian Rhapsody - Queen
Reproduciendo: Hotel California - Eagles
Reproduciendo: Imagine - John Lennon

Pulsar Enter para salir...

Requisitos

  1. Crea una clase Cancion con las propiedades: Titulo, Artista y Duracion (TimeSpan).

  2. Crea una clase ReproductorMusica que gestione una LinkedList<Cancion> llamada listaReproduccion.

  3. Implementa los siguientes métodos en ReproductorMusica:

    • AgregaCancionAlFinal(Cancion cancion): Añade una canción al final de la lista (AddLast).
    • AgregaCancionAlPrincipio(Cancion cancion): Añade una canción al principio de la lista (AddFirst).
    • InsertaDespuesDe(string tituloCancionExistente, Cancion nuevaCancion): Busca una canción por su título y, si existe, inserta la nueva canción justo después (AddAfter). Necesitarás usar Find para obtener el nodo.

    Aviso

    Como Find busca por valor, necesitarás implementar Equals en Cancion.

    • EliminaCancion(string titulo): Busca y elimina la primera canción que coincida con el título (Remove).
    • Reproduce(): Simula la reproducción recorriendo la lista desde el principio hasta el final. Muestra por consola "Reproduciendo: [Titulo] - [Artista]".
    • ReproduceInverso(): Simula la reproducción en orden inverso (desde la última hasta la primera).
  4. En el método Main, crea una instancia del reproductor, añade varias canciones, prueba a insertar una entre dos existentes, elimina una y reproduce la lista en ambos sentidos.

Ejercicio 8. Sistema de pedidos de restaurante con colecciones especializadas

Desarrolla un sistema para gestionar pedidos de un restaurante usando colecciones apropiadas para cada tipo de operación: menú ordenado, ingredientes únicos, cola de pedidos y histórico de clientes.

Ejercicio 8: Sistema de pedidos de restaurante

=== MENÚ DEL DÍA (por categorías) ===
ENTRANTES:
  - Ensalada César ($8,50)
  - Bruschetta ($6,00)
PRINCIPALS:
  - Paella Valenciana ($15,20)
  - Salmón a la plancha ($18,50)
POSTRES:
  - Tiramisu ($7,80)
  - Flan casero ($5,50)

=== COLA DE PEDIDOS ===
Cola actual (3 pedidos esperando):
1. 29/12/2025 - Mesa 5: Paella Valenciana, Tiramisu - Total: 23,00
2. 29/12/2025 - Mesa 2: Ensalada César, Salmón a la plancha - Total: 27,00
3. 29/12/2025 - Mesa 8: Bruschetta, Flan casero - Total: 11,50

Cocinando pedido de Mesa 5...
Pedido completado. Cola actualizada (2 pedidos).


Cliente Juan Martínez - Visitas: 6, Gasto promedio: $18,47
Pedidos:
        29/12/2025 - Mesa 0: Paella Valenciana - Total: 15,20
        29/12/2025 - Mesa 0: Paella Valenciana - Total: 15,20
        29/12/2025 - Mesa 0: Paella Valenciana - Total: 15,20
        05/10/2025 - Mesa 5: Paella Valenciana, Tiramisu - Total: 23,00
        02/10/2025 - Mesa 5: Ensalada César, Salmón a la plancha - Total: 27,00
        28/09/2025 - Mesa 5: Paella Valenciana - Total: 15,20

Pulsar Enter para salir...

Requisitos

Ejercicio 9. Implementación de una Pila Genérica (Wrapper)

Vamos a crear nuestra propia implementación de una pila (Stack) genérica, pero en lugar de usar un array interno (como hace Stack<T> de .NET), utilizaremos una List<T> privada para almacenar los elementos. Esto nos permitirá "capar" la funcionalidad de la lista y exponer solo las operaciones LIFO (Last In, First Out).

Ejercicio 9. Implementación de una Pila Genérica

--- Pila de Enteros ---
Pila con 3 elementos
Cima (Peek): 30
Desapilando (Pop): 30
Nueva Cima (Peek): 20
¿Está vacía?: False

--- Pila de Cadenas (desde Array) ---
Pila con 3 elementos
Desapilando: C#
Desapilando: Mundo
Desapilando: Hola
Excepción esperada: La pila está vacía.

Fin de la demostración de la pila.

Requisitos

  1. Crea una clase genérica Pila<T>.
  2. Define un campo privado List<T> _elementos donde se almacenarán los datos.
  3. Implementa los siguientes constructores:
    • Constructor vacío: Inicializa la lista interna.
    • Constructor con IEnumerable<T>: Permite inicializar la pila con los elementos de cualquier colección existente (Array, List, etc.).
  4. Implementa los métodos típicos de una pila:
    • Push(T elemento): Añade un elemento a la cima de la pila (final de la lista).
    • Pop(): Devuelve y elimina el elemento de la cima. Debe lanzar una excepción InvalidOperationException si la pila está vacía.
    • Peek(): Devuelve el elemento de la cima sin eliminarlo. También debe lanzar excepción si está vacía.
    • EstaVacia(): Devuelve true si no hay elementos.
  5. Implementa una propiedad Count que devuelva el número de elementos.
  6. Sobrescribe ToString() para mostrar el contenido de la pila.
  7. En el método Main, crea una pila de enteros, apila varios números, desapila uno, y prueba a crear otra pila de cadenas a partir de un array de strings usando el segundo constructor.

Ejercicio 10. Patrón Iterator en la Pila Genérica

Vamos a ampliar la clase Pila<T> del ejercicio anterior para que sea posible recorrer sus elementos utilizando un bucle foreach.

Ejercicio 10. Patrón Iterator en la Pila Genérica

Recorriendo la pila con foreach (LIFO):
Cuarto
Tercero
Segundo
Primero

Pulsar Enter para salir...

Requisitos

  1. Intento inicial: En el Main, intenta recorrer una instancia de tu Pila<T> con un bucle foreach. Observarás que el compilador da un error porque tu clase no implementa IEnumerable ni tiene un método GetEnumerator.
  2. Implementación del Iterador:
    • Modifica la clase Pila<T> para que implemente la interfaz IEnumerable<T>.
    • Implementa el método GetEnumerator() utilizando la palabra clave yield return.
    • Nota: El recorrido debe hacerse desde la cima (último elemento añadido) hacia el fondo, respetando la naturaleza LIFO de la estructura.
  3. Prueba final:
    • Vuelve a probar el bucle foreach en el Main. Ahora debería funcionar correctamente y mostrar los elementos de la pila.