Docsity
Docsity

Prepara tus exámenes
Prepara tus exámenes

Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity


Consigue puntos base para descargar
Consigue puntos base para descargar

Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium


Orientación Universidad
Orientación Universidad


Programación Práctica - Apuntes - Fundamentos De Programación, Apuntes de Programación de Ordenadores

Apuntes del curso universitario de Fundamentos de Programación sobre la Programación Práctica - Teoría y Hechos

Tipo: Apuntes

2011/2012

Subido el 25/09/2012

pedrito46
pedrito46 🇪🇸

4.4

(186)

63 documentos

1 / 35

Toggle sidebar

Esta página no es visible en la vista previa

¡No te pierdas las partes importantes!

bg1
docsity.com
Programación Práctica
Tabla de Contenidos
1 Introducción _________________________________________________________ 3
2 Hechos ______________________________________________________________ 3
3 Reglas ______________________________________________________________ 3
3.1 Reglas simples______________________________________________________ 3
3.2 Reglas con Variables _________________________________________________ 4
3.3 Reglas Recursivas ___________________________________________________ 4
3.4 Utilización de funciones _______________________________________________ 4
3.5 Datos Compuestos ___________________________________________________ 4
4 Unificación __________________________________________________________ 4
5 Listas _______________________________________________________________ 6
5.1 Definición _________________________________________________________ 6
5.2 Recorrer una lista ____________________________________________________ 6
5.3 Recorrer una lista tomando elementos de dos en dos___________________________ 7
5.4 Búsqueda de elementos en una lista_______________________________________ 7
5.5 Generación de una lista mediante concatenación de otras dos ____________________ 8
5.6 Descomposición de una lista en partes_____________________________________ 8
5.7 Generación de una lista filtrando elementos de otra lista ________________________ 9
5.8 Aplicación de un predicado a todos los elementos ____________________________ 9
5.9 Permutaciones de una lista _____________________________________________ 9
6 Aritmética ___________________________________________________________ 9
7 Aritmética con Listas _________________________________________________ 11
7.1 Obtener un valor a partir de una lista _____________________________________ 11
7.2 Acumulación de Resultados ___________________________________________ 11
7.3 Combinación miembro a miembro de los elementos de dos listas ________________ 11
7.4 Generación de una lista a partir de un valor ________________________________ 11
7.5 Generación de listas por filtrado de elementos ______________________________ 12
7.6 Clasificación de listas________________________________________________ 12
7.7 Creación de otra estructura a partir de una lista______________________________ 13
7.8 Otras Estructuras Recursivas___________________________________________ 13
8 Predicados Internos __________________________________________________ 14
8.1 Conversión de tipos _________________________________________________ 14
8.2 Chequeo de tipos ___________________________________________________ 14
8.3 Inspección de estructuras _____________________________________________ 15
8.4 Predicados meta-lógicos ______________________________________________ 16
8.4.1 Chequeo de tipo___________________________________________________________ 16
8.4.2 Comparación de términos no básicos ___________________________________________ 16
8.4.3 Conversión de Datos en Objetivos _____________________________________________ 17
8.5 Corte____________________________________________________________ 18
8.5.1 Aplicaciones del Corte ______________________________________________________ 18
8.6 Predicados Extra-lógicos _____________________________________________ 21
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23

Vista previa parcial del texto

¡Descarga Programación Práctica - Apuntes - Fundamentos De Programación y más Apuntes en PDF de Programación de Ordenadores solo en Docsity!

