Universidad de Costa Rica Escuela de Computación |
Examen único |
CI-1201 Programación II - 2014a Profesor Jeisson Hidalgo-Céspedes |
En cada ejercicio se evaluará la eficiencia del código y las buenas prácticas de programación como: el uso de identificadores significativos, la indentación, escritura correcta de llaves {} y el uso adecuado de la palabra reservada const. Se dispone de tres horas para entregar la prueba y debe realizarse en forma estrictamente individual.
Una agencia de eventos competitivos organiza frecuentemente torneos o campeonatos de diversa índole. Por ejemplo, campeonatos de ajedrez, fútbol, "yaxis", contar chistes, música, baile, y hasta campeonatos de programación. En cada uno de ellos se sigue el mismo procedimiento: organizar los competidores en grupos, clasificar la mitad con mejor rendimiento de cada grupo, entrelazar un grupo con el siguiente (grupo A vs grupo B, C vs D), y realizar la eliminatoria confrontando a los que van ganando en las fases: cuartos de final, semifinal, tercer puesto y final.
El trabajo es repetitivo y se hace manualmente, a veces bajo presión durante el mismo evento. En algunas ocasiones se cometen errores en el diseño o surgen inconformismos de los competidores, por ejemplo, argumentando que los grupos se conformaron con alevosía o falta de equidad. Por esto la agencia consideró que sería mejor que una computadora realice el diseño del campeonato conformando aleatoriamente los competidores en grupos, permita registrar los resultados de los encuentros, e imprimir el estado del campeonato.
Dada que la naturaleza de los competidores puede variar mucho de una competencia a otra (jugadores de ajedrez, equipos de fútbol, parejas de baile, equipos de programación), y el sistema de puntuación (gane/empate/pérdida en ajedrez, goles en fútbol, votación promedio del jurado en baile, puntaje en programación), usted decide por programar una clase Campeonato
-si programa en inglés, Championship- genérica en C++. Usted debe escoger el mecanismo para proveer esta generalidad, sea usando plantillas o polimorfismo.
Campeonato
, por ejemplo un método agregarCompetidor()
-en inglés, addCompetitor()-, o el operador <<
.establecerCantidadGrupos()
-en inglés setGroupCount()- que le indica a la clase la cantidad de grupos que se quieren formar. Implemente un método hacerGrupos()
-makeGroups()- que distribuya aleatoriamente los competidores en los grupos indicados por el usuario de la clase. Este método no debe cambiar la semilla del generador de números aleatorios. Si lo necesita puede utilizar el algoritmo std::random_shuffle(itr1, itr2)
. Usted puede imponer las restricciones que necesite, por ejemplo, la cantidad de competidores debe ser múltiplo de la cantidad de grupos, y en caso del usuario no cumplirlas, debe indicarlo de alguna forma, como retornar un booleano o lanzar una excepción.imprimirGrupos()
que reciba por parámetro el archivo ostream
donde se quiere imprimir la lista de grupos con sus competidores.Campeonato
debe mantener registro de todos los encuentros celebrados y por celebrarse, además del marcador final en aquellos celebrados. Implemente una clase anidada Encuentro
-en inglés Match- que relaciona dos competidores (apuntadores) y el puntaje (score) que obtuvo cada uno en dicho encuentro. Asuma que este puntaje es siempre entero. Un encuentro debe poderse imprimir en un archivo que recibe por parámetro. Un encuentro debe ser capaz de saber si se ha celebrado o no.Encuentro
s en su clase Campeonato
, y un método actualizar()
que se encarga de llenar este contenedor con todos los encuentros conocidos hasta el momento. Los encuentros dependen del estado del campeonato y La clase Campeonato
debe conocer este estado: no iniciado, iniciado, eliminatoria, semifinal, final. Por ejemplo, al llamar el método actualizar()
cuando el campeonato está en estado no iniciado, provocará que se agreguen al contenedor de encuentros las permutaciones de los equipos de cada grupo. Una vez actualizado el campeonato, pasará al estado iniciado.Iterador
-en inglés Iterator o MatchIterator- que permite recorrer los encuentros conocidos del campeonato. Un iterador debe ser capaz de obtener una referencia al Encuentro
que "apunta" con el operador asterisco (*
), pasar al próximo encuentro con el operador de preincremento (++
), comparar si dos iteradores representan el mismo Encuentro
con los operadores ==
y !=
. Implemente en el iterador un método asignarResultado(a,b)
-en inglés setScores(a,b)
que recibe dos enteros, uno para el marcador del primer equipo y el otro para el marcador del segundo equipo. Implemente un método inventarResultado(max)
que asigna un marcador aleatorio a cada equipo.Campeonato
un método primerEncuentro()
que retorna un iterador al primer encuentro, un método ultimoEncuentro()
que retorna un iterador a un encuentro no válido, y un método primerEncuentroPendiente()
, que retorna un iterador al primer encuentro que aún no se ha celebrado.actualizar()
para que cuando se encuentre en estado iniciado revise todos los encuentros pendientes utilizando iteradores. Si todos los encuentros han sido efectuados, pasa al estado eliminatoria. Ordena cada grupo por los competidores con mejor rendimiento. Aquí debe imponer restricciones sobre la clase Competidor
. Si es una plantilla documente qué debe implementar (por ejemplo, el operador <
, si es una clase base polimórfica, implemente algún método virtual puro). Haga que la mitad de competidores de cada grupo pase a la eliminatoria, asignándoles nuevos encuentros (los cuales se agregan al contenedor de encuentros), de tal forma que se mezclen los grupos en orden: el mejor del grupo A contra el mejor del grupo B, el segundo mejor del grupo A contra el segundo mejor del grupo B; luego los mejores del grupo C contra los del grupo D, y así sucesivamente.main()
. Agregue competidores ficticios, invente marcadores hasta iniciar la eliminatoria.