Universidad Politécnica de Madrid Escuela Universitaria de Informática Departamento de Lenguajes, Proyectos y Sistemas Informáticos Asignatura PROGRAMACIÓN II EXAMEN DE LA CONVOCATORIA DE FEBRERO Plan: 92 / Curso: 2003-2004 Madrid a 30 de Enero de 2004 APELLIDOS: ...................................NOMBRE: .................................................. Nº DE MATRÍCULA: ....... DNI:.................GRUPO: .......................................... CALIFICACIONES TEORÍA PROB_1 PROB_2 TOTAL CUESTIONES TEÓRICAS Valoración: 3 puntos. Pregunta correcta:....................................0'2 puntos. Pregunta no contestada o incorrecta: .... -0'15 puntos I. UTILICE EL REVÉS DE LAS HOJAS DE PROBLEMAS COMO BORRADOR PROGRAMACIÓN CONCURRENTE. 1. ¿En qué arquitecturas no es directamente aplicable el modelo de variables compartidas? En las arquitecturas distribuidas 2. Defina en qué consisten las propiedades de seguridad de un programa concurrente. Cite dos propiedades de este tipo. Aquéllas que deben ser ciertas en todo instante de la ejecución del programa. Por tanto, aseguran que nada malo ocurrirá nunca durante una ejecución. Dos propiedades de seguridad son Exclusión Mutua y Ausencia de Interbloqueo Pasivo. Página 1 de 13 Programación II Febrero 2004 3. Describa la política utilizada para liberar un proceso mediante RESUME en un Monitor de PASCAL-FC. La política seguida por Pascal-FC es la que se conoce con el nombre de REANUDAR Y ESPERA URGENTE. Cuando un proceso ejecuta una operación RESUME sobre una variable de tipo CONDITION del monitor pueden darse dos casos: a) Si la cola de esa condición está vacía no tiene ningún efecto b) Si hay algún proceso bloqueado en esa condición, libera al primero de ellos (FIFO) y cede la exclusión mutua del monitor al proceso liberado, pasando el proceso que realiza el RESUME a bloquearse en la cola urgente del monitor. Los procesos bloqueados en la cola urgente tienen mayor prioridad para acceder al monitor que los de la cola exterior del monitor. 4. ¿Puede haber procesos bloqueados en la cola urgente de un monitor PASCAL FC, si ningún proceso está ejecutando código del monitor? ¿y si existe un proceso bloqueado en una CONDITION? Razone las respuestas. A ) NO: porque los procesos que se bloquean en la cola urgente de un monitor han realizado una operación RESUME sobre una de las “conditions” declaradas en él. Estos procesos tienen que salir en orden de la cola urgente en cuanto el monitor queda libre. Por lo tanto, si en el monitor no hay ningún proceso ejecutando código, y hay procesos bloqueados en la cola urgente el primer proceso bloqueado entraría a ejecutar código del monitor. B) NO: si se cumple también la condición anterior y por el mismo motivo SI: si no se cumple la condición anterior y hay un proceso ejecutando código de monitor 5. Dado el siguiente código, qué tipo de interacción se produce entre los procesos P1 y P2? ¿En qué estados pueden estar los procesos P1 y P2? PROGRAM P; VAR X: BOOLEAN; PROCESS P1 (VAR X:BOOLEAN); BEGIN A1 X:=TRUE; A2 END; PROCESS P2 (VAR X:BOOLEAN); BEGIN B1 WHILE NOT X DO; B2 END; BEGIN X:=FALSE; COBEGIN P1 (X); P2 (X) COEND END. a) La interacción es una Sincronización Condicional b) Los procesos pueden estar en los estados Preparado y Ejecución Página 2 de 13 Programación II Febrero 2004 II. PROGRAMACIÓN ORIENTADA A OBJETOS. 6. ¿Cómo se traduce en código una relación de uso con visibilidad privada? Con los objetos locales definidos para la implantación de los métodos de la clase cliente. 7. Atendiendo al siguiente diagrama de clases, codifique en PIIPOO los atributos y métodos de las clases cA, cB necesarios para la implantación de sus relaciones. cA Composición Composición cB cC Asociación CLASS INTERFACE cA; PUBLIC METHODS CONSTRUCTOR cA; END CLASS INTERFACE cA; CLASS INTERFACE cB; PUBLIC METHODS CONSTRUCTOR cB (pC: ^cC); END CLASS INTERFACE cB; CLASS IMPLEMENTATION cA; ATTRIBUTES mpC:^cC; mpB: ^cB; CLASS IMPLEMENTATION cB; ATTRIBUTES mpC:^cC; METHODS DEFINITION CONSTRUCTOR cA; BEGIN NEW (mpC, cC); NEW (mpB, cB(mpC) END; END CLASS IMPLEMENTATION cA; METHODS DEFINITION CONSTRUCTOR cB (pC: ^cC); BEGIN mpC:=pC; END; END CLASS IMPLEMENTATION cB; 8. ¿Tiene sentido en la implantación de un método MetodoB de una clase cA, escribir el mensaje SELF.MetodoA, cuando MetodoA es un método diferido de la clase cA? ¿y si el mensaje SELF.MetodoA se escribe en la implantación de un método MetodoC de una clase cB, derivada de cA? Razone su respuesta. a) SI: porque el método MetodoA puede estar redefinido en una clase derivada, y cuando un objeto de la clase derivada ejecute dicho código, SELF se referirá a dicho objeto de la clase derivada y se ejecutará el método A tal como esté definido en esa clase derivada. b) SI: si el método MetodoA está redefinido en la clase cB, SELF puede ser un objeto de la clase derivada cB y pasaría lo mismo que en el caso a). Si el método MetodoA no está redefinido quedará pendiente de definir en la descendencia de cB y también estaremos en el caso a) Página 3 de 13 Programación II Febrero 2004 9. ¿Qué es necesario para la implantación del polimorfismo en PIIPOO? Herencia e instanciación dinámica. 10. Dadas las vistas públicas de las siguientes clases en PIIPOO: CLASS INTERFACE cA; PUBLIC METHODS FUNCTION f (A : cA) : cA; OPERATOR := (A : cA); END CLASS INTERFACE cA, CLASS INTERFACE cB INHERITS FROM cA; PUBLIC METHODS FUNCTION f (B : cB) : cB; OPERATOR := (B : cB); END CLASS INTERFACE cB, Y las siguientes declaraciones de objetos: A : cA; B : cB; ¿Cuáles de las siguientes expresiones son correctas y cuáles no? Razone las respuestas. a) B:= A . f(A); CORRECTA. 1) El objeto A puede recibir f(A) que está definido en cA y devuelve un objeto de la clase cA 2) B recibe el mensaje := recibiendo un objeto de la clase cA, este operador está definido en su clase base cA y es heredado de ella b) B:= A . f(B); INCORRECTA. El objeto A no puede recibir f(B), ya que no está definido en su clase c) A:= B . f(A); CORRECTA. El objeto B puede recibir el mensaje f(A) porque lo ha heredado de cA, y devuelve un objeto de la clase cA. 2) A también puede recibir el mensaje := (x : cA) porque lo tiene definido en cA d) A:= B . f(B); INCORRECTA: El objeto B puede recibir el mensaje f(B) definido en cB y devuelve un objeto de la clase cB 2) A no puede recibir el mensaje := (x : cB) pues no lo tiene definido en su interfaz III. PROGRAMACIÓN FUNCIONAL. 11. ¿Qué es la transparencia referencial? El valor de una expresión compuesta depende únicamente de sus componentes y de nada más, no de la historia del programa en ejecución o de otros componentes que no estén inmersos en la expresión. Página 4 de 13 Programación II Febrero 2004 12. ¿Qué elementos pueden intervenir en un patrón en la definición de una función? Ponga un ejemplo de cada uno. Valores: Comodín: Identificadores: Tuplas con () Listas con [] Listas con :: 1 `a` _ a (5.1, `b`) (_, `b`) (b, c) [-1; 5] [_; `a`] [a; b] a :: b 13. Codifique en CAML una nueva definición de F utilizando patrones para evitar el uso de hd, tl, fst y snd. Defina su tipo. let rec F = function x- > if fst (x) = [] then 0 else if hd (fst x) = snd (x) then 1 + F (tl (fst(x)), snd(x)) else F (tl (fst(x)), snd(x));; let rec F = function [],_ -> 0 | cab::cola, ele -> if cab=ele then 1 + F (cola,ele) else F(cola,ele);; F: `a list * `a -> int = <fun> 14. Son correctas las siguientes expresiones, en caso incorrecto razone la respuesta, en caso correcto escriba en notación CAML su tipo. a) [[1;2];[true;false];[’a’;’b’]] b) ([1;2],(true,false),[‘a’;’b’]) c) [(1,true)=(2,false);true] d) [(`a`,[3],1);(`b`,[1;2;3],2);(`c`,[],3)] a) NO: Los elementos de una lista han de ser del mismo tipo. Los tipos de [ `a`;`b`] y [true;flase] son distintos b) SI int list * (bool*bool) * char list c) SI bool list d) SI (char * int list * int) list 15. ¿Son válidos los siguientes patrones? En caso afirmativo describa los valores que satisfacen el patrón; en caso negativo justifique su respuesta. a) _::_::L b) (v * false) :: L c) []::L::[(1,2)] d) _::0::int list a) SI Lista de cualquier tipo con al menos dos valores b) NO v * false no puede formar parte de un patrón c) NO la lista que se construye ha de tener los elementos del mismo tipo. (1,2) es una tupla y [] es una lista d) NO int list no puede formar parte de un patrón Página 5 de 13 Universidad Politécnica de Madrid Escuela Universitaria de Informática Departamento de Lenguajes, Proyectos y Sistemas Informáticos Asignatura PROGRAMACIÓN II ENUNCIADOS DE LOS PROBLEMAS DEL EXAMEN DE LA CONVOCATORIA DE FEBRERO Plan: 92 / Curso: 2003-2004 Madrid a 30 de Enero de 2004 Fechas de Publicación de Notas y de Revisión de Exámenes Publicación de Notas Miércoles 18 de Febrero de 2004 Revisión de Examen y Prácticas: Lunes 23 de Febrero de 2004 en horario que será publicado en el tablón de la Asignatura a la publicación de las notas Puede consultar sus notas en: www.lpsi.eui.upm.es/ProgramacionII/Notas.htm PROBLEMA 1: PROGRAMACIÓN CONCURRENTE Puntuación: 2'5 puntos En una carrera de relevos de atletismo compiten NumEquipos equipos, cada uno formado por NumCorredores corredores. El cuerpo de los procesos que simulan a los corredores tiene la siguiente estructura: PROCESS TYPE TCorredor (Equipo, Corredor : INTEGER); BEGIN Correr; RecogerPremio; END; donde Equipo representa el número del equipo de cada corredor (comprendido entre 1 y NumEquipos), y Corredor representa el número de orden del corredor dentro del equipo (comprendido entre 1 y NumCorredores). Los procedimientos Correr y RecogerPremio ya están codificados, y sólo se sabe de ellos que duran un tiempo aleatorio finito. SE PIDE: Escribir todo el código de sincronización necesario en los procesos para garantizar que se cumplan las siguientes condiciones: 1) Los corredores de equipos distintos pueden correr concurrentemente. 2) Dentro de un mismo equipo, primero debe correr el corredor 1. Hasta que éste no termina de correr, no puede comenzar a correr el corredor 2, y así sucesivamente hasta el último corredor del equipo. 3) La posición de un equipo al terminar la carrera viene determinada por el orden en el que finaliza de correr su último corredor. 4) Ningún corredor puede recoger su premio hasta que todos los corredores de todos los equipos hayan terminado de correr. 5) Una vez que todos los corredores hayan terminado de correr, primero recogen sus premios concurrentemente todos los corredores del equipo que ha quedado en la última posición. Cuando todos ellos han terminado de recoger su premio, pasan a recoger el suyo los corredores del equipo Página 6 de 13 Programación II Febrero 2004 que ha quedado en la penúltima posición, y así sucesivamente hasta el equipo que quedó en la primera posición. NOTA: Para guardar las posiciones de los equipos al terminar la carrera y recuperar esas posiciones en orden inverso para que cada equipo recoja su premio se dispone de la siguiente estructura de datos y de los siguientes procedimientos y funciones: (* Pila donde se guardan y se recuperan las posiciones de los equipos en la carrera *) TYPE TPilaEquipos = RECORD ........ END; (* Inicia la pila sin ningun equipo *) PROCEDURE Iniciar (VAR Pila : TPilaEquipos); ........ (* Guarda un equipo en la pila *) PROCEDURE MeterEquipo (VAR Pila : TPilaEquipos; Equipo : INTEGER); ........ (* Recupera un equipo de la pila *) PROCEDURE SacarEquipo (VAR Pila : TPilaEquipos; VAR Equipo : INTEGER); ........ (* Devuelve cuantos equipos hay en la pila *) FUNCTION Ocupacion (Pila : TPilaEquipos) : INTEGER; ........ Página 7 de 13 Programación II Febrero 2004 Solución Problema 1 MONITOR Carrera; EXPORT PreCorrer, PostCorrer, PostPremio; VAR (* Turno de los corredores de cada equipo *) iTurnoCorrer : ARRAY [1..NumEquipos] OF INTEGER; i : INTEGER; (* Colas donde cada corredor espera para correr *) qCorrer : ARRAY [1..NumEquipos] OF ARRAY [1..NumCorredores] OF CONDITION; (* Pila de las posiciones de los equipos *) PilaEquipos : TPilaEquipos; (* Colas donde los corredores de cada equipo esperan para recoger el premio *) qPremio : ARRAY [1..NumEquipos] OF CONDITION; (* Numero de corredores del equipo que han recogido su premio *) iFinPremio : INTEGER; (* ---------------------------------------------------------------------- *) PROCEDURE PreCorrer (Equipo, Corredor : INTEGER); BEGIN (* Esperar si no es el turno del corredor *) IF iTurnoCorrer[Equipo] <> Corredor THEN DELAY(qCorrer[Equipo][Corredor]) END; (* ---------------------------------------------------------------------- *) PROCEDURE PostCorrer (Equipo, Corredor : INTEGER); BEGIN (* Si no es el ultimo corredor del equipo *) IF Corredor < NumCorredores THEN BEGIN (* Avanzar el turno al siguiente corredor del equipo *) iTurnoCorrer[Equipo] := iTurnoCorrer[Equipo] + 1; RESUME(qCorrer[Equipo][iTurnoCorrer[Equipo]]); (* Esperar a recoger el premio *) DELAY(qPremio[Equipo]) END (* Si es el ultimo corredor del equipo *) ELSE BEGIN (* Si es el ultimo corredor del ultimo equipo *) IF Ocupacion(PilaEquipos) = NumEquipos - 1 THEN (* Despertar a todos los corredores del ultimo equipo *) WHILE NOT EMPTY(qPremio[Equipo]) DO RESUME(qPremio[Equipo]) (* Si no es el ultimo corredor del ultimo equipo *) ELSE BEGIN (* Guardar equipo en la pila *) MeterEquipo(PilaEquipos, Equipo); (* Esperar a recoger el premio *) DELAY(qPremio[Equipo]) END END END; Página 8 de 13 Programación II Febrero 2004 (* ---------------------------------------------------------------------- *) PROCEDURE PostPremio; VAR Equipo : INTEGER; BEGIN (* Aumentar el numero de corredores del equipo que han recogido el premio *) iFinPremio := iFinPremio + 1; (* Si es el ultimo corredor del equipo en recoger el premio *) IF iFinPremio = NumCorredores THEN BEGIN (* Reiniciar numero de corredores que han recogido el premio *) iFinPremio := 0; (* Si faltan equipos por recoger el premio *) IF Ocupacion(PilaEquipos) > 0 THEN BEGIN (* Sacar siguiente equipo de la pila *) SacarEquipo(PilaEquipos, Equipo); (* Despertar a todos los corredores del siguiente equipo *) WHILE NOT EMPTY(qPremio[Equipo]) DO RESUME(qPremio[Equipo]) END; END END; (* ---------------------------------------------------------------------- *) (* Iniciar el monitor *) BEGIN (* Iniciar el turno de los equipos *) FOR i := 1 TO NumEquipos DO iTurnoCorrer[i] := 1; (* Iniciar las posiciones de los equipos *) Iniciar(PilaEquipos); (* Iniciar numero de corredores del equipo que han recogido el premio *) iFinPremio := 0 END; (* ********************************************************************** *) (* Procesos de los corredores *) PROCESS TYPE TCorredor (Equipo, Corredor : INTEGER); BEGIN Carrera.PreCorrer(Equipo, Corredor); Correr; Carrera.PostCorrer(Equipo, Corredor); RecogerPremio; Carrera.PostPremio END; Página 9 de 13 Programación II Febrero 2004 PROBLEMA 2: PROGRAMACIÓN ORIENTADA A OBJETOS Puntuación: 2'5 puntos Una empresa de construcción levanta muros con piezas de dos tipos que, por su analogía con la grafía de los caracteres, denominaremos eles (L) y eses (S). a) Pieza L b) Pieza S Estas piezas pueden colocarse en distintas orientaciones con giros de 90º a partir de la posición original de la figura anterior. a) Pieza L 1) Orientación 0º 2) Orientación 90º 3) Orientación 180º 4) Orientación 270º b) Pieza S 1) Orientación 0º 2) Orientación 90º 3) Orientación 180º 4) Orientación 270º Los muros de construcción, que en todo momento deben quedar compactos sin posibles huecos, tienen un ancho de 20 columnas. En un momento dado de la construcción se desea saber automáticamente si se puede ensamblar una pieza con una cierta orientación en algún lugar de la parte superior del muro. ¿se puede ensamblar? SI SE PUEDE ¿se puede ensamblar? NO SE PUEDE Para la solución de este problema se ha decidido el siguiente diseño de clases: Página 10 de 13 Programación II Febrero 2004 CLASS INTERFACE cPieza; PUBLIC METHODS ... CLASS INTERFACE cPieza; CLASS IMPLEMENTATION cPieza; ATTRIBUTES (* con unicamente valores 0, 90, 180 y 270 grados *) Orientacion:INTEGER; ... END CLASS IMPLEMENTATION cPieza; CLASS INTERFACE cPiezaS; INHERITS FROM cPieza; PUBLIC METHODS ... CLASS INTERFACE cPiezaS; CLASS IMPLEMENTATION cPiezaS; ... END CLASS IMPLEMENTATION cPiezaS; CLASS INTERFACE cPiezaL; INHERITS FROM cPieza; PUBLIC METHODS ... CLASS INTERFACE cPiezaL; CLASS IMPLEMENTATION cPiezaL; ... END CLASS IMPLEMENTATION cPiezaL; CLASS INTERFACE cMuro; PUBLIC METHODS ... CLASS INTERFACE cMuro; CLASS IMPLEMENTATION cMuro; ATTRIBUTES (* almacena la altura de cada una de las columnas del muro compacto *) Columnas:ARRAY [1..20] OF INTEGER; ... END CLASS IMPLEMENTATION cMuro; SE PIDE Codificar el método sePuedeEnsamblar de la clase cMuro, y todo lo necesario en las clases dadas, para que, recibiendo una pieza de cualquier tipo, devuelva si dicha pieza tiene cabida en la parte superior del muro sin dejar huecos. Solución Problema 2 CLASS INTERFACE cMuro; PUBLIC METHODS Página 11 de 13 Programación II FUNCTION sePuedeEnsamblar (pPieza:POLYMORPHIC ^cPieza):BOOLEAN; END CLASS INTERFACE cMuro; Febrero 2004 CLASS IMPLEMENTATION cMuro; ATTRIBUTES Columnas:ARRAY [1..20] OF INTEGER; MERTHODS DEFINITION FUNCTION sePuedeEnsamblar(pPieza:POLYMORPHIC ^cPieza):BOOLEAN; BEGIN sePuedeEnsamblar:=pPieza^.Encaja(Columnas) END; END CLASS IMPLEMENTATION cMuro; CLASS INTERFACE cPieza; PUBLIC METHODS DEFERRED FUNCTION Encaja (Columnas:ARRAY [1..20] OF INTEGER):BOOLEAN; END CLASS INTERFACE cPieza; CLASS IMPLEMENTATION cPieza; ATTRIBUTES Orientacion:INTEGER; END CLASS IMPLEMENTATION cPieza; CLASS INTERFACE cPiezaS; INHERITS FROM cPieza; PUBLIC METHODS REDEFINED FUNCTION Encaja(Columnas:ARRAY [1..20] OF INTEGER):BOOLEAN; END CLASS INTERFACE cPiezaS; CLASS IMPLEMENTATION cPiezaS; METHODS DEFINITION FUNCTION Encaja(Columnas:ARRAY [1..20] OF INTEGER):BOOLEAN; LOCALS I:INTEGER; BEGIN IF (Orientacion=0) OR (Orientacion=180) THEN BEGIN WHILE ((I<18) AND NOT( (Columnas[I]=Columnas[I+1]) AND (Columnas[I+1]+1=Columnas[I+2]))) DO I:=I+1; Encaja:= ((Columnas[I]=Columnas[I+1]) AND (Columnas[I+1]+1=Columnas[I+2])) END ELSE BEGIN WHILE ((I<19) AND NOT((Columnas[I]-1= Columnas[I+1]))) DO I:=I+1; Encaja:= (Columnas[I]-1 = Columnas[I+1]) END; END; END CLASS IMPLEMENTATION cPiezaS; CLASS INTERFACE cPiezaL; INHERITS FROM cPieza; PUBLIC METHODS REDEFINED FUNCTION Encaja(Columnas:ARRAY [1..20] OF INTEGER):BOOLEAN; END CLASS INTERFACE cPiezaL; CLASS IMPLEMENTATION cPiezaL; METHODS DEFINITION FUNCTION Encaja(Columnas:ARRAY [1..20] OF INTEGER):BOOLEAN; LOCALS Página 12 de 13 Programación II I:INTEGER; Febrero 2004 BEGIN IF (Orientacion=0) OR (Orientacion=180) THEN BEGIN WHILE ((I<19) AND NOT( ((Orientacion=0) AND (Columnas[I]=Columnas[I+1])) OR ((Orientacion=180) AND (Columnas[I]-2=Columnas[I+1])))) DO I:=I+1; Encaja:= ((Orientacion=0) AND (Columnas[I]=Columnas[I+1])) OR ((Orientacion=180) AND (Columnas[I]-2=Columnas[I+1])) END ELSE BEGIN WHILE ((I<18) AND NOT( ((Orientacion=90) AND (Columnas[I]=Columnas[I+1]) AND (Columnas[I+1]=Columnas[I+2])) OR ((Orientacion=270) AND (Columnas[I]=Columnas[I+1]+1) AND (Columnas[I+1]=Columnas[I+2]))))) DO I:=I+1; Encaja:=((Orientacion=90) AND (Columnas[I]=Columnas[I+1]) AND (Columnas[I+1]=Columnas[I+2])) OR ((Orientacion=270) AND (Columnas[I]=Columnas[I+1]+1) AND (Columnas[I+1]=Columnas[I+2])) END; END; END CLASS IMPLEMENTATION cPiezaL; Página 13 de 13