Programación Práctica

  • 1 Introducción _________________________________________________________ Tabla de Contenidos
  • 2 Hechos ______________________________________________________________
  • 3 Reglas ______________________________________________________________
  • 3.1 Reglas simples______________________________________________________
  • 3.2 Reglas con Variables _________________________________________________
  • 3.3 Reglas Recursivas ___________________________________________________
  • 3.4 Utilización de funciones _______________________________________________
  • 3.5 Datos Compuestos ___________________________________________________
  • 4 Unificación __________________________________________________________
  • 5 Listas _______________________________________________________________
  • 5.1 Definición _________________________________________________________
  • 5.2 Recorrer una lista ____________________________________________________
  • 5.3 Recorrer una lista tomando elementos de dos en dos___________________________
  • 5.4 Búsqueda de elementos en una lista_______________________________________
  • 5.5 Generación de una lista mediante concatenación de otras dos ____________________
  • 5.6 Descomposición de una lista en partes_____________________________________
  • 5.7 Generación de una lista filtrando elementos de otra lista ________________________
  • 5.8 Aplicación de un predicado a todos los elementos ____________________________
  • 5.9 Permutaciones de una lista _____________________________________________
  • 6 Aritmética ___________________________________________________________
  • 7 Aritmética con Listas _________________________________________________
  • 7.1 Obtener un valor a partir de una lista _____________________________________
  • 7.2 Acumulación de Resultados ___________________________________________
  • 7.3 Combinación miembro a miembro de los elementos de dos listas ________________
  • 7.4 Generación de una lista a partir de un valor ________________________________
  • 7.5 Generación de listas por filtrado de elementos ______________________________
  • 7.6 Clasificación de listas________________________________________________
  • 7.7 Creación de otra estructura a partir de una lista______________________________
  • 7.8 Otras Estructuras Recursivas___________________________________________
  • 8 Predicados Internos __________________________________________________
  • 8.1 Conversión de tipos _________________________________________________
  • 8.2 Chequeo de tipos ___________________________________________________
  • 8.3 Inspección de estructuras _____________________________________________
  • 8.4 Predicados meta-lógicos ______________________________________________
  • 8.4.1 Chequeo de tipo___________________________________________________________
  • 8.4.2 Comparación de términos no básicos ___________________________________________
  • 8.4.3 Conversión de Datos en Objetivos _____________________________________________
  • 8.5 Corte____________________________________________________________
  • 8.5.1 Aplicaciones del Corte ______________________________________________________
  • 8.6 Predicados Extra-lógicos _____________________________________________

8.6.1 Entrada/Salida ____________________________________________________________ 21 8.6.2 Acceso a la Base de Datos ___________________________________________________ 23

8.7 Predicados de Segundo Orden__________________________________________ 24

9 Ejercicios Propuestos _________________________________________________ 25

10 Bibliografía Comentada _______________________________________________ 28

11 Indice ______________________________________________________________ 30

Programación Práctica en Prolog Chequeo de tipo 3

1 Introducción Con estos apuntes se muestran las diferentes características del núcleo del lenguaje Prolog mediante sencillos ejemplos. Se ha realizado un tratamiento especial a las listas y a los diversos esquemas recursivos para trabajar con listas. El objetivo es ayudar al lector a identificar esquemas de programación que puedan servirle para resolver problemas similares. No se ha pretendido realizar una guía detallada sino una presentación práctica informal del lenguaje. El lector que esté interesado en profundizar en el lenguaje, deberá consultar los libros de la bibliografía. Con el fin de facilitar la lectura, se utilizan los siguientes símbolos: Clave: 4 Punto importante a recordar

