Está en la página 1de 13

LABORATORIO NRO 02 1

PROLOG
Prolog1: Hechos y Reglas
1. El siguiente fragmento incluye un conjunto de declaraciones bsicas sobre
una familia y una regla que indica si X es progenitor de Y:
progenitor(fernando ,juan).
progenitor(luisa ,juan).
progenitor(luisa ,maria).
progenitor(luisa ,diego).
progenitor(fernando ,pepe).
progenitor (pepe , pedro ).
progenitor(pedro ,ana).
progenitor (pedro , belen ).
hombre(juan ).
hombre(fernando ).
hombre ( pepe ) .
hombre( diego ).
hombre(pedro ).
mujer( luisa ).
mujer ( pepa ) .
mujer( belen ).
mujer(ana).
Compilar el programa y realizar las siguientes consultas:
a) Se cumple que fernando es el progenitor de pepe?
b) Hay alguien que sea progenitor de ana?
c)Hay alguien que sea progenitor de fernando?
d) Hay alguien que sea a la vez progenitor de pepe y de juan?

2. Los siguientes fragmentos declaran una regla que indica si X es el padre de Y,


y una regla que indica si X es abuelo de Y:
padre(X,Y):progenitor (X,Y) ,hombre(X).
abuelo( X, Y) : progenitor ( X, Z ) , progenitor ( Z , Y ) , hombre ( X ) .
Declarar reglas familiares para:
a) madre
b) hermano
c) hijo
1

Escuela Prof. De Ingeniera de Sistemas UNSA- M.Sc. Carlo Corrales


d) hermana
e) abuela
f) tio

3. Definir un predicado que indique si X es un antepasado de Y

Prolog2: Listas
Una lista est vacia o est compuesta por un primer elemento
(head) y una cola la cual es una lista adems.. En Prolog
representamos la lista vacia por el tomo [] y una lista no vaca por
el trmino [H|T] donde H denota la cabeza y T denota la cola.
1.01 (*) Encontrar el ultimo elemento de una lista.
Ejemplo:
?- my_last(X,[a,b,c,d]).
X=d
1.02 (*) Encontrar el penultimo elemento de una lista.
1.03 (*) Encontrar el K-esimo elemento de una lista.
El primer elemento en la lista es el nmero 1.
Ejemplo:
?- element_at(X,[a,b,c,d,e],3).
X=c
1.04 (*) Encontrar el nmero de elementos de una lista.
1.05 (*) Invertir una lista.
1.06 (*) Descubrir si una lista es un palindrome.
Un palindrome puede ser leido de adelante hacia atras o atrs hacia
adelante
; p.e. [x,a,m,a,x].
1.07 (**) Aplanar una lista de listas.
Transformar una lista, posiblemente manteniendo listas como
elementos dentro de una lista plana, reemplazando cada lista con
2

LABORATORIO NRO 02 3

sus elementos recursivamente.


