Examen de LABORATORIO IV Junio de 2001 UNIVERSIDAD DE MÁLAGA Departamento de Lenguajes y Ciencias de la Computación Apellidos................................................................................Nombre ........................................... Especialidad: Gestión [ ] Grupo: A [ ] Sistemas [ ] B [ ] PROGRAMACIÓN LÓGICA A) Define los siguientes predicados: concatena(Xs,Ys,XsYs) XsYs es la concatenación de las listas Xs e Ys. selecciona(X,AsXBs,AsBs) AsBs es la lista AsXBs con una aparición menos del elemento X. suma(Xs,N) N es la suma de todos los elementos de la lista Xs. todosmayores(Xs,N) todos los elementos de la lista Xs son mayores que N. concatena([],Ys,Ys). concatena([X|Xs],Ys,[X|Zs]):concatena(Xs,Ys,Zs). selecciona(X,[X|Xs],Xs). selecciona(X,[Y|Ys],[Y|Zs]):selecciona(X,Ys,Zs). suma([],0). suma([X|Xs],N):suma(Xs,N1), N is X+N1. todosmayores([],_N). todosmayores([X|Xs],N):X>N, todosmayores(Xs,N). B) Define un predicado premax(PsRs,N,Ps,Rs) que devuelva en Ps el prefijo no vacío más largo posible de la lista PsRs, tal que la suma de sus elementos no supere el valor N, y devuelva en Rs el resto de PsRs. Ejemplo: ?- premax([3,6,2,1,6,4],10,Ps,Rs). Ps = [3,6] Rs = [2,1,6,4] ?- premax([13,6,2,1,6,4],10,Ps,Rs). No premax([X|Xs],N,[X|Xs],[]):suma([X|Xs],M), M=<N. premax([X|Xs],N,[A|As],[Y|Ys]):concatena([A|As],[Y|Ys],[X|Xs]), suma([A|As],M), M =< N, M+Y > N. C) Define un predicado partir(Ls,N,Es) que devuelva en Es la lista de las sublistas lo más largas posible de Ls tales que la suma de sus elementos no supere el valor N. Ejemplos: ?- partir([3,6,2,1,6,4],10,Es). Es = [[3,6],[2,1,6],[4]] ?- partir([3,6,2,12,6,4],10,Es). No partir([],_,[]). partir([X|Xs],N,[As|Yss]):premax([X|Xs],N,As,Bs), partir(Bs,N,Yss). D1) Define un predicado selecmax(Ls,N,Xs,Rs) que devuelva en Xs una lista no vacía de elementos de Ls tal que la suma de éstos se acerque lo más posible a N sin superarlo, y en Rs devuelve el resto de elementos de Ls. Ejemplo: ?- selecmax([3,6,2,1,6,4],10,Es,Rs). Es = [3, 6, 1] Rs = [2, 6, 4] ; Es = [6, 1, 3] Rs = [2, 6, 4] ; Es = [6, 2, 1] Rs = [3, 6, 4] ; ... selecmax(Xs,N,[],Xs):todosmayores(Xs,N), !. selecmax(Xs,N,[X|Ys],Rs):selecciona(X,Xs,Ls), X =< N, N1 is N-X, selecmax(Ls,N1,Ys,Rs). (El orden en que obtengas las soluciones no tiene que coincidir con el del ejemplo) D2) Define un predicado reparte(Ls,N,Xss) que reparta los elementos de la lista Ls en una lista de listas Xss tal que la suma de los elementos de cada lista de Xss se acerque lo más posible a N sin superarlo. Ejemplo: ?- reparte([3,6,2,1,6,4],10,Xss). Xss = [[3,6],[6,4],[2,1]]; Xss = [[6,3],[6,4],[1,2]]; Xss = [[6,2,1],[6,3],[4]]; ... (El orden en que obtengas las soluciones no tiene que coincidir con el del ejemplo) reparte([],_,[]). reparte([X|Xs],N,[As|Yss]):selecmax([X|Xs],N,As,Ls), reparte(Ls,N,Yss). PROGRAMACIÓN FUNCIONAL Sea el tipo data Elemento = E String Int deriving Show para representar una palabra y un contador asociado a ella. A) Los datos de este tipo debe poder compararse y ordenarse por el campo de tipo String lexicográficamente. Define funciones de igualdad y orden (Se recomienda la definición de las instancias correspondientes). instance Eq Elemento where (E s n) == (E s' n') = s == s' instance Ord Elemento where (E s n) <= (E s' n') = s <= s' B) Sea el tipo data Árbol a = Vacío | Nodo (Árbol a) a (Árbol a) deriving Show y sea el sinónimo de tipo type Dic = Árbol Elemento Queremos que los datos de Dic representen un árbol binario de búsqueda cuya información son datos de tipo Elemento. El orden de inclusión viene determinado por el definido en el apartado anterior. Define las siguiente función: insertar :: Elemento -> Dic -> Dic insertar :: Elemento -> Dic -> Dic insertar e'@(E s' n') Vacío = Nodo Vacío e' Vacío insertar e'@(E s' n') (Nodo i e@(E s n) d) | e' == e = Nodo i (E s (n+n')) d | e' < e = Nodo (insertar e' i) e d | otherwise = Nodo i e (insertar e' d) que inserta un elemento en el árbol teniendo en cuenta que si ya está, debe actualizar el contador con la suma de ambos y si no, creará un nuevo nodo. C) Utilizando map y foldr, define una función creaDic para que, a partir de una lista de palabras (posiblemente repetidas), genere la correspondiente lista de elementos y, a partir de ella, cree un árbol binario de búsqueda que almacene toda la información de la lista. creaDic :: [String] -> Dic creaDic :: [String] -> Dic creaDic = foldr insertar Vacío . map (\s -> E s 1) D.1) Define una función de plegado, foldÁrbol, para el tipo Árbol a. Usando este plegado, crea una función listado que genere una lista ordenada de elementos a partir de un árbol binario de búsqueda. foldÁrbol :: (b -> a -> b -> b) -> b -> Árbol a -> b foldÁrbol f z Vacío = z foldÁrbol f z (Nodo i r d) = f (foldÁrbol f z i) r (foldÁrbol f z d) listado :: Dic -> [Elemento] listado = foldÁrbol (\i r d -> i ++ [r] ++ d) [] D.2) Define una función que devuelva una lista con el/los elemento/s más citado/s (con mayor contador) de un árbol binario de búsqueda. (Se recomienda hacerla usando foldÁrbol). Ejemplo, siendo: l = ["pepe","juan","pedro","pedro","pepe","pedro","luis","pepe"]) entonces Main> másCitados (creaDic l) [E "pepe" 3, E "pedro" 3] :: [Elemento] másCitados :: Dic -> [Elemento] másCitados = foldÁrbol (\i r d -> une [r] (une i d)) [] where une xs@(E s n:_) xs'@(E s' n':_) | n == n' = xs ++ xs' | n > n' = xs | otherwise = xs'