Está en la página 1de 6

Paradigmas de Lenguajes de Programaci on

2
do
Cuatrimestre de 2012
Practica N
o
5 - Programaci on logica
Para resolver esta practica, recomendamos utilizar el programa SWI-Prolog, de distribucion gratui-
ta, que puede bajarse de http://www.swi-prolog.org. El unico meta predicado que puede utilizarse
para resolver los ejercicios es not. No utilizar cut (!) ni predicados de alto orden (como setof).
Los ejercicios marcados con el smbolo constituyen un subconjunto mnimo de ejercitacion. Sin
embargo, aconsejamos fuertemente hacer todos los ejercicios.
Ejercicio 1
i. A partir de los predicados binarios padre y esposo y de los predicados unarios hombre y mujer, denir en
Prolog los predicados binarios: hijo, abuelo, hermano, descendiente, tio. Si bien los nombres de estos
predicados tienen genero masculino se reeren al parentesco, sin considerar el genero de la persona; es
decir, deben admitir tanto mujeres como hombres. Se puede asumir que toda persona que aparece como
padre, aparece tambien como esposo.
ii. Considerar el arbol genealogico de la siguiente gura. Dibujar el arbol de b usqueda de Prolog para la
consulta abuelo(Alguien, ron).
iii. Denir una nueva relacion primo. Como se puede denir una consulta para conocer todos los primos de
ron?
iv. Considerar el agregado del siguiente hecho y regla:
ancestro(X, X).
ancestro(X, Y) :- ancestro(Z, Y), padre(X, Z).
y el arbol genealogico del tem anterior.
a) Explicar la respuesta a la consulta ancestro(bill, X).
b) Describir las circunstancias en las que puede ocurrir un ciclo innito en Prolog.
c) Sugerir un solucion al problema hallado en los puntos anteriores reescribiendo el programa de
ancestro.
Pagina 1 de 6
Paradigmas de Lenguajes de Programaci on
2
do
Cuatrimestre de 2012
Ejercicio 2
Usando la denicion de n umero natural a partir de cero y sucesor, denir un predicado unario natural,
tal que natural(-X) sii X es un n umero natural. Denir las siguientes relaciones entre n umeros naturales:
i. moi(-X, +Y) sii X es menor o igual que Y.
ii. producto(+X, +Y, -Z) sii Z es el producto de X con Y.
iii. factorial(+X, -F) sii F es el factorial de X.
iv. mod(+X, +Y, -Z) sii Z es el resto de la division entera entre X e Y. Dar una denicion recursiva y una no
recursiva.
v. Denir un predicado unario que determine si un n umero entero dado es primo. Tener en cuenta que el
argumento siempre esta instanciado.
Ejercicio 3
Sea el siguiente programa logico:
vecino(X, Y, [X|[Y|Ls]]).
vecino(X, Y, [W|Ls]) :- vecino(X, Y, Ls).
i. Mostrar el arbol de derivacion en Prolog para resolver vecino(5, Y, [5,6,5,3]), devolviendo todos los
valores de Y que hacen que la meta se deduzca logicamente del programa.
ii. Si se invierte el orden de las reglas, los resultados son los mismos? Y el orden de los resultados?
Ejercicio 4
Denir los siguientes predicados:
i. last(?L, ?U), donde U es el ultimo elemento de la lista L. Denirlo en forma recursiva, y usando el
predicado append denido de la siguiente manera:
append([], X, X).
append( [H | T], Y, [H | Z]) :- append(T, Y, Z).
ii. reverse(+L, -L1), donde L1 contiene los mismos elementos que L, pero en orden inverso.
Ejemplo: reverse([a,b,c], [c,b,a]).
Realizar una denicion usando append, y otra sin usarlo. Mostrar el arbol de prueba para el ejemplo dado.
iii. maxlista(+L, -M) y mnlista(+L, -M), donde M es el maximo/mnimo de la lista L.
iv. palndromo(+L, -L1), donde L1 es un palndromo construido a partir de L.
Ejemplo: palndromo([a,b,c], [a,b,c,c,b,a]).
v. doble(?L, ?L1), donde cada elemento de L aparece dos veces en L1.
Ejemplo: doble([a,b,c], [a,a,b,b,c,c]).
vi. prefijo(?P, +L), donde P es prejo de la lista L.
vii. sufijo(?S, +L), donde S es sujo de la lista L.
viii. sublista(?S, +L), donde S es sublista de L.
ix. iesimo(?I, +L, -X), donde X es el I-esimo elemento de la lista L.
Ejemplo: iesimo(2, [10, 20, 30, 40], 20).
x. pertenece(?X, +L), que es verdadero sii el elemento X se encuentra en la lista L. (Este predicado ya viene
denido en Prolog y se llama member).
Pagina 2 de 6
Paradigmas de Lenguajes de Programaci on
2
do
Cuatrimestre de 2012
Ejercicio 5
Denir los siguientes predicados:
i. interseccion(+L1, +L2, -L3), tal que L3 es la interseccion sin repeticiones de las listas L1 y L2, respe-
tando en L3 el orden en que aparecen los elementos en L1.
ii. mezcla(L1, L2, L3), donde L3 es el resultado de intercalar uno a uno los elementos de las listas L1 y L2.
Si una lista tiene longitud menor, entonces el resto de la lista mas larga es pasado sin cambiar. Vericar
la reversibilidad, es decir si es posible obtener L3 a partir de L1 y L2, y viceversa.
Ejemplo: mezcla([a,b,c], [d,e], [a,d,b,e,c]).
iii. split(N, L, L1, L2), donde L1 tiene los N primeros elementos de L, y L2 el resto. Si L tiene menos de
N elementos el predicado debe fallar. Cuan reversible es este predicado? Es decir, que elementos pueden
estar indenidos al momento de la invocacion?
iv. borrar(+ListaOriginal, +X, -ListaSinXs), que elimina todas las ocurrencias de X de la lista
ListaOriginal.
v. sacarDuplicados(+L1, -L2), que saca todos los elementos duplicados de la lista L1.
vi. corteMasParejo(+L,-L1,-L2) que, dada una lista de n umeros, realiza el corte mas parejo posible con
respecto a la suma de sus elementos (puede haber mas de un resultado). Por ejemplo:
?- corteMasParejo([1,2,3,4,2],L1,L2). L1 = [1, 2, 3], L2 = [4, 2] ; false.
?- corteMasParejo([1,2,1],L1,L2). L1 = [1], L2 = [2, 1] ; L1 = [1, 2], L2 = [1] ; false.
Ejercicio 6
Considerando los predicados append, prefijo y sufijo ya denidos, realizar el arbol de b usqueda para las
siguientes consultas:
i. prefijo(L, [a,b,c]), sufijo([a], L).
ii. prefijo(L, [a,b,c]), sufijo([b], L).
Ejercicio 7
Denir el predicado aplanar(+Xs, -Ys), que es verdadero sii Ys contiene los elementos de todos los niveles
de Xs, en el mismo orden de aparicion. Los elementos de Xs son enteros, atomos o nuevamente listas, de modo
que Xs puede tener una profundidad arbitraria. Por el contrario, Ys es una lista de un solo nivel de profundidad.
Ejemplos:
?- aplanar([a, [3, b, []], [2]], [a, 3, b, 2]).
?- aplanar([[1, [2, 3], [a]], [[[]]]], [1, 2, 3, a]).
Ejercicio 8
Denir los siguientes predicados:
i. ordenada(+L), que sera cierta si los elementos de L estan ordenados en forma ascendente.
ii. quicksort(+L, -L1), donde L1 es el resultado de ordenar L por el metodo de quicksort, que consiste en
dividir a L en 2 sublistas con los menores y mayores al primer elemento, ordenar cada una de ellas y luego
proceder a concatenarlas.
iii. inssort(+L, -L1), donde L1 es el resultado de ordenar L por el metodo de insercion, que consiste en
insertar cada elemento en el lugar adecuado del resto de la lista ya ordenada.
Ejercicio 9
Denir un predicado rotar(+L, +N, -R), tal que R sea la lista L rotada N posiciones (la rotacion se debe
hacer hacia la derecha si N>0 y hacia la izquierda si N<0).
Ejemplos:
rotar([1, a, 2, b, 3], 3, X) debe dar como respuesta X = [2, b, 3, 1, a]
rotar([1, a, 2, b, 3], -3, X) debe dar como respuesta X = [b, 3, 1, a, 2]
Pagina 3 de 6
Paradigmas de Lenguajes de Programaci on
2
do
Cuatrimestre de 2012
Ejercicio 10
Escribir en Prolog un predicado que devuelva la mediana de una lista (la mediana es el elemento que se
halla en la posicion del medio de dicha lista, tras ser ordenada). Utilizar los predicados denidos anteriormente.
Considerar que la lista siempre esta instanciada.
Ejercicio 11
Un arbol binario se representara en Prolog con:
nil, si es vaco.
bin(izq, v, der), donde v es el valor del nodo, izq es el subarbol izquierdo y der es el subarbol derecho.
i. Denir predicados en Prolog para las siguientes operaciones: vac\io, ra\iz, altura y cantidadNodos.
Asumir siempre que el arbol esta instanciado.
ii. Se dene la profundidad de un nodo como la distancia desde la raz hasta el mismo (la raz tiene pro-
fundidad 0). Denir un predicado hpp que permita, dado un arbol binario instanciado, obtener la lista de
todos los valores de las hojas que tengan profundidad par. Puede ocurrir que dos o mas hojas distintas
tengan el mismo valor, pero en la respuesta de hpp los valores no deben repetirse.
Ejemplo:
hpp( bin(bin(nil, 2, nil), 2, bin(bin(nil, 4, nil), 1, nil) ), L).
L = [4];
No.
Ejercicio 12
Denir los siguientes predicados, utilizando la representacion de arbol binario denida en el ejercicio 11:
i. aBB(+T), que sera verdadero si T es un arbol binario de b usqueda.
ii. aBBInsertar(+X, +T1, -T2), donde T2 resulta de insertar X en orden en el arbol T1.
iii. ramas(+AB,-Ramas), que tenga exito si AB es un arbol binario y Ramas una lista de listas de elementos
que representa las ramas del arbol (es decir, los caminos desde la raz hacia las hojas).
iv. arbolConRamas(+Ramas,-AB), version inversa del predicado anterior.
Ejercicio 13
Un arbol (a secas) de naturales se representara en Prolog con:
hoja(V), donde V es un natural seg un la representacion de Prolog.
nodo(V, Hijos), donde V es un natural seg un la representacion de Prolog, e Hijos es una lista no vaca
de arboles de naturales.
Denir el predicado mayores(+Arbol, +Max) que dado un arbol de naturales (que podra contener variables
en los nodos) devuelve verdadero si:
Los naturales que contiene el arbol son menores o iguales a Max (en caso de ser variables, deberan
instanciarse con valores en dicho rango).
El valor de cada nodo del arbol es mayor que la suma de los valores de sus hijos.
Ejemplo:
mayores(
nodo(X, [hoja(0), nodo(1,[hoja(0), hoja(0)]),
nodo(4,[hoja(1), hoja(0), nodo(1, [hoja(0)])])]),9
)
debe responder:
X = 8;
X = 9;
No
Pagina 4 de 6
Paradigmas de Lenguajes de Programaci on
2
do
Cuatrimestre de 2012
Ejercicio 14
Denir el predicado combinador(+L,+D,+H,-XS), que debe dar verdadero cuando XS es una lista de naturales
de longitud L, y cada uno de sus elementos XS
i
cumple que D XS
i
H. No se deben devolver soluciones repetidas.
Por ejemplo:
?- combinador(2,3,5,X).
X = [3,3] ;
X = [3,4] ;
X = [3,5] ;
X = [4,3] ;
X = [4,4] ;
X = [4,5] ;
X = [5,3] ;
X = [5,4] ;
X = [5,5] ;
No.
Ejercicio 15
Un cuadrado semi-latino es una matriz cuadrada de naturales (incluido el cero) donde todas las las de la
matriz suman lo mismo. Por ejemplo:
1 3 0
2 2 0 todas las las suman 4
1 1 2
Representamos la matriz como una lista de las, donde cada la es una lista de naturales. El ejemplo anterior
se representara de la siguiente manera: [[1,3,0],[2,2,0],[1,1,2]].
Se pide denir el predicado cuadradoSemiLatino(N,XS). El parametro N debe estar instanciado, no as XS
que no puede estar instanciado. El predicado debe ir devolviendo matrices (utilizando la representacion antes
mencionada), que sean cuadrados semi-latinos de dimension N*N. Dichas matrices deben devolverse de manera
ordenada: primero aquellas cuyas las suman 0, luego 1, luego 2, etc..
Ejemplo: cuadradoSemiLatino(2,X). devuelve:
X = [[0, 0], [0, 0]] ;
X = [[0, 1], [0, 1]] ;
X = [[0, 1], [1, 0]] ;
X = [[1, 0], [0, 1]] ;
X = [[1, 0], [1, 0]] ;
X = [[0, 2], [0, 2]] ;
etc.
Para la implementacion de cuadradoSemiLatino se cuenta con el siguiente predicado:
desde(+A, -B).
desde(D, D).
desde(D, X) :- DD is D+1, desde(DD, X).
Ejercicio 16
Sea la estructura Censo, y los siguientes predicados disponibles:
personas(+Censo, -Personas), que tiene exito cuando Personas contiene toda la lista de personas
registradas por el Censo.
edad(+Censo, +Persona, -Edad), que tiene exito cuando la Persona tiene edad Edad seg un el Censo.
Denir el predicado personasEnPromedio(+Censo, +Edad, -Conjunto) que tenga exito cuando Conjunto
sea una lista de Personas del Censo, cuyo promedio de edad sea menor a Edad.
Ejercicio 17
En este ejercicio trabajaremos con grafos no orientados. Un grafo no orientado es un conjunto de nodos y un
conjunto de ejes sin una direccion especca. Cada eje esta representado por un par de nodos y, como se puede
viajar en cualquiera de los dos sentidos, el eje (a, b) y el eje (b, a) son el mismo.
No sabemos cual es la representacion interna de un grafo, pero contamos con un predicado esNodo(+G,-X)
que dado un grafo G dice si X es nodo de G. Tambien tenemos otro predicado esEje(+G,-X,-Y) que dice si en G
hay un eje de X a Y. Notar que podemos usar esNodo para enumerar los nodos del grafo y esEje para enumerar
los ejes. Instanciando apropiadamente, tambien podemos usar esEje para obtener todos los ejes que tienen a un
nodo particular. Cuando esEje lista todos los ejes, cada eje lo lista una sola vez en una orientacion arbitraria
de las dos posibles, pero si se pregunta por cualquiera de las dos, respondera que s. Suponer que dos nodos son
el mismo si y solo si unican.
Ayuda: para algunos items conviene pensar primero en como programar el predicado opuesto al que se pide.
Pagina 5 de 6
Paradigmas de Lenguajes de Programaci on
2
do
Cuatrimestre de 2012
i. Implementar el predicado esCaminoSimple(+G,+D,+H,-L) que dice si L es un camino simple en el grafo G
que empieza en D y termina en H. Un camino simple lo representaremos por una lista de nodos distintos,
tal que para cada par de nodos consecutivos en L existe un eje en G que los conecta. Notar que el primer
elemento de L debe ser D y el ultimo H. Cuando L esta sin instanciar, el predicado debe ir devolviendo
todos los caminos simples desde D a H sin repetidos (es decir, hay que tener cuidado con los ciclos y evitar
que el predicado se cuelgue).
ii. Un camino L en un grafo G es Hamiltoniano sii L es un camino simple que contiene a todos los nodos G.
Implementar el predicado esCaminoHamiltoniano(+G,-L) que dice si L es un camino Hamiltoniano en G.
Recordar que no se pueden usar predicados de alto orden, salvo el not (en particular no se puede utilizar
setof).
iii. Implementar el predicado esConexo(+G) que dado un grafo dice si este es conexo. Un grafo G es conexo sii
no existe un par de nodos en G tal que no hay un camino simple que los una. Notar que con esta denicion
un grafo de un nodo (y sin ejes) es conexo.
iv. Implementar el predicado esEstrella(+G) que dado un grafo dice si es un grafo estrella. Un grafo es
estrella sii es conexo y hay un nodo com un a todos sus ejes.
Ejercicio 18
Trabajaremos con arboles binarios, usando nil y bin(AI, V, AD) para representarlos en Prolog.
i. Implementar un predicado arbol(-A) que genere estructuras
de arbol binario, dejando los valores de los nodos sin instan-
ciar. Deben devolverse todos los arboles posibles (es decir, para
toda estructura posible, el predicado debe devolverla luego de
un n umero nito de pedidos). No debe devolverse dos veces el
mismo arbol.
? arbol(A).
A = nil ;
A = bin(nil, _G104, nil) ;
A = bin(nil, _G107, bin(nil, _G117, nil)) ;
...
ii. Implementar un predicado nodosEn(?A, +L) que es verdadero
cuando A es un arbol cuyos nodos pertenecen al conjunto conjunto
de atomos L (representado mediante una lista no vaca, sin orden
relevante y sin repetidos). Puede asumirse que el arbol se recibe
instanciado en su estructura, pero no necesariamente en sus nodos.
? arbol(A), nodosEn(A, [ka, pow]).
A = nil ;
A = bin(nil, ka, nil) ;
A = bin(nil, pow, nil) ;
A = bin(nil, ka, bin(nil, ka, nil)) ;
A = bin(nil, ka, bin(nil, pow, nil)) ;
...
iii. Implementar un predicado sinRepEn(-A, +L) que genere todos los
arboles cuyos nodos pertenezcan al alfabeto L y usando como maximo
una vez cada smbolo del mismo. En este caso, no hay innitos arboles
posibles; es importante que el predicado no devuelva soluciones repeti-
das y que no se quede buscando indenidamente una vez terminado el
espacio de soluciones.
? arbolSinRepEn(A, [ka, pow]).
A = nil ;
A = bin(nil, ka, nil) ; ...
A = bin(nil, ka, bin(nil, pow, nil)) ;
... ;
No.
Ejercicio 19 (opcional)
Torres de Hanoi
Se tienen tres estacas A, B y C, y N discos de distintos tama nos, perforados en el centro. Los discos pueden
apilarse en las estacas formando torres, y estan ubicados inicialmente en la estaca A en orden decreciente de
tama no. El problema consiste en mover los discos de A a C de tal manera que terminen ordenados como lo
estaban originalmente. La tarea debe efectuarse bajo las siguientes restricciones:
En cada paso solo un disco puede moverse de una estaca a otra.
Nunca puede ubicarse un disco sobre otro mas peque no.
Usando Prolog, modelar y resolver el problema de las torres de Hanoi para tres estacas y N discos.
Pagina 6 de 6

También podría gustarte