Ejemplo:
?- my_flatten([a, [b, [c, d], e]], X).
X = [a, b, c, d, e]
Tip: Use los predicados predefinidos is_list y append
1.08 (**) Eliminar duplicados consecutivos de una lista de
elementos.
Si una lista contiene elementos repetidos, sern reemplazados con
una copia Simple del elemento. El orden de los elementos no debe
cambiar.
Ejemplo:
?- compress([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X).
X = [a,b,c,a,d,e]
1.09 (**) Empaquetar duplicados consecutivos de una lista de
elementos dentro de sublistas.
Si una lista contiene elementos repetidos, deben ser reemplazados
en sublistas separadas.
Ejemplo:
?- pack([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X).
X = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]]
1.10 (*) Llevar la cuenta de los elementos repetidos en una lista.
Use el resultado del problema 1.09 para implementar el llevar la
cuenta de los elementos repetidos en una lista, como mtodo de
compression de datos.
Los duplicados consecutivos son contados como trminos [N,E]
donde N es el nmero de duplicados del elemento E.
Ejemplo:
?- encode([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X).
X = [[4,a],[1,b],[2,c],[2,a],[1,d][4,e]]
1.11 (*) Llevar la cuenta de los elementos repetidos, menos los
que sean nicos.
Modifica el resultado del problema 1.10 de tal manera que si un
elemento no tiene duplicados, ste es simplemente copiado en la
lista resultado. Solo los elementos con duplicados son transferidos
3

Escuela Prof. De Ingeniera de Sistemas UNSA- M.Sc. Carlo Corrales

como terminos [N,E].


Ejemplo:
?- encode_modified([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X).
X = [[4,a],b,[2,c],[2,a],d,[4,e]]
1.12 (**) Decodificar el llevar la cuenta de elementos repetidos.
Dado el algoritmo de llevar la cuenta, generado en el problema
1.11, Construye su version descomprimida.
1.13 (**) Ejecutar el llevar la cuenta de elementos repetidos de
una lista (solucin directa)
Implementa la compresion de datos de llevar cuenta de elementos
repetidos directamente. Es decir, no crear explicitamente las
sublistas conteniendo los duplicados, como en el problema 1.09,
sino solo contarlos. Como en el problema 1.11, simplifica la lista
resultado reemplazando los terminus simples [1,X] por X.
Ejemplo:
?- encode_direct([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X).
X = [[4,a],b,[2,c],[2,a],d,[4,e]]
1.14 (*) Duplicar elementos de una lista.
Ejemplo:
?- dupli([a,b,c,c,d],X).
X = [a,a,b,b,c,c,c,c,d,d]
1.15 (**) Duplicar los elementos de una lista un nro
determinado de veces.
Ejemplo:
?- dupli([a,b,c],3,X).
X = [a,a,a,b,b,b,c,c,c]
Cual es el resultado de la meta?:
?- dupli(X,3,Y).
1.16 (**) Elimina cada N-esimo elemento de la lista.
Ejemplo:
?- drop([a,b,c,d,e,f,g,h,i,k],3,X).
X = [a,b,d,e,g,h,k]
1.17 (*) Divide una lista en 2 partes; dada la longitud de la
primera parte
4

LABORATORIO NRO 02 5

No uses ningun predicado predefinido.


Ejemplo:
?- split([a,b,c,d,e,f,g,h,i,k],3,L1,L2).
L1 = [a,b,c]
L2 = [d,e,f,g,h,i,k]
1.18 (**) Divide un trozo de una lista.
Dados 2 indices, I y K, la division es la lista que contiene los
elementos entre el i-esimo y el k-esimo elemento de la lista
original (ambos lmites incluidos). Empieza a contra los elementos
en 1.
Ejemplo:
?- slice([a,b,c,d,e,f,g,h,i,k],3,7,L).
L = [c,d,e,f,g]
1.19 (**) Rota una lista N lugares a la izquierda.
Ejemplos:
?- rotate([a,b,c,d,e,f,g,h],3,X).
X = [d,e,f,g,h,a,b,c]
?- rotate([a,b,c,d,e,f,g,h],-2,X).
X = [g,h,a,b,c,d,e,f]
Tip: Usa el predicado predefinido length y append, asi como el
resultado del problema 1.17.
1.20 (*) Elimina el K-esimo elemento de una lista.
Ejemplo:
?- remove_at(X,[a,b,c,d],2,R).
X=b
R = [a,c,d]
1.21 (*) Inserta un elemento en una posicion dada dentro de
una lista.
Ejemplo:
?- insert_at(alfa,[a,b,c,d],2,L).
L = [a,alfa,b,c,d]
1.22 (*) Crea una lista que contenga todos los nros enteros
dentro de un rango.
Ejemplo:
5

Escuela Prof. De Ingeniera de Sistemas UNSA- M.Sc. Carlo Corrales

?- range(4,9,L).
L = [4,5,6,7,8,9]
1.23 (**) Extraer un nro dado de elementos seleccionados al
azar de una lista.
Los items seleccionados deben ser colocados en la lista resultado.
Ejemplo:
?- rnd_select([a,b,c,d,e,f,g,h],3,L).
L = [e,d,a]
Tip: Use el generador de nros aleatorios random y los resultados
del problema 1.20.
1.24 (*) Lotto: Dibuje N diferentes nros aleatorios de un
conjunto 1..M.
Los nros seleccionados deben ser colocados en la lista resultado.
Ejemplo:
?- rnd_select(6,49,L).
L = [23,1,17,33,21,37]
Tip: Combine las soluciones de los problemas 1.22 y 1.23.
1.25 (*) Genere una permutacion aleatoria de elementos de una
lista.
Ejemplo:
?- rnd_permu([a,b,c,d,e,f],L).
L = [b,a,d,c,e,f]
Tip: Use la solucion del problema 1.23.
1.26 (**) Genere las combinaciones de K distintos objectos
escogidos de N elementos de una lista.
En cuantas formas puede un comit de 3 ser escogido de un grupo
de 12 personas? Todos sabemos que hay C(12,3) = 220
posibilidades (C(N,K) denota el conocido coeficiente polinomial).
Para los matemticos este resultado puede ser maravilloso. Pero
nosotros queremos generar todas las posibilidades (via
backtracking).
Ejemplo:
?- combination(3,[a,b,c,d,e,f],L).
L = [a,b,c] ;
L = [a,b,d] ;
6

LABORATORIO NRO 02 7

L = [a,b,e] ;
...
1.27 (**) Agrupe los elementos de un conjunto en subconjuntos
disjuntos.
a) En cuantas maneras puede un grupo de 9 trabajar en 3
subgrupos disjuntos de 2, 3 y 4 personas? Escribe un predicado que
genere todas las posibilidades via backtracking.
Ejemplo:
?- group3([aldo,beat,carla,david,evi,flip,gary,hugo,ida],G1,G2,G3).
G1 = [aldo,beat], G2 = [carla,david,evi], G3 = [flip,gary,hugo,ida]
...
b) Generalice el predicate de la parte a) de tal forma que podamos
especificar una lista de tamaos de grupos y el predicado retorne
una lista de grupos.
Ejemplo:
?- group([aldo,beat,carla,david,evi,flip,gary,hugo,ida],[2,2,5],Gs).
Gs = [[aldo,beat],[carla,david],[evi,flip,gary,hugo,ida]]
...
Note que no queremos permutaciones de miembros del grupo; es
decir [[aldo,beat],...] es la misma solucion que [[beat,aldo],...]. Sin
embargo, hacemos una diferencia entre [[aldo,beat],[carla,david],...]
y [[carla,david],[aldo,beat],...].
Encontraras mas sobre problemas combinatorios en un buen libro
de matematicas discretas bajo el trmino coeficientes
multinomiales.
1.28 (**) Ordenar una lista de listas de acuerdo a la longitud de
las sublistas
a) Suponemos que una lista (InList) contiene elementos que son
tambien listas. El objetivo es ordenar los elementos de InList de
acuerdo a su longitud.
Por ejemplo, las listas cortas al inicio, las mas largas luego, o vice
versa.
Ejemplo:
?- lsort([[a,b,c],[d,e],[f,g,h],[d,e],[i,j,k,l],[m,n],[o]],L).
L = [[o], [d, e], [d, e], [m, n], [a, b, c], [f, g, h], [i, j, k, l]]
7

