Programación Lógica

Transcripción

Programación Lógica
Programación Lógica
Hoja de problemas 3
1. Escribir los siguientes predicados:
a) max(L,Max)::= calcula en Max el máximo de los elementos de la lista de enteros L
b) minMax(L,Min,Max)::= calcula en Max el máximo y en Min el mı́nimo de los elementos de la lista de enteros L (en un sólo recorrido de la lista L).
c) cuadrados(L,Lc)::= calcula en Lc la lista de los cuadrados de los enteros de la lista
L.
d) cuadrados2(L,Lc): análogo al anterior pero además asocia (con el functor ’:’) a cada
elemento un entero indicando la posición de la lista donde aparece. Por ejemplo, para
la lista L = [2, 3, 5, 1, 6] devolverá Lc = [1 : 4, 2 : 9, 3 : 25, 4 : 1, 5 : 36].
e) filtraPares(L,Lf )::= devuelve en la lista Lf los elementos pares que aparecen en la
lista de enteros L
f) eliminaDuplicados(L,L1)::= devuelve en L1 el resultado de eliminar los elementos
duplicados de la lista L
2. Supongamos un grafo definido como (análogamente a lo visto en clase):
arco(a,b).
arco(a,e).
arco(b,c).
arco(b,f).
arco(d,a).
arco(e,d).
arco(e,f).
arco(f,c).
arco(g,d).
arco(g,h).
arco(h,f).
Nótese que este grafo contiene ciclos, por lo que no es correcto definir el predicado camino
como:
camino(X,X).
camino(X,Y):- arco(X,Z), camino(Z,Y).
¿Qué ocurrirı́a con el objetivo camino(a,b)?
Se pide:
a) Hacer una definición correcta del predicado camino para grafos (posiblemente) cı́clicos
como el del ejemplo (la idea es guardar los nodos visitados para impedir los recorridos
cı́clicos).
b) Desarrollar el árbol de búsqueda para el objetivo camino(g,c).
c) ¿Como se podrı́a determinar si hay un camino entre g y c que no pase por f utilizando
el programa anterior?
d) Extender la definción de camino para que, en el caso de que haya camino entre dos
nodos dados, devuelva además una lista con los nodos que forman dicho camino.
3. Escribir un predicado bin(N,L) que dado el entero (positivo) N , calcule en la lista L la
representación binaria de dicho número. Hacer la conversión inversa (de binario a decimal).
4. La forma más directa de representar una matriz de dimension N ×M en prolog es mediante
una lista (de longitud N ) de listas (de longitud M ). Ası́ por ejemplo, la matriz:


1 2 3
 4 5 6 