. Posibles ejercicios Comentarios avanzados ( Notas sobre portabilidad En la presentación de ejemplos se utiliza una tabla escribiendo el código y las preguntas en la parte izquierda y los comentarios en la parte derecha.

2 Hechos /* Relacion Progenitor */ progenitor(pilar,belen). progenitor(tomas,belen). progenitor(tomas,lucia). progenitor(belen,ana). progenitor(belen,pedro). progenitor(pedro,jose). progenitor(pedro,maria). Se describen una serie de hechos conocidos sobre una familia. 4 Sintaxis de Prolog: Constantes y predicados empiezan por minúscula. Los hechos acaban en punto. Variables comienzan por mayúscula. El programa anterior debe ser cargado en el sistema. Una vez cargado, es posible realizar preguntas: | ?- progenitor(pilar,belen). Yes El sistema puede responder: 1.-Yes: Se puede deducir y el objetivo no tiene variables. | ?- progenitor(pilar,lucia). No 2.-No: No puede deducir a partir del programa La respuesta No indica que no se puede deducir. En la vida real, podría ocurrir que pilar fuese madre de lucía (parece lo más lógico) pero el sistema supone que todo lo que no está declarado es falso 1 | ?- progenitor(belen,X). X = ana ; X = pedro 3.- Substitución de Respuesta: Se puede deducir y el objetivo tiene variables. Se indica el valor que toman las variables en la resolución del objetivo. En caso de que haya más de una solución. Cuando el

Téngase en cuenta que a la hora de resolver la pregunta madre(belen,X) con la cabeza de la regla madre(X,Y) es necesario renombrar la variable X El lenguaje Prolog realiza internamente un proceso de unificación que se describe en la página 4.

3.3 Reglas Recursivas

antepasado(X,Y):-progenitor(X,Y). antepasado(X,Y):-progenitor(X,Z), antepasado(Z,Y). En general, en una definición recursiva, es necesario considerar 2 casos: Caso básico : Momento en que se detiene la computación Caso Recursivo : Suponiendo que ya se ha solucionado un caso más simple, cómo descomponer el caso actual hasta llegar al caso simple. 4 Tanto el caso básico como el caso recursivo no tienen porqué ser únicos (puede haber varios casos básicos y varios casos recursivos) | ?- antepasado(belen,X). X = ana ; X = pedro ; X = jose ; X = maria ; no | ?- antepasado(X,belen). X = pilar ; X = tomas ; no Las definiciones recursivas se resuelven de la misma forma que las reglas comunes. En la traza de este tipo de definiciones tiene especial importancia el renombramiento de variables. Considerando la relación progenitor como un enlace entre dos nodos de un grafo. La relación antepasado indicaría si hay camino entre dos nodos del grafo dirigido acíclico formado por la relación progenitor. Este tipo de relaciones se utiliza en diversos contextos como la búsqueda de caminos entre ciudades, la simulación de movimientos de un autómata, etc.

. Describir en Prolog una serie de caminos entre diversas ciudades y construir un predicado que indique 2 Se dice que una variable está instanciada si tiene un valor concreto (en realidad ya no sería una variable) Programación Práctica en Prolog Chequeo de tipo 5 si 2 ciudades están conectadas.

3.4 Utilización de funciones

grande(pepe). grande(cabeza(juan)). grande(X):-mayor(X,Y). mayor(cabeza(X),cabeza(Y)):- progenitor(X,Y). Se utiliza la función: cabeza(x)=”cabeza de x” El programa indica: “Pepe es grande, la cabeza de juan es grande, si X es mayor que Y, entonces X es grande, además: La cabeza de X es mayor que la de Y si X es el progenitor de Y” 4 Prolog no necesita declaraciones de tipos. | ?- grande(X).

X = pepe ; X = cabeza(juan) ; X = cabeza(pilar) ; X = cabeza(tomas) ; ... 4 Las variables en Prolog no tienen tipo, de ahí que la respuesta X puede ser una persona ( pepe ) o una cabeza ( cabeza(juan) )

3.5 Datos Compuestos

horizontal(seg(punto(X,Y), punto(X1,Y))). vertical(seg(punto(X,Y), punto(X,Y1))). punto(X,Y) representa un punto de coordenadas (x,y) seg(p1,p2) representa un segmento cuyos extremos son los puntos p1 y p Los argumentos de una función pueden ser funciones | ?- horizontal(seg(punto(1,2),punto(3,2))). Yes | ?- horizontal(seg(punto(1,2),P)). P = punto(_47796,2) | ?- horizontal(P),vertical(P). P=seg(punto(_29128,_29130),punto(_29128,_29130) ) P = punto(_47796,2) indica que P es un punto cuya primera coordenada es una variable sin instanciar 3 y cuya segunda coordenada es 2 La última respuesta indica que para que un segmento sea vertical y horizontal a la vez, sus coordenadas deben ser las mismas (los números de las variables X e Y coinciden)

4 Unificación

Durante la resolución de objetivos, el sistema Prolog debe realizar la unificación entre los objetivos y las cabezas de las reglas o los hechos. De forma simplificada, el algoritmo de unificación consiste en: 1.- Inicializar = substitución vacía 2.- Si al aplicar a las 2 expresiones, éstas son iguales, finalizar y devolver  3.- Buscar de izquierda a derecha las primeras subexpresiones diferentes: Si dichas subexpresiones están formadas por una variable v y un término t (tal que vÏ t ) 4

Actualizar con el resultado de substituir v por t Volver a 2 En caso contrario Finalizar indicando que las expresiones no unifican | ?- f(X,X)=f(a,Y). X = a Y = a | ?- f(X,X)=f(a,Y). no | ?- p(f(X),g(Z,X))=p(Y,g(Y,a)). X = a , Z = f(a) El operador ‘=’ se cumple si sus argumentos unifican. El operador ‘=’ se cumple si sus argumentos no unifican. Puesto que Prolog no tiene chequeo de ocurrencias, se produce un error. 3 El formato de las variables sin instanciar varía de un sistema Prolog a otro. En estos apuntes, se utiliza un número de 4 dígitos aleatorio precedido del carácter ‘_’ 4 La condición vÏ t se conoce como chequeo de ocurrencias ( occur check ) y no es implementada por la mayoría

4 La llamada lista(X) genera por backtracking listas de cualquier tipo de elementos.

5.2 Recorrer una lista

hombres([]). hombres([X|Xs]):-hombre(X), hombres(Xs). noPertenece(X,[]). noPertenece(X,[Y|Ys]):-X=Y, noPertenece(X,Ys). | ?- hombres([jose,tomas,pedro]). yes | ?- hombres([jose,pilar,tomas]). hombres(Xs) :- Todos los X de Xs cumplen hombre(X) noPertenece(X,Xs) :- El elemento X no pertenece a la lista Xs (se comprueba que no unifica con ningún elemento de Xs En las definiciones recursivas, conviene escribir el caso básico antes que el caso recursivo ya que si la definición unifica con ambos casos y Programación Práctica en Prolog Chequeo de tipo 7 no | ?- noPertenece(pilar,[jose,pilar,tomas]). no | ?- noPertenece(luis,[jose,pilar,tomas]). yes estuviese pusiese el caso recursivo antes, el sistema entraría en un bucle infinito. De la misma forma, es conveniente que la llamada recursiva sea la última llamada de la definición recursiva (muchos sistemas optimizan las definiciones así escritas)

5.3 Recorrer una lista tomando elementos de dos en dos

todosIguales([]). todosIguales([X]). todosIguales([X,X|Xs]):-todosIguales([X|Xs]). | ?- todosIguales([1,2,3]). no | ?- todosIguales([1,1,1]). yes | ?- todosIguales(X). X = [] ; X = [_25576] ; X = [_27704,_27704] ; X = [_27704,_27704,_27704] ; X = [_27704,_27704,_27704,_27704] todosIguales(Xs):- Los elementos de Xs son todos iguales Obsérvese que hay dos casos básicos y que el caso recursivo no es de la forma [X|Xs]. Obsérvese que los tres casos se excluyen. Como regla general, conviene que los casos de una definición se excluyan. Cuando los casos no se excluyen, al realizar backtracking el sistema puede obtener respuestas distintas de las esperadas.

. Describir la respuesta ante: ?- todosIguales([2,X,Y]).

5.4 Búsqueda de elementos en una lista

pertenece(X,[X|Xs]). pertenece(X,[Y|Ys]):- pertenece(X,Ys). | ?- pertenece(pedro,[jose,pedro,tomas]). yes | ?- pertenece(jose,[]). no | ?- pertenece(X,[jose,pedro,tomas]). X = jose ; X = pedro ; X = tomas ; no | ?- pertenece(jose,X). X = [jose|_6617] ; X = [_8808,jose|_8817] ; X = [_8808,_11012,jose|_11021] ; X = [_8808,_11012,_13230,jose|_13239] ... pertenece(X,Xs) :- X está en la lista Xs El caso básico no es la lista vacía. Además, los casos no se excluyen. Una lista que encaje con la primera definición, lo hará con la segunda. La relación pertenece es un claro ejemplo de la flexibilidad de las definiciones en Prolog ya que se puede utilizar para: 1.- Chequear si un elemento pertenece a una lista 2.- Obtener todos los elementos de una lista por backtracking 3.- Obtener listas con un elemento X en primera, segunda, ... n-ésima posición. elimina(X,[X|Xs],Xs). elimina(X,[Y|Ys],[Y|Zs]):-elimina(X,Ys,Zs). | ?- elimina(1,[1,2,1,3],V). V = [2,1,3] ; V = [1,2,3] ; no | ?- elimina(1,V,[2,3]). eliminna(X,Ys,Zs):-Zs contiene todas las listas resultantes de eliminar el elemento X de Ys 4 El predicado selecciona sirve también para diversos propósitos: Borrar elementos de una lista Insertar un elemento en diferentes posiciones de una lista Programación Práctica en Prolog Chequeo de tipo 8 V = [1,2,3] ; V = [2,1,3] ; V = [2,3,1] ; no

. Describir el comportamiento del predicado si se añade X=Y en la segunda definición. algunHombre(Xs):-pertenece(X,Xs), hombre(X). | ?- algunHombre([jose,pilar,tomas]). yes algunHombre(Xs):- alguno de los elementos X de Xs cumple la relación hombre(X)

5.5 Generación de una lista mediante concatenación de otras dos

concat([],Ys,Ys).

sinDuplicados(Xs,Ys). sinDuplicados([X|Xs],Ys):- pertenece(X,Xs), sinDuplicados(Xs,Ys). | ?- sinDuplicados([1,1,2,3,2,1,4],V). V = [3,2,1,4] ; filtraHombres(Xs,Ys):- Ys contiene todos los hombres de la lista Xs.

. Obsérvese qué ocurre cuando se solicitan más soluciones por backtracking o cuando se pregunta: ?- filtraHombres(V,[jose,pilar]). sinDuplicados(Xs,Ys) :-Ys contiene los elementos de Xs eliminando elementos duplicados. 4 Ambas definiciones son poco eficientes . Construir el predicado sinDuplicados para que la lista resultado contenga los elementos en el mismo orden en que aparecen

5.8 Aplicación de un predicado a todos los elementos

edad(pilar,85). edad(tomas,90). edad(belen,67). edad(lucia,64). edad(ana,34). edad(pedro,36). edad(jose,10). edades([],[]). edades([X|Xs],[Y|Ys]):-edad(X,Y), edades(Xs,Ys). | ?- edades([jose,pilar,tomas],V). V = [10,85,90] | ?- edades([jose,dedo,tomas],V). no | ?- edades(V,[10,85]). V = [jose,pilar] edades(Xs,Ys):- Ys contiene las edades de los elementos de Ys 4 Si alguno de los elementos no tiene edad , el predicado falla.

5.9 Permutaciones de una lista

permutacion([],[]). permutacion(Xs,[X|Ys]):-elimina(X,Xs,Zs), permutacion(Zs,Ys). | ?- permutacion([1,2,3],V). V = [1,2,3] ; V = [1,3,2] ; V = [2,1,3] ; V = [2,3,1] ; V = [3,1,2] ; V = [3,2,1] ; no permutacion(Xs,Ys):- Ys es una permutación de la lista Xs

6 Aritmética

Con el fin de aprovechar las posibilidades aritméticas de los computadores convencionales, el lenguaje Prolog contiene una serie de predicados de evaluación aritmética. Al encontrar un objetivo de la forma “? X is E“ el sistema: Evalúa la expresión E hasta obtener un valor aritmético v (si no puede, devuelve un error) El objetivo se cumple si X unifica con v Programación Práctica en Prolog Chequeo de tipo 10 La expresión E puede contener los operadores aritméticos clásicos (+, -, *, mod, etc.) y valores numéricos. Si

contiene variables, éstas deben estar instanciadas a un valor numérico en el momento de la evaluación. | ?- X is 3+5. X = 8 | ?- X is pepe. Error al evaluar | ?- 8 is 3+5. yes | ?- 4 is 3+5. no | ?- X is 4/0. Error aritmético | ?- X is X + 1. Error al evaluar | ?- X = 3, Y is X + 5. X = 3 , Y = 8 | ?- X=0, X is X + 1. no | ?- X = 3 + 5. X = 3 + 5 La evaluación de 3+5 se realiza internamente en una instrucción del procesador. Si la expresión no resulta en un valor aritmético, se obtiene un error. Al evaluar pueden producirse errores. El operador “ is” no es nunca un operador de asignación como el := de Pascal. En general, una expresión del tipo X is X+1 no tiene sentido en Prolog. Describir en qué situaciones “X is X + 1” es un error y en qué situaciones falla sin más. 4 El operador = unifica sus argumentos pero no evalúa. par(X) :- 0 is X mod 2. impar(X) :- 1 is X mod 2. suma(X,Y,Z):- Z is X + Y. | ?- par(3). no | ?- par(4). yes | ?- suma(2,3,V). V = 5 | ?- suma(2,V,5). Error al evaluar Con el operador is se pierde la flexibilidad de las relaciones lógicas. Lo ideal es que al evaluar suma(2,V,5), el sistema devolviese V=

. ¿Por qué se obtiene error al evaluar suma(2,V,5) y no se obtiene error al evaluar par(4)? Además del predicado is , los predicados de comparación realizan una evaluación aritmética de sus argumentos y se cumplen si los valores obtenidos cumplen las relaciones correspondientes: | ?- 3+5 > 2+6. no | ?- 3+5 >= 2+6. yes | ?- 3+5 < 2+6. yes | ?- 3+5 =< 2+6. yes | ?- 3+5 =:= 2+6. yes

cuyo valor se modifique durante la resolución del objetivo. Existen ciertos algoritmos que requieren la utilización de un estado que almacena resultados intermedios. Para implementar dichos algoritmos es necesario utilizar un predicado auxiliar con un argumento extra que almacenará el estado que se modifica. La definición de sum1 de la sección anterior sigue el patrón mencionado. sumAcum(Xs,Ys):-sumAc(Xs,0,Ys). sumAc([],S,[]). sumAc([X|Xs],Sa,[Sp|Ys]):-Sp is X + Sa, sumAc(Xs,Sp,Ys). | ?- sumAcum([1,2,3,4],V). V = [1,3,6,10]

sumAcum(Xs,Ys):-   j i y j xi 1 para cada y jYs

. Construir la definición del predicado maximo(Xs,M) que se cumple si M es el máximo de los elementos de Xs

7.3 Combinación miembro a miembro de los elementos de dos listas

prodEscalar(Xs,Ys,P):- pEsc(Xs,Ys,0,P). pEsc([],[],P,P). pEsc([X|Xs],[Y|Ys],Pa,Pr):-Pn is Pa + X * Y, pEsc(Xs,Ys,Pn,Pr). | ?- prodEscalar([1,2,3],[4,5,6],P). P = 32 prodEscalar(Xs,Ys,P):-P es el producto escalar de los vectores Xs e Ys (P = xiyi) 4 En esta definición se utiliza además el patrón de acumulación de resultados anterior.

7.4 Generación de una lista a partir de un valor

Es posible generar una lista mediante la descomposición de un valor. En el primer ejemplo, se descompone un número natural hasta llegar a cero, en el segundo, se descompone un intervalo hasta que los extremos son iguales. 5 En este sentido, los lenguajes funcionales se caracterizan por utilizar funciones de orden superior, permitiendo una mayor reutilización de código. Programación Práctica en Prolog Chequeo de tipo 12 repite(0,X,[]). repite(N,X,[X|Xs]):-N > 0, N1 is N - 1, repite(N1,X,Xs). intervalo(X,X,[X]). intervalo(X,Y,[X|Xs]):-X < Y, Z is X + 1, intervalo(Z,Y,Xs). | ?- repite(3,a,V). V = [a,a,a] ; | ?- intervalo(1,5,V). V = [1,2,3,4,5] ; repite(N,X,Xs):- Xs con N elementos de valor X intervalo(X,Y,Xs) :- Xs es una lista creciente cuyo primer valor es X y su último valor Y

7.5 Generación de listas por filtrado de elementos

Los siguientes ejemplos muestran cómo se puede generar una o varias listas filtrando los elementos de otras listas.

  • En pares , la condición de filtrado (ser par) indica si se inserta o no el elemento
  • En inserta la condición de filtrado (ser menor o mayor que el valor X ) indica si se selecciona el elemento Y de la lista que se recorre o el elemento X a insertar
  • En particion la condición de filtrado indica en qué lista se inserta
  • En el último caso, se recorren dos listas y la condición indica de cuál de las listas seleccionar el valor pares([],[]). pares([X|Xs],[X|Ys]):-par(X), pares(Xs,Ys). pares([X|Xs],Ys):- impar(X),pares(Xs,Ys). | ?- intervalo(1,5,V), pares(V,P). V = [1,2,3,4,5] , P = [2,4] ; pares(Xs,Ys):-Ys contiene los elementos pares de Xs. Se filtran los elementos pares inserta(X,[],[X]). inserta(X,[Y|Ys],[X,Y|Ys]):-X < Y. inserta(X,[Y|Ys],[Y|Zs]) :-X >= Y, inserta(X,Ys,Zs). | ?- inserta(3,[1,2,4],V). V = [1,2,3,4] ; inserta(X,Xs,Ys):-Ys es el resultado de insertar X en la posición adecuada de la lista ordenada Xs de forma que Ys se mantenga ordenada. particion(X,[Y|Ys],[Y|Ps],Gs):- Y < X, particion(X,Ys,Ps,Gs). particion(X,[Y|Ys],Ps,[Y|Gs]):- Y >= X, particion(X,Ys,Ps,Gs). particion(X,[],[],[]). | ?- particion(3,[2,4,1,5],X,Y). X = [2,1] , Y = [4,5] ; particion(X,Xs,Ps,Gs):- Ps contiene los elementos de Xs más pequeños que X y Gs los elementos de Xs más grandes o iguales que X. mezcla(Xs,[],Xs). mezcla([],[Y|Ys],[Y|Ys]). mezcla([X|Xs],[Y|Ys],[X|Zs]):-X < Y, mezcla(Xs,[Y|Ys],Zs). mezcla([X|Xs],[Y|Ys],[Y|Zs]):-X >= Y, mezcla([X|Xs],Ys,Zs). | ?- mezcla([1,3,5],[2,4,6],V). V = [1,2,3,4,5,6] ; mezcla(Xs,Ys,Zs) :-Zs es una lista ordenada formada a partir de las listas ordenadas Xs e Ys 4 Obsérvese que esta definición consta de dos casos básicos y dos recursivos. El segundo caso básico podría haber sido: mezcla([],Ys,Ys) pero no sería excluyente con el primero cuando Xs e Ys están vacías.

7.6 Clasificación de listas

ordenada([]). ordenada([X]). ordenada(Xs):- Los elementos de Xs están en

Los árboles de búsqueda se caracterizan porque el valor de cualquier nodo del árbol es mayor que el valor de los nodos a su izquierda y menos que el valor de los nodos a su derecha. insertArbol(X,vacio,rama(X,vacio,vacio)). insertArbol(X,A,An):-An es el árbol de 6 El algoritmo quicksort se caracteriza porque, aunque en el caso peor tiene complejidad O(n 2 ), en el caso medio tiene complejidad O(n log 2 n) 7 Este esquema de codificación se conoce como run-length encoded y es muy utilizado para comprimir imágenes 8 Las listas son un caso especial de estructura recursiva Programación Práctica en Prolog Chequeo de tipo 14 insertArbol(X,rama(X,A1,A2),rama(X,A1,A2)). insertArbol(X,rama(Y,A1,A2),rama(Y,A1n,A2)):- X < Y, insertArbol(X,A1,A1n). insertArbol(X,rama(Y,A1,A2),rama(Y,A1,A2n)):- X > Y, insertArbol(X,A2,A2n). listArbol(Xs,A):-creaArbol(Xs,vacio,A). creaArbol([],A,A). creaArbol([X|Xs],Ao,Ar):-insertArbol(X,Ao,An), creaArbol(Xs,An,Ar). | ?- listArbol([2,1,3],V). V = rama(2,rama(1,vacio,vacio),rama(3,vacio,vacio)) busca(X,rama(X,,)). busca(X,rama(Y,A1,A2)):-X < Y, busca(X,A1). busca(X,rama(Y,A1,A2)):-X > Y, busca(X,A2). nodos(vacio,[]). nodos(rama(X,A1,A2),Xs):-nodos(A1,Xs1), nodos(A2,Xs2), concat(Xs1,[X|Xs2],Xs). ordenArbol(Xs,XsO):-listArbol(Xs,A), nodos(A,XsO). | ?- ordenArbol([2,1,3,4],V). V = [1,2,3,4] ; búsqueda resultante de insertar X en A listaArbol(Xs,A):- A es el árbol de búsqueda creado a partir de la lista Xs

. Indicar qué patrón de recursividad se utiliza en la definición de listArbol busca(X,A):- Se cumple si X está en el árbol A nodos(A,Xs):- Xs son los nodos del árbol A. El predicado nodos realiza el recorrido del árbol empezando por los nodos de la izquierda, luego el nodo central y finalmente los de la derecha. Este recorrido se conoce como recorrido inorden. Existen otros recorridos como preorden y postorden 4 Obsérvese que con los árboles podrían definirse patrones recursivos similares a los definidos para las listas 9.

8 Predicados Internos

8.1 Conversión de tipos

En general, Prolog no contiene chequeo de tipos en tiempo de compilación, siendo necesario utilizar una serie de predicados predefinidos que chequean el tipo de sus argumentos. Predicado Condición para que se cumpla Preguntas Simples atom_chars(A,Cs) Cs es la lista de caracteres que representa el átomo A | ?- atom_chars(abc,V).

V = [97,98,99]

| ?- atom_chars(V,"abc"). V = abc number_chars(N,Cs) Cs es la lista de caracteres que representa el número N | ?- number_chars(123,V). V = [49,50,51] | ?- number_chars(V,"123"). V = 123 number_atom(N,A) A es el átomo que representa el número N | ?- number_atom(123,V). V = '123' | ?- number_atom(V,'123'). V = 123

8.2 Chequeo de tipos

En general, Prolog no contiene chequeo de tipos en tiempo de compilación, siendo necesario utilizar una serie de predicados predefinidos que chequean el tipo de sus argumentos. Predicado Condición para que se cumpla Ejemplos

integer( X) X es un entero. 4 9 Actualmente, se investiga la posibilidad de utilizar lenguajes que definan automáticamente dichos patrones de recursividad para los diferentes tipos de datos definidos por el usuario. Programación Práctica en Prolog Chequeo de tipo 15 float(X) X es un flotante. 4.

number(X) X es un número. 4 4. atom(X) X es un átomo. pepe []

atomic(X) X es un átomo o un número. pepe 4 4,5 [] compound(X) X es un término compuesto. padre(luis,juan) [3] list(X) X es una lista. [] [3] “3,2” sumaLogica(X,Y,Z):-integer(X), integer(Y), Z is X + Y. sumaLogica(X,Y,Z):-integer(Y), integer(Z), X is Z - Y. sumaLogica(X,Y,Z):-integer(X), integer(Z), Y is Z - X. | ?- sumaLogica(2,3,V). V = 5 ; | ?- sumaLogica(3,V,5). V = 2 sumaLogica(X,Y,Z):- Z es igual a X + Y Define un predicado aritmético que admite la flexibilidad de las relaciones lógicas. alisar([],[]). alisar([X|Xs],Ls):-list(X), alisar(X,Ls1), alisar(Xs,Ls2), concat(Ls1,Ls2,Ls). alisar([X|Xs],[X|Ls]):- atomic(X), alisar(Xs,Ls). | ?- alisar([[1,2],[3],[[4]]],V). V = [1,2,3,4] alisar(Xs,Ys):- Ys contiene una lista con los elementos de las listas de Xs

aunque los programas con ‘=..’ son más legibles, también son menos eficientes, pues necesitan construir una lista auxiliar.

8.4 Predicados meta-lógicos

Los predicados meta-lógicos permiten controlar el algoritmo de resolución facilitando la meta-programación. Ésta consiste en construir programas que manipulan otros programas proporcionando una mayor expresividad al lenguaje.

8.4.1 Chequeo de tipo

Predicado Condición para que se cumpla Ejemplos

var(X) X es una variable no instanciada | ?- var(X). X = _ | ?- X = 1, var(X). no nonvar( X) X no es una variable o es una variable instanciada | ?- nonvar(X). no | ?- X = 1, nonvar(X). X = 1 La utilización de estos predicados permite al programador chequear si una variable está instancia o no para proporcionar programas más flexibles y eficientes. abuelo(X,Y):-nonvar(X), hombre(X), progenitor(X,Z), progenitor(Z,Y). abuelo(X,Y):-nonvar(Y), progenitor(Z,Y), progenitor(X,Z), hombre(X). abuelo(X,Y) :- X es abuelo de Y

8.4.2 Comparación de términos no básicos

Predicado Condición para que se cumpla Ejemplos X==Y X e Y son iguales (no unifica las variables) | ?- f(X,2) = f(1,Y). X = 1 , Y = 2 | ?- f(X,2) == f(1,Y). no X == Y X e Y no son iguales (no | ?- f(X,2) == f(1,Y). yes Programación Práctica en Prolog Conversión de Datos en Objetivos 17 unifica las variables) unifica(X,Y):-var(X),var(Y), X = Y. unifica(X,Y):-var(X), nonvar(Y), noOcurre(X,Y),X=Y. unifica(X,Y):-var(Y), nonvar(X), noOcurre(Y,X),Y=X. unifica(X,Y):-nonvar(X), nonvar(Y), atomic(X), atomic(Y), X = Y. unifica(X,Y):-nonvar(X), nonvar(Y), compound(X), compound(Y), unifTerm(X,Y). unifTerm(X,Y):- functor(X,F,A), functor(Y,F,A), unifArgs(A,X,Y). unifArgs(N,X,Y):- N > 0, unifArg(N,X,Y), N1 is N - 1, unifArgs(N1,X,Y). unifArgs(0,X,Y). unifArg(N,X,Y):- arg(N,X,Ax), arg(N,Y,Ay), unifica(Ax,Ay). noOcurre(X,Y):-var(Y), X == Y. noOcurre(X,Y):-nonvar(Y), atomic(Y). noOcurre(X,Y):-nonvar(Y), compound(Y), functor(Y,F,A), noOcurreArgs(A,X,Y). noOcurreArgs(N,X,Y):- N > 0, arg(N,Y,An), noOcurre(X,An), N1 is N - 1, noOcurreArgs(N1,X,Y).

noOcurreArgs(0,X,Y). unifica(X,Y):- Se cumple si X e Y son unificables utilizando chequeo de ocurrencias. | ?- unifica(f(1,X),f(Y,2)). X = 2 , Y = 1 ; | ?- f(X,X)=f(Y,g(Y)). Error ... Stack Full, | ?- unifica(f(X,X),f(Y,g(Y))). no noOcurre(X,T):- se cumple si la variable X no aparece en el término T

8.4.3 Conversión de Datos en Objetivos

El predicado call(X) se cumple si se cumple el objetivo X. o(X,Y):-call(X). o(X,Y):-call(Y). | ?- o(progenitor(belen,tomas), progenitor(tomas,belen)). yes | ?- progenitor(belen,tomas) ; progenitor(tomas,belen). yes for(0,X). for(N,X):-call(X),N1 is N - 1, for(N1,X). | ?- for(5,write('*')).


yes | ?- T =.. [progenitor, tomas, belen], T. T = progenitor(tomas,belen) ; o(X,Y):- se cumple si se cumple X o si se cumple Y 4 El predicado o(X,Y) está predefinido como el operador ‘;’ 4 El Prolog Standard sustituye automáticamente una objetivo en forma de variable X por call(X) Programación Práctica en Prolog Conversión de Datos en Objetivos 18

8.5 Corte

El corte es uno de los predicados internos más polémicos del lenguaje Prolog. Se utiliza para “podar” ramas del árbol de resolución consiguiendo que el sistema vaya más rápido. Un mal uso del corte puede podar ramas del árbol de resolución que contengan soluciones impidiendo que el sistema encuentre algunas soluciones (o todas) a un problema dado. De esta forma se aconseja utilizar el corte con precaución y únicamente en el lugar necesario, Ni antes ni después. El predicado corte se representa mediante el símbolo ‘!’ y su efecto es:

  • El predicado siempre se cumple.
  • Si se intenta re-ejecutar (al hacer backtracking) elimina las alternativas restantes de los objetivos que hay desde su posición hasta la cabeza de la regla donde aparece. q(X):-p(X). q(0). p(X):-a(X),!,b(X). p(1). a(2). a(3). b(2). b(2). b(3). | ?- q(X). X = 2 ; X = 2 ; X = 0