Escuela Prof. De Ingeniera de Sistemas UNSA- M.Sc. Carlo Corrales

b) Nuevamente, suponemos que una lista (InList) contienen


elementos que son tambien listas. Pero esta vez el objetivo es
ordenar los elementos de InList de acuerdo a su frecuencia de
longitud; es decir, por defecto, donde ordenar es realizado
ascendentemente, las listas con longitudes mas escasas son
colocados al inicio, otras con longitudes ms frecuentes vendras
luego.
Ejemplo:
?- lfsort([[a,b,c],[d,e],[f,g,h],[d,e],[i,j,k,l],[m,n],[o]],L).
L = [[i, j, k, l], [o], [a, b, c], [f, g, h], [d, e], [d, e], [m, n]]
Note que en el ejemplo anterior, las primeras 2 listas en el
resultado L tienen logitudes de 4 y 1, ambas longitudes aparecen
solamente una vez. La 3ra y 4ta listas tienen longitud 3, hay 2 listas
de su longitud. Y finalmente las 3 listas tienen longitud 2. Esta es
la cantidad de elementos mas frecuentes.

Prolog3: Aritmtica
2.01 (**) Determinar si un nmero entero dado es primo.
Ejemplo:
?- is_prime(7).
Yes
2.02 (**) Determinar los factores primos de un entero positivo
dado.
Construya una lista plana que contenga los factores primos en
rden ascendente.
Ejemplo:
?- prime_factors(315, L).
L = [3,3,5,7]
2.03 (**) Determinar los factores primos de un entero positivo
dado (2).
Construya una lista que contenga los factores primos y su
multiplicidad.
Ejemplo:
?- prime_factors_mult(315, L).
8