7 8 9
se representarı́a como [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ].
Escribir un predicado que calcule la traspuesta de una matriz dada.
5. Consideremos los árboles binarios de búsqueda representados como vacio (árbol vacı́o) y
arbol(HijoIzq,Raiz,HijoDer) y el predicado de inserción de un elemento visto en clase. Se
pide:
a) Escribir un predicado cons(L,A) que tome como entrada una lista de enteros L y
construya el árbol A resultante de insertar cada uno de los elementos de dicha lista
en un árbol vacı́o. Por ejemplo, el objetivo cons([6,3,4,2,8,1],A) debe producir A
= arbol(arbol(arbol(arbol(vacio, 1, vacio), 2, vacio), 3, arbol(vacio, 4, vacio)), 6,
arbol(vacio, 8, vacio))
b) Prolog proporciona un amplio repertorio de predicados de entrada/salida. En este
ejercicio nos interesa el predicado write(T) que escribe en pantalla el término T ,
tab(N) que escribe en pantalla N espacios en blanco y el predicado nl que escribe un
salto de lı́nea. Se pide programar un predicado escribe(A) que muestre en pantalla
el árbol A en un formato “legible”. Por ejemplo, el del apartado anterior se quedarı́a
como:
8
6
4
3
2
1
La idea es rotar el árbol de modo que la raiz quede a la izquierda y escribir el
hijo derecho por encima y el izquierdo por debajo. Además cada nodo se indenta
horizontalmente dependiendo de la profundidad que tenga en el árbol.
6. Una lista puede empaquetarse mediante otra lista de pares elemento/multiplicidad de modo
que la multiplicidad indica el número de apariciones consecutivas del elemento. Ası́ por
ejemlo, la lista [a, a, a, b, b, a, a, c, c, c, c] queda empaquetada como [a : 3, b : 2, a : 2, c : 4].
Se piden dos predicados:
empaqueta(+L,-Le)::= devuelve en Le el empaquetado correspondiente a la lista de
entrada L.
desempaqueta(+Le,-L)::= realiza la operación inversa con la lista empaquetada Le.
7. Supongamos que codificamos el stock de una tienda de software mediante una lista de elementos de la forma articulo(identificador, cantidad). Por ejemplo, la lista [articulo(windowsXP,0),
articulo(ubuntu,114), articulo(explorer,0),articulo(swiprolog, 37), articulo(windowsXP,0),
articulo(ubuntu,6)] indicarı́a que disponemos de un stock con 0 cd’s de windows XP, 114
cd’s de ubuntu, 0 cd’s de internet explorer, 37 cd’s de swi prolog, 0 cd’s de windowsXP y
6 cd’s de ubuntu.
A la vista de este ejemplo, se aprecia que esta representación puede compactarse sumando
las cantidades de los artı́culos disponibles y eliminando aquellos cuya cantidad (acumulada)
es 0. En nuestro ejemplo, al compactar obtendrı́amos [articulo(ubuntu,120),articulo(swiprolog,37)].
Implementar un predicado para compactar stocks.
8. Los multiconjuntos (conjuntos que admiten repetición de elementos) pueden representarse
en Prolog como una lista de la forma [. . . , E : N, . . .] donde E es el elemento y N el número
de veces que aparece. Ası́ el multiconjunto { {1, 2, 3, 4, 3, 3, 4, 4, 3, 3, 5, 6, 7, 8, 7, 6, 5, 4} } se
representa como [1 : 1, 2 : 1, 3 : 5, 4 : 4, 5 : 2, 6 : 2, 7 : 2, 8 : 1]. Se pide:
a) Escribir un predicado añade para insertar un elemento en un multiconjunto.
b) Escribir un predicado que convierta una lista dada (posiblemente con elementos
repetidos) en un multiconjunto.
c) Escribir un predicado que devuelva la multiplicidad (número de apariciones) de un
elemento en un multiconjunto .
9. Implementar un programa Prolog para obtener soluciones al problema de colocar (todas)
las fichas del dominó en secuencia de modo que casen dos a dos (en la terminologı́a habitual
del dominó).
10. Las expresiones aritméticas se pueden escribir en notación postfija sin necesidad de paréntisis ni ningún otro tipo de delimitador. Por ejemplo, la expresión (3 + 4) ∗ ((6 − 2)/1), en
notación postfija es 3 4 + 6 2 − 1 / ∗.
La evaluación de este tipo de expresiones puede hacerse fácilmente utilizando una pila. La
expresión se procesa de izquierda a derecha: cada vez que se encuentra un operando se
apila, cuando se encuentra un operador se aplica a los dos primeros operandos de la pila (la
cima y el siguiente) y el resultado se apila nuevamente. Si la expresión es correcta, al final
del proceso se habrá consumido toda la expresión y la pila contendrá un único elemento
con el resultado de la evaluación.
Se pide implementar un predicado eval(L,V) que tome como input una lista de operadores/operandos que representan la expresión postfija y devuelva el valor de su evaluación. Por ejemplo, para la expresión anterior eval([3,4,+,6,2,-,1,/,*],V). deberı́a dar la
respuesta V = 28.

Documentos relacionados