Tabla de Contenidos

Práctica Nro.: 2 (Listas)

Enunciados

  1. Definir un predicado que permita obtener el último elemento de una Lista.
  2. Definir un predicado que retorne al Cabeza y la Cola de una Lista.
  3. Definir un predicado que calcule la longitud de una Lista.
  4. Definir un predicado verifique si un elemento pertenece o no a una Lista.
  5. Definir un predicado que dadas dos Listas, obtenga la Lista resultante de juntar estas dos en una sola (append).
  6. Definir un predicado que determine si un par de elementos figura en forma adyacente o no en una Lista.
  7. Definir la unión, la intersección, y la diferencia simétrica entre Listas (interpretando a estas como conjuntos).
    1. Con FindAll
    2. Sin FindAll
  8. Definir la relación Disjuntas aplicada a dos Listas.(Dos Listas son disjuntas si no tienen elementos en común)
    1. Con FindAll
    2. Sin FindAll
  9. Definir un predicado que determine la cantidad de hijos que tiene una madre utilizando Listas.
  10. Definir un predicado que obtenga una Lista que contenga la cadena de descendientes entre dos personas.
  11. Definir un predicado que determine la cantidad de hijos varones que tiene una persona.
  12. 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).