====== Práctica Nro.: 2 (Listas) ====== ===== Enunciados ===== - Definir un predicado que permita obtener el último elemento de una Lista.\\ - Definir un predicado que retorne al Cabeza y la Cola de una Lista.\\ - Definir un predicado que calcule la longitud de una Lista.\\ - Definir un predicado verifique si un elemento pertenece o no a una Lista.\\ - Definir un predicado que dadas dos Listas, obtenga la Lista resultante de juntar estas dos en una sola (append).\\ - Definir un predicado que determine si un par de elementos figura en forma adyacente o no en una Lista.\\ - Definir la unión, la intersección, y la diferencia simétrica entre Listas (interpretando a estas como conjuntos).\\ - Con FindAll\\ - Sin FindAll\\ - Definir la relación Disjuntas aplicada a dos Listas.(Dos Listas son disjuntas si no tienen elementos en común)\\ - Con FindAll\\ - Sin FindAll\\ - Definir un predicado que determine la cantidad de hijos que tiene una madre utilizando Listas.\\ - Definir un predicado que obtenga una Lista que contenga la cadena de descendientes entre dos personas.\\ - Definir un predicado que determine la cantidad de hijos varones que tiene una persona.\\ - Definir un predicado que determine todos los hombres que no tienen hijos varones, utilizando Listas.\\ Para los ejercicios 10,11,12 y 13 se debe contar en la base de conocimientos con hechos referentes a las relaciones **Hombre**, **Mujer**, **Padre_de**, etc. ===== Resueltos ===== ==== Ej 1 ==== % Ej1 de la Práctica Nro 2. % Definir un predicado que permita obtener el último elemento de una lista. domains elemento = integer lista = elemento* predicates nondeterm obtenerUltimo(lista, elemento). clauses % Si es el último elemento le retorno. obtenerUltimo([Ca|[]], Ultimo) :- Ultimo=Ca. % Si tiene Cola, no es el último elemento, por eso es que llamo nuevamente obtenerUltimo con la Cola como Lista. obtenerUltimo([_|Co],Ultimo) :- obtenerUltimo(Co,Ultimo). goal obtenerUltimo([], Salida). ==== Ej 2 ==== % Ej 2 de la Práctica Nro 2. % Definir un predicado que retorne la cabeza y la cola de una Lista domains elemento = integer lista = elemento* predicates nondeterm obtenerCabezayCola(lista, elemento, lista). clauses obtenerCabezayCola([Ca|Co],Ca,Co). goal obtenerCabezayCola([1,2,3,4,5], Cabeza, Cola). ==== Ej 3 ==== % Ej 3 de la Práctica Nro 2. % Definir un predicado que calcule la longitud de una Lista. domains elemento = integer lista = elemento* predicates nondeterm longitud(lista, integer). clauses % Si la lista está vacía => Long es igual a 0. longitud([], Long) :- Long=0. % Si la lista no esta vacía calculo la longitud de la cola y le sumo uno. longitud([_|Co],Long) :- longitud(Co,Long2), Long=Long2+1. goal longitud([1,2,4,123,5678], Longitud). ==== Ej 4 ==== % Ej 4 de la Práctica Nro 2. % Definir un predicado que verifique si un elemento pertenece o no a una Lista. domains elemento = integer lista = elemento* predicates nondeterm perte(lista, elemento). clauses perte([Ca|_], Ca):- !. perte([Ca|Co], Elem) :- Ca<>Elem, perte(Co, Elem). goal perte([1,2,4,123,5678], 2). ==== Ej 5 ==== % Ej 5 de la Práctica Nro 2. % Definir un predicado que dadas dos Listas, obtenga la Lista resultante de juntar estas dos en una sola (append). domains elemento = integer lista = elemento* predicates % Agrego la segunda lista al final de la primera y la retorno en la tercera. nondeterm append(lista, lista, lista). clauses % Si la lista 2 está vacía, la Unión es solo la lista 1. append(Lista,[], Union) :- Union=Lista, !. % Si la lista 1 está vacía, la Unión es solo la lista 2. append([],Lista, Union) :- Union=Lista, !. append([Ca|Co],L2, Union) :- append(Co,L2,Union2), Union=[Ca|Union2]. goal append([1,2], [3,4,5], Salida). ==== Ej 6 ==== % Ej 6 de la Práctica Nro 2. % Definir un predicado que determine si un par de elementos figura en forma adyacente o no en una lisa. domains elemento = integer lista = elemento* predicates % Busco si en la primer lista se encuentran adyacentes los elementos de la segunda. nondeterm buscarAdyasentes(lista, lista, symbol). nondeterm compararCabezas (lista, lista). clauses % Comparo si son iguales las cabezas de las listas. compararCabezas([Ca1|_],[Ca2|_]) :- Ca1=Ca2. % Si la lista original esta vacía, sin importar la lista secundaria, el resultado es falso. buscarAdyasentes([],_,Salida) :- Salida="Falso",!. % Si la lista secundaria esta vacía, sin importar la lista principal, el resultado es falso. buscarAdyasentes(_,[],Salida) :- Salida="Falso",!. % Si las cabezas son distintas, sigo buscando en la cola de la primera. buscarAdyasentes([Ca1|Co1],[Ca2|Co2],Salida) :- Ca1<>Ca2, buscarAdyasentes(Co1,[Ca2|Co2], Salida). % Si las cabezas son iguales, pero los dos siguientes no, sigo buscando en la cola del primero. buscarAdyasentes([Ca1|Co1],[Ca2|Co2],Salida) :- Ca1=Ca2, not (compararCabezas(Co1,Co2)), buscarAdyasentes(Co1,[Ca2|Co2], Salida). % Si las cabezas son iguales, y los dos siguientes también, entonces esos dos son adyasentes. buscarAdyasentes([Ca1|Co1],[Ca2|Co2],Salida) :- Ca1=Ca2, compararCabezas(Co1,Co2), Salida="Verdadero",!. goal buscarAdyasentes([1,2,3,4,5,1,3,7],[4,5],Resultado). ==== Ej 6 (Otra forma) ==== % Ej 6 de la Práctica Nro 2. % Definir un predicado que determine si un par de elementos figura en forma adyacente o no en una lisa. domains lista = integer* predicates nondeterm adyacente(lista, integer, integer). clauses adyacente([Ca|Co], E1, E2) :- Ca<>E1, Ca<>E2, adyacente(Co, E1, E2). adyacente([E1,E2|_], E1, E2). adyacente([E2,E1|_], E1, E2). goal adyacente([1,2,3,1523], 2,3). ==== Ej 7 a ==== % Ej 7.a de la guía 2 % Definir la unión, la intersección, y la diferencia simétrica entre Listas (interpretando a estas como conjuntos) con FindAll. domains elemento = integer lista = elemento* predicates nondeterm perte(lista, elemento). nondeterm perte1AND2(lista, lista, elemento). nondeterm perte1OR2(lista, lista, elemento). nondeterm perte1NOT2(lista, lista, elemento). nondeterm union(lista, lista, lista). nondeterm inter(lista, lista, lista). nondeterm diferencia(lista, lista, lista). clauses perte([Ca|_],Ca). perte([_|Co], Elemento) :- perte(Co,Elemento). perte1AND2(L1, L2, Elemento) :- perte(L1,Elemento), perte(L2,Elemento). perte1NOT2(L1, L2, Elemento) :- perte(L1,Elemento), not(perte(L2,Elemento)). perte1OR2(L1, _, Elemento) :- perte(L1,Elemento). perte1OR2(_, L2, Elemento) :- perte(L2,Elemento). union(L1,L2,L3) :- findAll(X, perte1OR2(L1,L2,X), L3). inter(L1,L2,L3) :- findAll(X,perte1AND2(L1,L2,X),L3). diferencia(L1,L2,L3) :- findAll(X,perte1NOT2(L1,L2,X),L3). goal union([1,2,3], [3,5,6], Union), inter([1,2,3], [3,5,6], Interseccion), diferencia([1,2,3], [3,5,6], Diferencia). ==== Ej 7 b ==== % Ej 7.b de la guía 2 % Definir la unión, la intersección, y la diferencia simétrica entre Listas (interpretando a estas como conjuntos) sin FindAll. domains elemento = integer lista = elemento* predicates nondeterm perte(lista, elemento). % La segunda lista tendrá como cabeza el elemento y cola la primer lista. nondeterm insertarElemento(lista, elemento, lista). nondeterm union(lista, lista, lista). nondeterm inter(lista, lista, lista). nondeterm diferencia(lista, lista, lista). clauses perte([Ca|_],Ca). perte([_|Co], Elemento) :- perte(Co,Elemento). insertarElemento(ListaInicial, Elemento, ListaFinal) :- ListaFinal=[Elemento|ListaInicial]. % Si una de las listas está vacía la unión es toda la otra lista. union(Lista,[],Lista). union([],Lista,Lista). % Lista 1 es de entrada, Lista 2 es de entrada y Lista 3 es de salida. union([Ca|Co],L2,Union) :- union(Co,L2,Union2), insertarElemento(Union2, Ca, Union). % Si una de las listas está vacía la intersección es vacía. inter(_,[],[]). inter([],_,[]). % Busco para cada elemento de la lista 1 si pertenece a la lista 2, si es así lo inserto a la lista Intersección. inter([Ca|Co],L2,Interseccion) :- perte(L2,Ca), inter(Co,L2,Inter2), insertarElemento(Inter2,Ca,Interseccion). % Si la cabeza no pertenece a la segunda lista, entonces no pertenece a la intersección. inter([Ca|Co],L2,Interseccion) :- not (perte(L2,Ca)), inter(Co,L2,Interseccion). % Si la segunda lista está vacía la diferencia es igual a la lista 1. diferencia (Lista,[], Lista). % Si la primer lista está vacía, sin importar como es la segunda, la diferencia es vacía. diferencia ([],_, []). % Si la Cabeza de la primer lista no está en la segunda, entonces la inserto en diferencia. diferencia ([Ca|Co], Lista2, Diferencia) :- not (perte(Lista2,Ca)), diferencia(Co,Lista2,Dif2), insertarElemento(Dif2, Ca, Diferencia). diferencia ([Ca|Co], Lista2, Diferencia) :- perte(Lista2,Ca), diferencia(Co,Lista2,Diferencia). goal union([1,2,3], [4,5,6], Union), inter([1,2,3], [3,5,6], Interseccion), diferencia([1,2,3], [3,5,6], Diferencia).