Trabajos finales de la materia DSC G3 Utilizando todos los conocimientos adquiridos durante el curso, resuelva el problema que aparece a continuación utilizando como lenguaje de programación C/C++. Para solucionar el problema debe: 1. Diseñar los algoritmos necesarios que permitan resolver el problema planteado, utilizando alguna de las técnicas estudiadas. Debe indicar qué técnica utilizó y justificar su respuesta en cada caso. Puede ser que utilice varios algoritmos para resolver partes parciales del problema, cada uno con técnicas diferentes. 2. Implementar los algoritmos diseñados en C/C++ de la manera más óptima posible y mostrar su funcionamiento en un programa interactivo. 3. Calcular sus tiempos de ejecución y su complejidad algorítmica para los casos: mejor, peor y promedio, analizando cuando ocurre cada uno de los casos anteriores. Esto aplica para cada algoritmo diseñado.
Según seleccionaron en el chat, a continuación aparece el problema asignado a cada equipo: Mayra y José Luis (7) Dante, Emilio y Luis Armando (3) Edgar y Olga (4) Américo y José Jaime (2) Ernesto Lee y Adalberto (5) Carlos y Javier Aurelio (1) Rubén y Leobano (6)
Equipo 1. Hay un campo en el cual hay postes clavados en el suelo, en ubicaciones en apariencia arbitrarias. Un colono, al que le gustan particularmente los campos triangulares, desea establecer su chacra allí. Dada su preferencia, y el hecho de que no parece haber otros colonos, decide delimitar su chacra eligiendo los tres postes que hagan máxima su superficie. El archivo chatri.in contiene la lista de las coordenadas x e y, enteras, no negativas, menores que 1000, de cada poste, separadas por un espacio en blanco, en una línea cada par. El fin de la lista está indicado por un par –1 –1, que no forma parte de la lista. Hay a lo sumo 500 postes. En el archivo chatri.out debe grabar, en cualquier orden, las coordenadas de los tres postes que hacen máxima la superficie de la chacra triangular que determinan esos postes, en una línea cada par de coordenadas. Ejemplo: Si, chatri.in contiene:
0 4 1 7 3 1 3 8 5 10 5 5 6 2 8 9 10 7 10 3 -1 -1 El archivo chatri.out podría contener: 1 7 3 1 10 7 Equipo 2. Se desea escribir un programa para evaluar expresiones que representan operaciones entre conjuntos de números naturales menores que 1000. Los conjuntos están expresados por listas de valores separados por comas, y encerrados entre llaves. Los siguientes son cuatro ejemplos de conjuntos representados de este modo: {1,3,9,77} {} {7,1,193} {55}. Note que como las listas representan conjuntos, {1,3,9,77} y {77,3,1,9} representan el mismo conjunto y pueden utilizarse indistintamente. Una expresión puede ser simplemente una lista. Por ejemplo, {7,1,193} es una expresión cuyo resultado es ese mismo conjunto. Una expresión puede también formarse con dos listas, o expresiones, separadas por *, que representa la intersección de conjuntos, es decir el conjunto de los elementos comunes a ambos. Por ejemplo, {1,3,9,77}*{7,1,193} da como resultado {1}. Con igual forma constructiva, pero usando +, se calcula la unión, es decir el conjunto de los elementos que están al menos en uno de los dos conjuntos. Por ejemplo, {1,3,9,77}+{7,1,193} da como resultado {1,3,7,9,77,193}. Cuando hay múltiples operaciones seguidas, se evalúa de izquierda a derecha. Por ejemplo, {1,3,9,77}*{7,1,193}+{55} da como resultado {1,55}. Para expresar explícitamente un orden, cualquier expresión puede encerrarse entre paréntesis. Por ejemplo, {1,3,9,77}*({7,1,193}+{55}) da como resultado {1}. Estas reglas pueden aplicarse repetidamente. Por ejemplo, las siguientes expresiones son válidas: (((({})))), (({1}+{2,3})*({4,5,6}+{})), {}+({}+{})+({5}).
El programa a escribir debe leer una expresión, de hasta 250 caracteres, del archivo expres.in, evaluarla, y grabar el conjunto resultante como una lista en el mismo formato que la entrada, en el archivo expres.out. Por ejemplo, si expres.in contiene: (({3}+({1,4,2}))*({1,2,3,4,5}*{4,3,2,5}*{2,3,4,5,6}+{}))+{} el archivo expres.out podría contener {2,3,4} Equipo 3. Se cuenta con un mueble para biblioteca de N estantes y M libros de distinta altura. Por simplificación, todos los libros tienen el mismo ancho de forma tal que a lo sumo entren k libros por estante, todos “parados”. Además todos los libros caben en profundidad y la altura de los estantes es la suficiente para que calce cualquier libro. El objetivo es ordenarlos (parados), de forma que queden "lo más prolijo posible". Esto significa encontrar una distribución de los M libros en los N estantes tal que sea mínima la suma de los valores absolutos de las diferencias de altura de un libro con su vecino de la derecha, si hay. A este valor lo llamaremos “número de prolijidad”. Por ejemplo si tuviese 5 libros con las alturas: 5 5 6 8 9, a colocar en 2 estantes, el “número de prolijidad” sería 2, p. ej. colocando 6 5 5 en el primer estante y 8 9 en el segundo. Considere que: Hay más libros que estantes y alcanza el lugar en el mueble para guardarlos todos. (O sea N < M y K x N >= M) Además se restringen los valores según: 0 < K <= 50; 0 < N <= 10; 0 < M <= 500 La altura es un número entero tal que: 0 < altura <= 1000 El archivo de entrada libros.in posee: 1) N M K, en el primer renglón, separados por un espacio en blanco. 2) la altura de los M libros, uno por renglón. El archivo de salida libros.out tendrá solo el “número de prolijidad” Si libros.in tiene: 3 10 4 58 14 20 35789 10
libros.out tendrá 12 Equipo 4. En la entrada a una fiesta hay un portero, que controla una fila de damas y otra de caballeros. El portero puede decidir dejar entrar: -‐ a la primer dama de la fila -‐ al primer caballero de la fila -‐ a la pareja formada por la primer dama y el primer caballero de la fila. El portero sabe qué damas y caballeros simpatizan entre sí, y sabe dónde están en sus filas. Tiene la idea de dejar entrar las damas y los caballeros de forma tal de hacer pasar en pareja la mayor cantidad de damas y caballeros que simpaticen entre sí. Por ejemplo, si en las filas están las siguientes personas: 1 2 3 4 5
Mónica María Luisa Leticia Josefa
1 2 3 4
Juan Pedro Augusto Felipe
y el portero sabe que: Mónica y Felipe simpatizan María y Augusto simpatizan María y Felipe simpatizan Luisa y Juan simpatizan Leticia y Augusto simpatizan Leticia y Juan simpatizan Josefa y Felipe simpatizan
(pobre Pedro!) el portero debe:
dejar dejar dejar dejar dejar dejar
pasar sola a Mónica pasar sola a María entrar a Luisa con Juan entrar solo a Pedro entrar a Leticia con Augusto entrar a Josefa con Felipe.
Debemos ayudar al portero escribiendo un programa que determine la cantidad máxima de parejas que puede dejar entrar e identifique la primera de tales parejas. Datos de entrada Se recibe un archivo PORTERO.IN del directorio actual, que contiene: • Primera línea: el número n de damas en la fila de damas (n <= 1000) • n líneas, cada una con el nombre de una dama (hilera de hasta 30 caracteres usando letras y dígitos), la primer línea corresponde a la primer dama. • una línea con el número m de caballeros en la fila de caballeros (m <= 1000) caballero (hilera de hasta 30 caracteres usando letras y dígitos), la primer línea corresponde al primer caballero.
• una línea con el número p de parejas dama / caballero que simpatizan entre sí (0 < p <= 1000) • p líneas, cada una con una pareja dama / caballero, separados por un guión. Aclaraciones: No existen dos nombres iguales. Datos de salida El programa debe generar el archivo PORTERO.OUT, en el directorio actual, con: • una línea con la cantidad máxima de parejas (que simpatizan entre sí), que puede hacer pasar el portero. • una segunda línea con los nombres de alguna pareja (simpatizantes entre sí), separados por un espacio, que el portero puede hacer pasar primero si quiere maximizar las parejas. En caso de que no existan parejas que simpaticen entre sí, la primera línea debe decir 0 y no debe haber segunda línea. Ejemplo: En el caso de que el archivo PORTERO.IN contenga: 5 Mónica María Luisa Leticia Josefa 4 Juan Pedro Augusto Felipe 7 Mónica-Felipe Josefa-Felipe María-Augusto María-Felipe Luisa-Juan Leticia-Augusto Leticia-Juan el archivo PORTERO.OUT deberá contener: 3 Luisa Juan Equipo 5. Una clínica de salud quiere implementar un sistema de urgencias acorde a las necesidades de sus pacientes. Para lo anterior, ha decidido implementar un sistema formado por tres elementos principales: un conjunto de médicos con especialidades diferentes (pueden existir varios médicos de la misma especialidad) que siempre están de guardia en urgencias, un
sistema automatizado de diagnóstico (en lo sucesivo, SAD) que permitirá a cada paciente decidir con cuál médico debe pasar para ser atendido según sus síntomas, y una fila de pacientes que se van atendiendo en el mismo orden en que van llegando. Dentro de los requerimientos iniciales del sistema se tienen los siguientes: § De cada médico se conoce su nombre, apellidos y especialidad. Pueden existir tantos médicos de guardia como se necesiten, incluso varios médicos de la misma especialidad. § Cuando un paciente llega a la clínica, se registra en el sistema con su nombre, apellidos, edad y teléfono. Posteriormente consulta al SAD, el cual le hará una pregunta y el paciente debe responder si o no. En dependencia de cada respuesta, el SAD irá haciendo más preguntas hasta llegar a una decisión de determinar en cuál especialidad debe ser atendido el paciente. Una vez que el SAD determina la especialidad, debe enviar al paciente con el médico de dicha especialidad, que tenga menos pacientes en espera. A medida que el paciente interactúa con el SAD, este último va registrando junto con los datos del paciente, todas las preguntas realizadas al paciente y las respuestas obtenidas del mismo, para que el médico que lo atienda pueda tener una idea previa de sus padecimientos. Dos pacientes que respondan exactamente igual a las preguntas del SAD deben atenderse por un médico de la misma especialidad, pero no necesariamente por el mismo médico. § El sistema debe utilizar todos los conceptos de POO, programación genérica, sobrecarga de operadores, estructuras y algoritmos de la STL, uso y manipulación de streams, seriación de objetos, manipulación de errores con validación y excepciones (según sea el caso). § El código debe estar optimizado. Diseñe y programe una aplicación que permita: a) Ingresar médicos al cuerpo de guardia. b) Crear la base de información del SAD. c) Registrar un paciente nuevo; su interacción con el SAD y pasarlo a la lista de espera del médico correspondiente. d) Atender un paciente por el médico asignado (al ser atendido, el paciente deja la clínica y se retira a su casa). Cuando un paciente es atendido, su registro se queda almacenado en el sistema para cuestiones estadísticas. e) Generar un reporte en cualquier momento que incluya: a. Cantidad de médicos de guardia b. Para cada médico, su nombre, apellidos, especialidad, cantidad de personas que tiene en espera, cantidad de personas que ya ha atendido, y de cada persona su nombre, apellidos y edad. c. Por ejemplo, debe mostrarse una salida como la siguiente: Médicos de guardia: 3 Patricio Martínez (Cardiología) Personas atendidas: 2 1. Emeregildo Estévez, 54 años 2. Lisbet Esquivel, 87 años Personas en espera: 1 1. Salvador Imer, 60 años Josefina Almarante (Pediatría) Personas atendidas: 1 1. Lisa Elena Bustamante, 5 años Personas en espera: 1
1. Camilo Juárez, 8 años Emilia Alvarez (Pediatría) Personas atendidas: 0 Personas en espera: 1 1. Santiago Esquivel, 12 años f) Generar un reporte que muestre la cantidad de personas que han sido atendidas, agrupadas por especialidad. a. Por ejemplo: Cantidad de personas atendidas por especialidad: § Ginecología: 0 § Pediatría: 1 § Cardiología : 2 g) Generar un reporte de todas las personas que han sido atendidas (por todos los médicos), ordenadas ascendentemente por su edad, mostrando su nombre, apellidos, edad y especialidad del médico que la atendió: a. Por ejemplo, debe salir un listado como el siguiente: Personas atendidas: 1. Lisa Elena Bustamante, 5 años, Pediatría 2. Emeregildo Estévez, 54 años, Cardiología 3. Lisbet Esquivel, 87 años, Cardiología h) Almacenar el estado actual del sistema (médicos, personas en espera de ser atendidas, personas que ya fueron atendidas y la base de datos de preguntas del SAD) como mecanismo de respaldo de la información ante cualquier falla que pueda surgir. i) Restablecer el estado del sistema al punto en que se encontraba antes de ocurrir una falla. Equipo 6. Se quiere modelar un mapa de carreteras, donde aparezcan las ciudades y todas las rutas que las conectan entre sí. De cada ruta se conoce la distancia en kilómetros y de cada ciudad se conoce su número de habitantes, nombre y año de fundada. Programe una aplicación interactiva que permita: • • • •
• • •
Construir el mapa de carreteras. Determinar la población total del país. Determinar la ciudad más antigua y la más joven. Dada dos ciudades A y B, determinar si se puede llegar a la ciudad B partiendo de la ciudad A. En caso de ser posible indicar todas las posibles rutas (simples) con los nombres de las ciudades que incluye y la distancia de cada tramo, así como la distancia total a recorrer por cada ruta. Dada una ciudad, determinar cuál es la ciudad más cercana y cuál es la más distante. Actualizar el mapa, eliminando ciudades y/o carreteras, teniendo en cuenta que las ciudades se pueden quedar aisladas. Encontrar la ruta más corta entre dos ciudades, indicando las ciudades intermedias y las distancias de cada tramo, así como la distancia total a recorrer en kms.
• •
•
Encontrar las rutas más cortas desde una ciudad origen a todas las demás ciudades, indicando las distancias en kms. Dada una ciudad de origen y dos ciudades destino, determinar cuál de ellas se encuentra más cerca y cuál es la diferencia en kms con respecto a la que se encuentra más lejos. Encontrar la ruta más larga entre dos ciudades, indicando la distancia en kms.
Equipo 7. Sea n el número de tipos de monedas distintos, L la cantidad a conseguir y T[1..n] un vector con el valor de cada tipo de moneda del sistema. Supondremos que disponemos de una cantidad inagotable de monedas de cada tipo. Llamaremos C(i,j) (1 ≤ i ≤ n, 1 ≤ j ≤ L) al número mínimo de monedas para obtener la cantidad j restringiéndose a los tipos T[1], T[2], ..., T[i]. Si no se puede conseguir dicha cantidad entonces C(i,j) = ∞. En primer lugar hemos de encontrar una expresión recursiva de C(i,j). Para ello observemos que en cada paso existen dos opciones: 1. No incluir ninguna moneda del tipo T(i). Esto supone que el valor de C(i,j) va a coincidir con el de C(i–1,j), y por tanto C(i,j) = C(i–1,j). 2. Sí incluirla. Pero entonces, al incluir la moneda del tipo T(i), el número de monedas global coincide con el número óptimo de monedas para una cantidad (j – T(i)) más esta moneda T(i) que se incluye, es decir podemos expresar C(i,j) en este caso como C(i,j) = 1 + C(i,j – T(i)). El cálculo de C(i,j) óptimo tomará la solución más favorable, es decir, el menor valor de ambas opciones. Con esto, la relación en recurrencia queda definida como:
Una vez disponemos de la solución recursiva del problema, aplicaremos un algoritmo para calcular los C(n,j), 1 ≤ j ≤ L, mediante el uso de un vector de longitud L.