LABORATORIO NRO 02 9

L = [[3,2],[5,1],[7,1]]
Tip: La solucion del problema 1.10 puede ser de ayuda.
2.04 (*) Una lista de nmeros primos.
Dado un rango de enteros por sus lmites inferior y superior,
construya una lista de todos los nmeros primos en este rango.
2.05 (**) La conjetura de Goldbach.
La conjetura de Goldbach dice que cada nmero positivo par mayor
a 2 es la suma de 2 nmeros primos. Ejemplo: 28 = 5 + 23. Es uno
de los ms Famosos hechos en la teoria de nmeros que no ha
podido ser probado en el caso general. Ha sido numricamente
confirmado hasta un nmero bastante grande (mucho mayor que
lo que podemos calcular con el Prolog). Escribir un predicado para
allar 2 nros primos que sumen un nmero entero par dado.
Ejemplo:
?- goldbach(28, L).
L = [5,23]
2.06 (**) Una lista de las composiciones Goldbach.
Dado un rango de enteros por sus lmites inferior y superior,
imprimir una lista de todos los nmeros pares y su composicin
Goldbach.
Ejemplo:
?- goldbach_list(9,20).
10 = 3 + 7
12 = 5 + 7
14 = 3 + 11
16 = 3 + 13
18 = 5 + 13
20 = 3 + 17
En la mayora de los casos, si un nmero par est escrito como la
suma de 2 nmeros primos, uno de ellos es bastante pequeo.
Raramente los primos son ambos grandes mayores digamos que
50. Trata de hallar cuantos de esos casos hay en el rango de
1..2000.
Ejemplo (para un lmite de 50):
?- goldbach_list(1,2000,50).
992 = 73 + 919
9

Escuela Prof. De Ingeniera de Sistemas UNSA- M.Sc. Carlo Corrales

1382 = 61 + 1321
1856 = 67 + 1789
1928 = 61 + 1867
2.07 (**) Determinar el MCD de 2 enteros positivos.
Use el algoritmo de Euclides.
Ejemplo:
?- gcd(36, 63, G).
G=9
Defina gcd como una funcin aritmtica; as puedes usarla de esta
manera:
?- G is gcd(36,63).
G=9
2.08 (*) Determinar si 2 nmeros enteros positivos son
coprimos.
Dos nmeros son coprimos si su MCD es 1.
Ejemplo:
?- coprime(35, 64).
Yes
2.09 (**) Calcular la funcin totient de Euler phi(m).
La funcin de Euler's es definida como el nmero de enteros
positivos r (1 <= r < m) que son coprimos con m.
Ejemplo: m = 10: r = 1,3,7,9; as phi(m) = 4. Note el caso especial:
phi(1) = 1.
?- Phi is totient_phi(10).
Phi = 4
Descubra cual es el valor de phi(m) si m es un nmero primo. La
funcin totient de Euler juega un importante rol en uno de los ms
amplios mtodos criptogrficos de clave pblica (RSA). En este
ejercicio debes usar el mtodo ms primitivo para calcular esta
funcin. Hay una manera interesante que deberas usar al resolver
el problema 2.10.
2.10 (**) Calcula la funcin totient de Euler phi(m) (2).
Mira el problema 2.09 para la definicin de la funcin totient de
Euler. Si la lista de factores primos de un nmero m es conocida en
la forma del problema 2.03 entonces la funcin phi(m) puede ser
10

1
LABORATORIO NRO 02 1

calculada eficientemente como sigue:


Sea [[p1,m1],[p2,m2],[p3,m3],...] la lista de factores primos (y sus
multiplicidades) de un nmero dado m. Entonces phi(m) puede ser
calculado con la siguiente frmula:
phi(m) = (p1 - 1) * p1**(m1 - 1) * (p2 - 1) * p2**(m2 - 1) * (p3 - 1)
* p3**(m3
- 1) * ...
Note que a**b indica a elevado a la potencia de b.
2.11 (*) Compare los 2 metodos de calcular la funcion totient de
Euler.
Use las soluciones de los problemas 2.09 y 2.10 para comparar los
algoritmos.
Tome el nmero de inferencias lgicas como una medida de
eficiencia. Trate de calcular phi(10090) como Ejemplo.

