Universidad Rey Juan Carlos Curso 2010/11 Ingeniería Técnica en Informática de Gestión Estructuras de Datos y de la Información Examen Final Junio 2011 Fecha: 3-5-2011 SOLUCIONES SEGUNDO PARCIAL Ejercicio 1. a) 3 9 2 3*9 27 2 27*2 9 27-2 54 3*2 25 9*6 54 6 3 18 9-6 3 3*18 54 9-2 9-3 9*2 7 3 6 2 18-3 15 6*2 3-2 6-2 12 4 1 7*3 7-3 1*9 21 4 9 9-1 9 8 b) WITH Operaciones, Listas_Operaciones, Listas_Positivos; PACKAGE Estados_Cifras IS TYPE TipoEstado IS LIMITED PRIVATE; PROCEDURE Inicializar(cifras: Listas_Positivos.TipoLista; exacto: Positive; estado: OUT TipoEstado); PROCEDURE Avanzar(estado: IN TipoEstado; operacion: IN Operaciones.TipoOperacion; sucesor: OUT TipoEstado); FUNCTION SolucionParcial(estado: TipoEstado) RETURN Listas_Operaciones.TipoLista; PROCEDURE ObtenerAlternativas(estado: IN TipoEstado; alternativas: OUT Listas_Operaciones.TipoLista); FUNCTION EsSolucion(estado: TipoEstado) RETURN Boolean; -- Otras operaciones auxiliares debidas al uso de memoria dinámica. << según el enunciado, no era necesario implementar estas operaciones >> PRIVATE TYPE TipoEstado IS RECORD cifras: Listas_Positivos.TipoLista; exacto: Positive; operaciones: Listas_Operaciones.TipoLista; END RECORD; END Estados_Cifras; 1 WITH Operaciones, Listas_Operaciones, Listas_Positivos; USE Operaciones, Listas_Operaciones, Listas_Positivos; PACKAGE BODY Estados_Cifras IS PROCEDURE Inicializar(cifras: Listas_Positivos.TipoLista; exacto: Positive; estado: OUT TipoEstado) IS BEGIN estado.exacto := exacto; CrearVacia(estado.operaciones); Copiar(estado.cifras,cifras); END Inicializar; PROCEDURE Avanzar(estado: IN TipoEstado; operacion: IN TipoOperacion; sucesor: OUT TipoEstado) IS BEGIN Copiar(sucesor, estado); BorrarElemento(Operando1(operacion),sucesor.cifras); BorrarElemento(Operando2(operacion),sucesor.cifras); Construir(Resultado(operacion),sucesor.cifras); InsertarFinal(sucesor.operaciones, operacion); END Avanzar; FUNCTION SolucionParcial(estado: TipoEstado) RETURN Listas_Operaciones.TipoLista IS BEGIN RETURN estado.operaciones; END SolucionParcial; PROCEDURE ObtenerAlternativas(estado: IN TipoEstado; alternativas: OUT Listas_Operaciones.TipoLista) IS PROCEDURE ProbarOperaciones(numero1, numero2: Positive; alternativas: IN OUT Listas_Operaciones.TipoLista) IS operacion : Operaciones.TipoOperacion; BEGIN -- suma Suma(numero1,numero2,operacion); Construir(operacion,alternativas); -- producto Producto(numero1,numero2,operacion); Construir(operacion,alternativas); -- resta IF numero2 > numero1 THEN Resta(numero2,numero1,operacion); Construir(operacion,alternativas); ELSIF numero1 > numero2 THEN Resta(numero1,numero2,operacion); Construir(operacion,alternativas); END IF; -- division IF numero1 MOD numero2 = 0 THEN Division(numero1,numero2,operacion); Construir(operacion,alternativas); ELSIF numero2 MOD numero1 = 0 THEN Division(numero2,numero1,operacion); Construir(operacion,alternativas); END IF; END ProbarOperaciones; 2 cursor_op1, cursor_op2: Listas_Positivos.TipoCursor; BEGIN CrearVacia(alternativas); cursor_op1 := PrimerCursor(estado.cifras); WHILE EsCursorValido(estado.cifras,cursor_op1) LOOP cursor_op2 := Siguiente(estado.cifras,cursor_op1); WHILE EsCursorValido(estado.cifras,cursor_op2) LOOP ProbarOperaciones(Elemento(estado.cifras,cursor_op1), Elemento(estado.cifras,cursor_op2), alternativas); cursor_op2 := Siguiente(estado.cifras, cursor_op2); END LOOP; cursor_op1 := Siguiente(estado.cifras,cursor_op1); END LOOP; END ObtenerAlternativas; FUNCTION EsSolucion(estado: TipoEstado) RETURN Boolean IS BEGIN RETURN Pertenece(estado.exacto,estado.cifras); END EsSolucion; END Estados_Cifras; c) Las estrategias de búsqueda más adecuadas serían profundidad y profundidad iterativa, dado que en ambos casos el número de estados pendientes por explorar en un momento dado es lineal con respecto a la profundidad del árbol de exploración. d) PROCEDURE Solucion_Cifras(numeros: IN Listas_Positivos.TipoLista; objetivo: IN Positive; solucion: OUT Listas_Operaciones.TipoLista) IS PROCEDURE InsertarSucesores(estado: IN Estados_Cifras.TipoEstado; cola: IN OUT Colas_Estados_Cifras.TipoCola) IS alternativas: Listas_Operaciones.TipoLista; cursor: Listas_Operaciones.TipoCursor; sucesor: Estados_Cifras.TipoEstado; BEGIN Estados_Cifras.ObtenerAlternativas(estado,alternativas); cursor := Listas_Operaciones.PrimerCursor(alternativas); WHILE Listas_Operaciones.EsCursorValido(alternativas,cursor) LOOP Estados_Cifras.Avanzar(estado,Listas_Operaciones.Elemento(alternativas,cursor), sucesor); Colas_Estados_Cifras.Insertar(sucesor, cola); cursor := Listas_Operaciones.Siguiente(alternativas,cursor); END LOOP; -- Liberamos memoria dinámica local Listas_Operaciones.Destruir(alternativas); Estados_Cifras.Destruir(sucesor); END InsertarSucesores; -- variables auxiliares 3 encontrada: Boolean := False; primero: Estados_Cifras.TipoEstado; cola: Colas_Estados_Cifras.TipoCola; BEGIN -- BuscarUna Estados_Cifras.Inicializar(numeros,objetivo,primero); Colas_Estados_Cifras.CrearColaVacia(cola); Colas_Estados_Cifras.Insertar(primero,cola); WHILE NOT Estados_Cifras.EsSolucion(primero) LOOP Colas_Estados_Cifras.Eliminar(cola); InsertarSucesores(primero,cola); -- Siguiente estado Estados_Cifras.Copiar(primero, Colas_Estados_Cifras.PrimeroCola(cola)); END LOOP; Listas_Operaciones.Copiar(solucion, Estados_Cifras.SolucionParcial(primero)); -- Liberamos memoria dinámica local Estados_Cifras.Destruir(primero); Colas_Estados_Cifras.Destruir(cola); EXCEPTION WHEN e: Colas_Estados_Cifras.ColaVacia => Ada.Exceptions.Raise_Exception(NoExisteSolucion'Identity); END Solucion_Cifras; Ejercicio 2. a) Tabla inicial: 0 Tras la inserción del 1 (sond.: 1) 1 2 3 F F F F F F F F 0 1 2 3 F F T F F F F F Tras la inserción del 6: (sond.: 2) 0 1 Tras la inserción del 10: (sond.:2,3) 0 1 2 3 F F T T T T T F 1 6 0 1 2 3 F F T F T T T F 0 1 14 10 1 2 3 2 3 F F T F F T T F 10 Tras la eliminación del 5: (snd: 1) 1 1 1 2 3 F F F F T T T F 14 10 3 6 Tras la inserción del 14: (sond: 2, 3) 0 1 2 3 F F T F T T T F 1 10 Tras la eliminación del 1 (sond.: 1): 0 2 1 Tras la eliminación del 6: (sond: 2) 0 1 F F T F T F F F 14 10 Tras la inserción del 5 (sond.: 1) 0 1 2 3 F F T F T T T F 5 14 10 F F T T T T T T ! 1 14 10 4 b) TYPE TipoVectorElementos IS ARRAY (TipoRangoDispersion) OF TipoElemento; TYPE TipoVectorBooleanos IS ARRAY (TipoRangoDispersion) OF Boolean; CAPACIDAD: CONSTANT Positive := TipoVectorElementos'Length; TYPE TipoTabla IS RECORD ocupacion: Natural; elementos: TipoVectorElementos; ocupada: TipoVectorBooleanos; ha_colisionado: TipoVectorBooleanos; END RECORD; FUNCTION BuscaClave(tabla: IN TipoTabla; key: IN TipoClave) RETURN TipoRangoDispersion IS encontrada: Boolean; posicion: TipoRangoDispersion; comprobadas: Positive := 1; pos_hash: TipoRangoDispersion := Hash(key); BEGIN posicion := pos_hash; encontrada := tabla.ocupada(posicion) AND THEN Clave(tabla.elementos(posicion))=key; WHILE NOT encontrada AND THEN tabla.ha_colisionado(posicion) AND THEN comprobadas<CAPACIDAD LOOP posicion := Recolocar(pos_hash, comprobadas); comprobadas:=comprobadas + 1; encontrada := tabla.ocupada(posicion) AND THEN Clave(tabla.elementos(posicion))=key; END LOOP; IF encontrada THEN RETURN posicion; ELSE raise_exception(ClaveNoEncontrada'Identity,"La clave no se encuentra"); END IF; END BuscaClave; FUNCTION Recuperar(tabla: TipoTabla; clave: tipoClave) RETURN TipoElemento IS BEGIN RETURN tabla.elementos(BuscaClave(tabla,clave)); END Recuperar; PROCEDURE Borrar(tabla: IN OUT TipoTabla; clave: IN TipoClave) IS pos: TipoRangoDispersion; BEGIN pos := BuscaClave(tabla,clave); tabla.Ocupada(Pos):=False; tabla.ocupacion:=tabla.ocupacion-1; EXCEPTION WHEN ClaveNoEncontrada=> NULL; END Borrar; 5