Parcial de Programación 2

Anuncio
Instituto de Computación. Facultad de Ingeniería. Universidad de la República
Parcial de Programación 2
6 de Julio de 2012
•
La prueba es individual y sin material; la duración es 3 hs; sólo se contestan dudas acerca de la letra de los ejercicios.
•
Escriba las hojas de un sólo lado y con letra clara; comience la solución de cada ejercicio en una nueva hoja; numere
cada hoja, indicando en la primera el total; coloque su número de cédula y nombre en cada hoja.
SI TODAS LAS RESTRICCIONES EXPLICITADAS DE UN EJERCICIO NO SON CUMPLIDAS POR LA
SOLUCIÓN PROPUESTA, EL EJERCICIO TENDRÁ PUNTAJE 0. PRESTAR ATENCIÓN A LAS NOTAS
INCLUÍDAS EN CADA EJERCICIO.
•
Ejercicio 1 (30 puntos: 5 parte a y 25 parte b)
Parte a)
Especifique un TAD Cola de Prioridad acotada de elementos de un tipo genérico T donde las prioridades estén dadas por
números naturales y que permita obtener, y eliminar, elementos tanto de mínima como de máxima prioridad. Considere un
conjunto mínimo de operaciones constructoras, selectoras/destructoras (Min, BorrarMin, Max, BorrarMax) y predicados. El
TAD debe admitir la existencia de elementos de igual prioridad. Las selectoras/destructoras no deben considerar ningún
criterio específico para elementos de igual prioridad. Esto es, no deben considerarse criterios de selección (desempate) entre
elementos de igual prioridad.
SOLUCIÓN
(* Constructoras *)
PROCEDURE Crear(): CP;
* Retorna una cola de prioridad vacía. *)
PROCEDURE Insertar(d: T; p: CARDINAL; VAR cp: CP );
(* Inserta en la cola de prioridad "cp" el dato "d" con prioridad "p".
Precondición: NOT EstaLlena(cp) *)
(* Selectoras/Destructoras *)
PROCEDURE Min(cp: CP): T;
(* Retorna el elemento de CP con menor prioridad.
Precondición: NOT EsVAcia(cp) *)
PROCEDURE BorrarMin(VAR cp: CP);
(* Elimina el elemento de prioridad mínima de la cola de prioridad "cp".
Precondición: NOT EsVAcia(cp) *)
PROCEDURE Max(cp: CP): T;
(* Retorna el elemento de CP con mayor prioridad.
Precondición: NOT EsVAcia(cp) *)
PROCEDURE BorrarMax(VAR cp: CP);
(* Elimina el elemento de prioridad máxima de la cola de prioridad "cp".
Precondición: NOT EsVAcia(cp) *)
(* Predicados *)
PROCEDURE EsVacia(cp: CP): BOOLEAN;
(* Retorna TRUE si la cola de prioridad "cp" esta vacía. *)
PROCEDURE EstaLlena(cp: CP): BOOLEAN;
(* Retorna TRUE si la cola de prioridad "cp" esta llena. *)
PROCEDURE DestruirCola(VAR cp: CP);
(* Libera la memoria reservada por la cola cp y sus elementos *)
Parte b)
Desarrolle una implementación del TAD anterior donde las operaciones selectoras/destructoras (Min, BorrarMin, Max y
BorrarMax) y los predicados tengan O(1) de tiempo de ejecución en el peor caso. Se debe dar una representación que
permita además hacer un uso eficiente del espacio de almacenamiento para valores grandes de la cota del TAD, e
implementar completamente las operaciones definidas en la parte (a). No se permite usar TADs auxiliares en este
ejercicio.
SOLUCIÓN
CONST
TOPE = ...; (* Algun valor apropiado *)
TYPE
CP = POINTER TO cabezalCP;
nodoCP = POINTER TO celdaCP;
celdaCP = RECORD
prior: CARDINAL;
dato: T;
sig, ant: nodoCP;
END;
cabezalCP = RECORD
primero, ultimo: nodoCP;
contador: CARDINAL;
END;
(* Constructoras *)
PROCEDURE Crear(): CP;
(* Retorna una cola de prioridad vacía. *)
VAR cabezal:CP;
BEGIN
NEW(cabezal);
cabezal^.primero := NIL;
cabezal^.ultimo := NIL;
cabezal^.contador := 0;
RETURN(cabezal);
END Crear;
PROCEDURE Insertar (d: CARDINAL; p: CARDINAL; VAR cp: CP );
(* Inserta ordenado en la cola de prioridad "cp" el dato "d" con prioridad "p".
Precondición: NOT EstaLlena(cp) *)
VAR
aux, nuevo: nodoCP;
sale: BOOLEAN;
BEGIN
NEW(nuevo);
nuevo^.dato := d;
nuevo^.prior := p;
nuevo^.sig := NIL;
nuevo^.ant := NIL;
IF cp^.primero = NIL THEN
cp^.primero := nuevo;
cp^.ultimo := nuevo;
ELSIF p <= cp^.primero^.prior THEN
cp^.primero^.ant := nuevo;
nuevo^.sig := cp^.primero;
cp^.primero := nuevo;
ELSE
aux := cp^.primero;
sale := FALSE;
WHILE (NOT sale) AND (aux^.sig <> NIL) DO
aux := aux^.sig;
IF p <= aux^.prior THEN
sale := TRUE;
END;
END;
END;
IF sale THEN
aux^.ant^.sig := nuevo;
nuevo^.sig := aux;
nuevo^.ant := aux^.ant;
aux^.ant := nuevo;
ELSE
aux^.sig := nuevo;
nuevo^.ant := aux;
cp^.ultimo := nuevo;
END;
cp^.contador := cp^.contador + 1;
END Insertar;
(* Predicados *)
PROCEDURE EsVacia(cp: CP): BOOLEAN;
(* Retorna TRUE si la cola de prioridad "cp" esta vacía. *)
BEGIN
RETURN (cp^.contador = 0);
END EsVacia;
PROCEDURE EstaLlena(cp: CP): BOOLEAN;
(* Retorna TRUE si la cola de prioridad "cp" esta llena. *)
BEGIN
RETURN (cp^.contador = TOPE);
END EstaLlena;
(* Selectoras/Destructoras *)
PROCEDURE BorrarMin(VAR cp: CP);
(* Elimina el elemento de prioridad mínima de la cola de prioridad "cp".
Precondición: NOT EsVAcia(cp) *)
VAR nodoBorrar: nodoCP;
BEGIN
nodoBorrar := cp^.primero;
IF cp^.contador = 1 THEN
cp^.primero := NIL;
cp^.ultimo := NIL;
ELSE
cp^.primero := nodoBorrar^.sig;
cp^.primero^.ant := NIL;
END;
DISPOSE(nodoBorrar);
cp^.contador := cp^.contador - 1;
END BorrarMin;
PROCEDURE Min(cp: CP): T;
(* Retorna el elemento de CP con menor prioridad.
Precondición: NOT EsVAcia(cp) *)
BEGIN
RETURN (cp^.primero^.dato);
END Min;
PROCEDURE BorrarMax(VAR cp: CP);
(* Elimina el elemento de prioridad máxima de la cola de prioridad "cp".
Precondición: NOT EsVAcia(cp) *)
VAR nodoBorrar: nodoCP;
BEGIN
nodoBorrar := cp^.ultimo;
IF cp^.contador = 1 THEN
cp^.primero := NIL;
cp^.ultimo := NIL;
ELSE
cp^.ultimo := nodoBorrar^.ant;
cp^.ultimo^.sig := NIL;
END;
DISPOSE(nodoBorrar);
cp^.contador := cp^.contador - 1;
END BorrarMax;
PROCEDURE Max(cp: CP): T;
(* Retorna el elemento de CP con mayor prioridad.
Precondición: NOT EsVAcia(cp) *)
BEGIN
RETURN (cp^.ultimo^.dato);
END Max;
PROCEDURE DestruirCola(VAR cp : CP);
VAR borrar : CP;
BEGIN
borrar := cp^.primero;
WHILE (cp^.primero <> NIL) DO
cp^.primero := cp^.primero^.sig;
DISPOSE(borrar);
borrar := cp^.primero;
END;
DISPOSE(cp);
END;
Ejercicio 2 (30 puntos: 15 parte a y 15 parte b)
Parte a)
Considere el siguiente tipo Expresion, que representa expresiones enteras compuestas por: valores enteros, variables
(cuyo nombre es un carácter) y suma de sub-expresiones.
TYPE TipoExpresion = (Suma, Entero, Variable);
Expresion
= POINTER TO NodoExpresion;
NodoExpresion = RECORD
CASE tipo : TipoExpresion
Suma
: izq, der
Entero
: valor :
Variable : nombre :
END
END;
OF
: Expresion |
INTEGER
|
CHAR
|
Accediendo a la representación del tipo Expresion implemente, en Módula-2, el siguiente procedimiento:
PROCEDURE CrearExpresion ( VAR tokens : ColaToken ) : Expresion;
Que dada una cola de tokens no vacía, representando una expresión escrita en modo prefijo, genere el valor de tipo
Expresion equivalente. Esta operación remueve de tokens todos los tokens consumidos para construir la expresión,
destruyendo los tokens que remueve.
Ejemplo, la cola de tokens:
Genera la expresión:
Considere implementados los TADs ColaToken y Token, donde un token puede ser un operador de suma, un entero o un
caracter (nombre de variable). Especifique, con pre y post condiciones, las operaciones que utiliza de estos TADs.
Solución
PROCEDURE CrearExpresion (VAR tokens: ColaToken) : Expresion;
VAR
exp
: Expresion;
token : Token;
BEGIN
token := PrimeroColaToken(tokens);
DesencolarColaToken(tokens);
NEW(exp);
IF EsOperadorSumaToken(token) THEN
exp^.tipo := Suma;
exp^.izq
:= CrearExpresion(tokens);
exp^.der
:= CrearExpresion(tokens)
ELSIF EsEnteroToken(token) THEN
exp^.tipo := Entero;
exp^.valor := ObtenerEnteroToken(token)
ELSE
exp^.tipo
:= Variable;
exp^.nombre := ObtenerVariableToken(token)
END;
DestruirToken(token);
RETURN exp
END CrearExpresion;
(******* Operaciones del TAD Token utilizadas en el ejercicio *******)
PROCEDURE EsOperadorSumaToken(t : Token) : BOOLEAN;
(* POST: Devuelve TRUE sii el token contiene un operador de suma. *)
PROCEDURE EsEnteroToken(t : Token) : BOOLEAN;
(* POST: Devuelve TRUE sii el token contiene un número entero. *)
PROCEDURE EsVariableToken(t : Token) : BOOLEAN;
(* POST: Devuelve TRUE sii el token contiene una variable. *)
PROCEDURE ObtenerEnteroToken(t : Token) : INTEGER;
(* PRE: EsEnteroToken(t)
POST: Devuelve el número contenido en el token. *)
PROCEDURE ObtenerVariableToken(t : Token) : CHAR;
(* PRE: EsVariableToken(t)
POST: Devuelve el caracter (la variable) contenido en el token. *)
PROCEDURE DestruirToken(VAR t : Token);
(* POST: Libera la memoria reservada por el token. *)
(******* Operaciones del TAD ColaToken utilizadas en el ejercicio *******)
PROCEDURE PrimeroColaToken (c: ColaToken): Token;
(* PRE: NOT EsVaciaColaToken (c).
POST: Devuelve el primer elemento de la Cola 'c'. *)
PROCEDURE DesencolarColaToken (VAR c: ColaToken);
(* PRE: NOT EsVaciaColaToken (c).
POST: Quita el primer elemento de la Cola 'c'. *)
Parte b)
Accediendo a la representación del tipo Expresion implemente, en Módula-2, el siguiente procedimiento:
PROCEDURE ReducirExpresion ( var : CHAR; val : INTEGER;
expre : Expresion ) : Expresion;
que retorna una expresión (sin compartir memoria) resultante de reducir una expresión (expre) todo lo que sea posible
asignando un valor (val) a una variable (var). Por ejemplo, la expresión de la izquierda se reduce a la expresión de la
derecha si var es 'x' y val es 1.
Solución
PROCEDURE ReducirExpresion(var: CHAR; val: INTEGER; exp: Expresion) : Expresion;
VAR newExp: Expresion;
sum
: INTEGER;
BEGIN
NEW(newExp);
CASE exp^.tipo OF
Suma :
newExp^.tipo := Suma;
newExp^.izq := ReducirExpresion(var, val, exp^.izq);
newExp^.der := ReducirExpresion(var, val, exp^.der);
IF (newExp^.izq^.tipo = Entero) AND (newExp^.der^.tipo = Entero) THEN
sum := newExp^.izq^.valor + newExp^.der^.valor;
DISPOSE(newExp^.izq);
DISPOSE(newExp^.der);
newExp^.tipo := Entero;
newExp^.valor := sum
END;
| Entero :
newExp^.tipo := Entero;
newExp^.valor := exp^.valor;
| Variable :
IF (exp^.nombre = var) THEN
newExp^.tipo := Entero;
newExp^.valor := val;
ELSE
newExp^.tipo
:= Variable;
newExp^.nombre := exp^.nombre;
END
END;
RETURN newExp
END ReducirExpresion;
Descargar