Prolog4: Lgica y Cdigos


3.01 (**) Tablas de Verdad para expresiones lgicas.
Definir predicados and/2, or/2, nand/2, nor/2, xor/2, impl/2 y
equ/2 (para equivalencias lgicas) los cuales se satisfacen o fallan
de acuerdo al resultado de sus respectivas operaciones; por
ejemplo and(A,B) ser satisfecha, si y solo si ambos A y B se
satisfacen. Note que A y B pueden ser metas de Prolog (no solo las
constantes true y fail).
Una expression lgica en 2 variables puede ser escrito en notacin
prefija, como en el siguiente ejemplo: and(or(A,B),nand(A,B)).
Ahora, escribe un predicado table/3 el cual imprima la tabla de
verdad de una expresin lgica dada en 2 variables.
Ejemplo:
?- table(A,B,and(A,or(A,B))).
true true true
true fail true
11

Escuela Prof. De Ingeniera de Sistemas UNSA- M.Sc. Carlo Corrales

fail true fail


fail fail fail
3.02 (*) Tablas de verdad para expresiones lgicas (2).
Continuar con el problema 3.01 definiendo and/2, or/2, etc como
operadores.
Esto permite escribir las expresiones lgicas en una manera ms
natural, como en el ejemplo: A and (A or not B). Definir el operador
de precedencia como es usual, es decir como es en Java.
Ejemplo:
?- table(A,B, A and (A or not B)).
true true true
true fail true
fail true fail
fail fail fail
3.03 (**) Tablas de verdad para expresiones lgicas (3).
Generalizar el problema 3.02 en tal manera que las expresiones
lgicas puedan contener cualquier nmero de variables lgicas.
Definir table/2 de tal manera que table(List,Expr) imprima la tabla
de verdad para la expresin Expr, la cual contiene las variables
lgicas enumeradas en una Lista.
Ejemplo:
?- table([A,B,C], A
true true true
true true fail
true fail true
true fail fail
fail true true
fail true fail
fail fail true
fail fail fail

and (B or C) equ A and B or A and C).


true
true
true
true
true
true
true
true

3.04 (**) El cdigo Gray.


Un cdigo Gray de n-bit es una secuencia de cadenas de n-bits
construido de acuerdo a ciertas reglas. Por Ejemplo,
n = 1: C(1) = ['0','1'].
n = 2: C(2) = ['00','01','11','10'].
n = 3: C(3) = ['000','001','011','010','110','111','101','100'].
12

1
LABORATORIO NRO 02 3

Descubrir las reglas de construccin y escribir un predicado con las


siguientes especificaciones:
% gray(N,C) :- C es el cdigo Gray de N-bits
Se puede aplicar el mtodo de "result caching" para hacer el
predicado ms eficiente, cuando se usar repetidamente?
3.05 (***) El Cdigo Huffman.
Primero que todo, estudiar un buen libro de matemticas discretas
o algoritmos
para una descripcin detallada del cdigo Huffman, o consulta
Wikipedia
Suponemos un conjunto de smbolos con sus frecuencias, dada
como una lista
de terminos fr(S,F). Ejemplo:
[fr(a,45),fr(b,13),fr(c,12),fr(d,16),fr(e,9),fr(f,5)]. Nuestro objetivo es
construir
una lista de trminos hc(S,C), donde C es el Cdigo Huffman para el
smbolo S.
En nuestro Ejemplo, el resultado puede ser Hs = [hc(a,'0'),
hc(b,'101'), hc(c,'100'),
hc(d,'111'), hc(e,'1101'), hc(f,'1100')] [hc(a,'01'),...etc.]. La tarea
debe ser
implementar el predicado huffman/2 definido de la siguiente
manera:
% huffman(Fs,Hs) :- Hs es la tabla de cdigos Huffman para la tabla
de frecuencias Fs.

13

También podría gustarte