Prolog V1 V. E/S en Prolog Jorge Cabrera Gámez Departamento de Informática y Sistemas Universidad...

Preview:

Citation preview

Prolog V 1

V. E/S en Prolog

Jorge Cabrera GámezDepartamento de Informática y Sistemas

Universidad de Las Palmas de Gran Canaria

Prolog V 2

Índice.El modelo de E/S

Comunicación con ficherosStreams de entrada/salida implícitosStreams de entrada/salida explícitos

Predicados de E/S orientados a caracteres

Lectura de Programas

Sumario

Prolog V 3

Terminal

Programa

Prolog

Fichero 1

Fichero 2

...

Fichero 4

Fichero 3

...

useruser

inputstreams

outputstreams

El modelo de E/S

Prolog V 4

Modos de Comunicación con ficheros

Streams de entrada/salida implícitos(Estándar)

Streams de entrada/salida explícitos

Prolog V 5

Streams de entrada/salida implícitos

Idea básica: Durante la ejecución de un programa Prolog sólo dos ficheros están activos: uno de entrada y otro de salida

see(NombreFichero)...see(fichero1),lee_de_fichero(Datos),see(user),...

tell(NombreFichero)

stream de entradastream de salida

...tell(fichero1),escribe_en_fichero(Datos),tell(user),...

seen

told

Prolog V 6

Streams de entrada/salida implícitos

see(+SrcDest) Convierte a SrcDest en el stream de entrada activo. Si SrcDest ya había sido abierto con see/1 y no había sido cerrado, la lectura del fichero se retoma desde la posición actual del puntero. En otro caso, el fichero se abre y el puntero se sitúa al comienzo del mismo.

tell(+SrcDest) Idem. Nótese que en este caso si el fichero no existía se crea y si existía se trunca.

append(+File) Similar a tell/1, pero posiciona el puntero de fichero al final del mismo en vez de truncar un fichero ya existente.

Prolog V 7

Streams de entrada/salida implícitos

seeing(?SrcDest) Unifica el nombre del stream de entrada activo con SrcDest

telling(?SrcDest) Unifica el nombre del stream de salida activo con SrcDest

Prolog V 8

Streams de entrada/salida explícitos

open(+SrcDest, +Modo, -Stream, +Opciones)

* Stream: manejador del stream. * Modo: read, write, append o update. * Opciones: una lista de opciones.

type(Type): text (defecto) o binary.alias(Atom): Fija un nombre para el stream.

?- open(foo, read, S, [alias(in)]). buffer(Buffering): Opciones de buffering de la salida. fullf (defecto): buffering completo.

line: buffering por líneasfalse: no se realiza buffering

close(+Stream)

Prolog V 9

Streams de entrada/salida explícitos

seek(+Stream, +Offset, +Método, -NuevaPosición)

Reposiciona el puntero del stream a la posición dada. Offset: Indica el número de bytes del desplazamiento. Método: bof (desde el principio) current (desde la posición actual) eof (desde el final) NuevaPosición: El nuevo offset desde el comienzo del stream

Prolog V 10

Streams de entrada/salida explícitos

set_input(+Stream) Convierte Stream en el stream de entrada activo.

open(file, read, Stream), set_input(Stream). es equivalente a:

see(file). set_output(+Stream)

current_input(-Stream)

current_output(-Stream)

Prolog V 11

Read/Write

read(X)Predicado predefinido que permite leer un términodel stream de entrada.

Si el argumento de read no es unificable con el término a leer, read falla.

read es determinista: si read falla, no se intentaleer otro término en el backtracking.

write(X)Predicado predefinido que permite escribir un términoen el stream de salida.

Prolog V 12

Read/Write

Ejemplo:

cubo :-write(´Siguiente item: ´),read(X),procesa(X).

procesa(stop) :- !.

procesa(N) :-C is N*N*N, tab(3),write(´El cubo de ´),write(N),write(´ is ´), write(C), nl,cubo.

?- cubo.Siguiente item: 3. El cubo de 3 is 27Siguiente item: 34. El cubo de 34 is 39304Siguiente item: stop.

Yes

Prolog V 13

Read/Write

Ejemplo:

barras( [ ] ).

barras( [ L| LL] ) :-estrellas(L), nl,barras(LL).

estrellas(N) :-N > 0,write(*),N1 is N-1,estrellas(N1).

estrellas(N) :- N =< 0.

?- barras([1,2,5,3,4]).***************

Yes

?- barras([1,2,5,3,4]).

Prolog V 14

Read/Write

Ejemplo:

escribe_lista( [ ] ).

escribe_lista( [ L| LL] ) :-una_linea(L), nl,escribe_lista(LL).

una_linea( [ ] ).

una_linea( [ X | L ] ) :-write(X), tab(1),una_linea(L).

?- escribe_lista([[2],[a,d],[q,w]]).

2 a d q w

Yes

?- escribe_lista([a, b]).

No

?- escribe_lista([[2],[a,d],[q,w]]).

Prolog V 15

Read/Write

Ejemplo:

pp_lista(L) :- pp(L,0).

pp([H|T], I) :- !, J is I+3, pp(H,J), ppx(T,J), nl.

pp(X, I) :- tab(I), write(X), nl.

ppx([ ], _).ppx([H|T], I) :-

pp(H, I), ppx(T, I).

?- pp_lista([[a,s],[1,[2],3]]). a s

1 2

3

Yes

?- pp_lista([ [a,s], [1, [2], 3] ]).

Prolog V 16

Read/Write

Ejemplo:

pp_palabras([ ]) :- nl.pp_palabras([H|T]) :- write(H),

T == [], !, write(.);tab(1), pp_palabras(T).

?- pp_palabras([mi, mamá, me, ama ]).mi mamá me ama .

Yes

?- pp_palabras([mi, mamá, me, ama ]).

Prolog V 17

Read/Write

Ejemplo:

pp_palabras([ ]) :- nl.pp_palabras([W|Ws]) :-

write(W), Ws == [] -> write_ln(.);tab(1), pp_palabras(Ws).

?- pp_palabras([mi, mamá, me, ama ]).mi mamá me ama .

Yes

?- pp_palabras([mi, mamá, me, ama ]).

Prolog V 18

Ejemplo:

pp_palabras([]) :- nl.pp_palabras([H|T]) :-

name(H,[A|B]), es_letra(A,C), name(H1,[C|B]),palabras_aux([H1|T]).

pp_palabras(L) :- palabras_aux(L).

palabras_aux([]) :- nl.palabras_aux([H|T]) :-

write(H), T == [] -> write_ln(.);tab(1), palabras_aux(T).

es_letra(A,A1) :-A =< 122, A >= 97, !, A1 is A-32;A =< 90, A >= 65, A1 is A.

?- pp_palabras([mamá,me, mima]).Mamá me mima .Yes

?- pp_palabras([‘Mamá’,me, mima]).Mamá me mima .Yes

Prolog V 19

Una utilidad: Cómo leer del teclado una línea sin tener que terminarla en un punto final.

% read_line(-Line)% Reads characters from the keyboard until % it reaches an eof or a new line.read_line([Char | List]) :-

get0(Char),Char =\= -1, % EOFChar =\= 10, % New line!,read_line(List).

read_line([]).

?- read_line(Line).|: holaX = [104, 111, 108, 97].

Prolog V 20

Otra utilidad: Cómo leer todas las líneas de texto de un fichero, devolviendo el contenido como una lista de caracteres.

% read_file(File,Charlist) % Equivalent to read_file_to_codes(File,CharList,[]) % which is a predefined in SWI-Prologread_file(File, CharList) :-

see(File),read_list(CharList),seen.

% read_list(-List)% Reads characters from the the input % it reaches an eof.read_list([Char | List]) :-

get0(Char),Char =\= -1,!,read_list(List).

read_list([]).

Prolog V 21

..., see(fichero), procesar_fichero, see(user), ...

procesar_fichero :-read(Term),procesar_termino(Term).

procesar_termino(end_of_file) :- !. % Fin

procesar_termino(Term) :-treat(Term), % Se trata el términoprocesar_fichero. % Resto del fichero

Esquema básico para procesar un fichero de términos

Prolog V 22

browse(File) :- seeing(Old), /* Lo salvamos para después */ see(File), /* Abrimos este fichero */

repeat, read(Data), /* Leemos del fichero */ process(Data), !, seen, /* Cerramos el fichero */ see(Old). /* Volvemos al primero */

process(end_of_file) :- !. process(Data) :-

write(Data), nl, fail.

?- browse('browse.pl').browse(_G249):-seeing(_G251), see(_G249), repeat, read(_G255), process(_G255), !, seen, see(_G251).

process(end_of_file):-!

process(_G249):-write(_G249), nl, fail

Yes

Prolog V 23

Predicados de E/S orientados a caracteres.

put(C) Escribe el carácter C en el stream de salida

C es el código ASCII del carácter o el propio carácter.

?- put('B'), put(66), put(b), put(98).BBbbYesget0(C) Lee el siguiente carácter del stream de entrada. C es el código ASCII del carácter?- get0(X).| 1X = 49 Yes

get(C) Lee el siguiente carácter del stream de entrada diferente del espacio. C es el código ASCII del carácter.?- get(X).|| 2X = 50 Yes

Aquí espacio en blanco + [ENTER]

Prolog V 24

put/get

Ejemplo:

corrige :-get0(C),put(C),haz_el_resto(C).

haz_el_resto(46) :- !. % Codigo ASCII del punto (.)

haz_el_resto(32) :- % Codigo ASCII del blanco!,get(C), % No consideramos otros blancosput(C), haz_el_resto(C).

haz_el_resto(Letra) :- corrige.

Elimina múltiples espacios entre palabras de una frase terminada por un punto

?- corrige.| Erase una vez un . Erase una vez un .Yes

Prolog V 25

Lo que hay que hacer:

1.Leer el texto del fichero2.Agrupar caracteres en palabras (“Tokenize”)3.Ordenar (sin eliminar duplicados)4.Contar los duplicados

El resultado debe ser una lista de pares del tipo:

[Apariciones, Palabra]

Ejercicio:

Contar el número de ocurrencias de una palabra en un texto

Prolog V 26

Solución:

:-ensure_loaded('tokenize.pl').

word_counter( MyFile, UnigramList):-

% Leer el texto del ficheroread_file_to_codes(MyFile, CharacterList,[]),

%Agrupar caracteres en palabras (“Tokenize”)tokenizes(CharacterList,TokenList),

%Ordenar (sin eliminar duplicados)msort(TokenList, OrderedTokens),

%Contar los duplicadoscount_duplicates(OrderedTokens, UnigramList).

Prolog V 27

% tokenize(+Chars, -Tokens)% breaks a list of characters into a list of tokens.% It uses blanks/2 that removes the blank characters from% the head of the list and token/3 that builds one% token from the characters of the head of the list.tokenize([], []) :- !.tokenize(Chars, Tokens) :-

blanks(Chars, RemainingChars),tokenize(RemainingChars, Tokens),!.

tokenize(Chars, [Token | Tokens]) :-token(Chars, Token, RemainingChars),tokenize(RemainingChars, Tokens).

% blanks(+Chars, -RemainingChars)% Removes the blank characters from the head of the list of Chars% RemainingChars contains the rest of the list.blanks([Char1, Char2 | Chars], [Char2 | Chars]) :-

Char1 =< 32, % blank = 32, non-printable chars < 32Char2 > 32,!.

blanks([], []) :- !.blanks([Char | Chars], RemainingChars) :-

Char =< 32,blanks(Chars, RemainingChars).

Prolog V 28

% token(+Chars, -Token, -RemainingChars)% Builds one token from the characters of the head of the list.% Token is the built token and RemainingChars is the rest of the listtoken(Chars, Token, RemainingChars) :-

alphanumeric_token(Chars, TokenChars, RemainingChars),name(Token, TokenChars),!.

token(Chars, Token, RemainingChars) :-others(Chars, TokenChar, RemainingChars),name(Token, [TokenChar]).

% alphanumeric_token(+Chars, -TokenChars, -RemainingChars)% Returns the characters of the first token on the head% of the list.alphanumeric_token([Char1, Char2 | Chars], [Char1], [Char2 | Chars]) :-

alphanumeric(Char1),\+ alphanumeric(Char2),!.

alphanumeric_token([], [], []) :- !.alphanumeric_token([Char | Chars], [Char | TokenChars], RemainingChars) :-

alphanumeric(Char),!,alphanumeric_token(Chars, TokenChars, RemainingChars).

Prolog V 29

% alphanumeric(+Char)% Checks whether Char is alphanumeric. There are several cases:

% Lower-case letters without accentalphanumeric(Char) :- 97 =< Char, Char =< 122, !.

% Upper-case letters without accentalphanumeric(Char) :- 65 =< Char, Char =< 90, !.

% Accented characters. The values 215 and 247 correspond to% the multiplication and division: × ÷alphanumeric(Char) :-

192 =< Char, Char =< 255,Char =\= 215, Char =\= 247,!.

% Digitsalphanumeric(Char) :-

48 =< Char, Char =< 57,!.

% The oe, OE, and Y" lettersalphanumeric(Char) :-

(Char =:= 140 ; Char =:= 156 ; Char =:= 159),!.

others([Char | Chars], Char, Chars).

Prolog V 30

% Cuenta el número de veces que un elemento aparece de forma% consecutiva en una lista

count_duplicates(OrderedList, CountedList) :-count_duplicates(OrderedList, 1, [], CountedListRev),reverse(CountedListRev, CountedList).

count_duplicates([X, X | Ordered], N, Counting, Counted) :-N1 is N + 1,!,count_duplicates([X | Ordered], N1, Counting, Counted).

count_duplicates([X | Ordered], N, Counting,Counted) :-!,count_duplicates(Ordered, 1, [[N, X] | Counting], Counted).

count_duplicates([], _, L, L).

Prolog V 31

nl nl(+Stream)

put(+Char) put(+Stream, +Char)

tab(+Espacios) tab(+Stream, +Espacios)

flush flush(+Stream)

get0(-Char) get0(+Stream,-Char)

get(-Char) get(+Stream,-Char)

peek_byte(-Char) peek_byte(+Stream,-Char)

skip(+Char) skip(+Stream,+Char)

write(+Term) write(+Stream,+Term)

read(-Term) read(+Stream,-Term)

Prolog V 32

name(?Atom, ?List)

atom_chars(?Atom, ?String)

atom_char(?Atom, ?ASCII)

atom_length(+Atom,-Length)

string_to_atom(?String, ?Atom)

string_to_list(?String, ?List)

string_length(+String, -Length)

string_concat(?String1, ?String2, ?String3)

?- string_to_atom("Hola que tal", A).A = 'Hola que tal' Yes?- string_to_list("Hola que tal",L).L = [72, 111, 108, 97, 32, 113, 117, 101, 32, 116, 97, 108] Yes

?- atom_chars(pepelu, A).A = [112, 101, 112, 101, 108, 117]Yes?- atom_char(p, C).C = 112Yes

Prolog V 33

write_nl(+Term)

writef (+Format, +Arguments)

swritef (-String, +Format,+Arguments)

format(+Format, +Arguments)

?- X is 17.2, Y is 238, format('Runtime: ~`.t ~2f~34| Inferences: ~`.t ~D~72|~n', [X,Y]).

Runtime: ................... 17.20 Inferences: .................... 238

Prolog V 34

Lectura de programas

consult(+Fichero)

[Fichero1, Fichero2]

reconsult(+Fichero)

No es necesario,(no existe)en SWI-Polog.

Prolog V 35

Sumario.

• E/S implícita y explícita. [user_input],

[user_output]

como flujos de entrada salida por defecto.

• read/write para leer y escribir términos.

• get/put para leer y escribir caracteres.

• SWI-Prolog oferta una gran variedad de

predicados

para producir una salida con formato.

• Para leer programas Prolog usar consult

Prolog V 36

Problemas

10. Implementar en Prolog los siguientes predicados que operan sobre conjuntos:A) permutacion(Xs, Ys), que devuelva en Ys las permutaciones posibles de la lista Xs (nota: cada permutación se consideraría como una solución).B) combinacion(Xs, N, Ys), que devuelva en Ys las combinaciones posibles de los elementos de Xs cuando éstos se toman de N en N.C) diferencia(Xs, Ys, Zs), que devuelva el Zs el conjunto diferencia de los conjuntos (listas) Xs e Ys. El conjunto diferencia debe contener los elementos que aparecen en sólo uno de los conjuntos.D) union(Xs, Ys, Zs), que devuelve en Zs la union (sin duplicados) de los conjuntos Xs e Ys.E) interseccion(Xs, Ys, Zs), que devuelve en Zs la intersección de los conjuntos Xs e Ys.

Prolog V 37

%Problema 10, A% extract(X,Ys,Zs) Genera la lista Zs extrayendo de la % lista Ys una ocurrencia de X

extract(X,[X|Xs],Xs).

extract(X,[Y|Ys],[Y|Zs]):- extract(X,Ys,Zs).

% permutation(Xs, Zs) % Devuelve en Zs una permutación de los elementos% de la lista Xs. La idea es generar las permutaciones% de los n elementos extrayendo uno de los elementos% mediante extract/3 y generando las permutaciones de % orden inferior (n-1 elementos) a las que se añade % por la cabeza el elemento seleccionado con extract/3.

permutation(Xs, [Z|Zs]):- extract(Z, Xs, Ys), permutation(Ys,Zs).

permutation([ ], [ ]).

Prolog V 38

2 ?- extract(X,[a,b,c],Xs).

X = a,Xs = [b, c] ;

X = b,Xs = [a, c] ;

X = c,Xs = [a, b] ;

No

Prolog V 39

[debug] ?- permutation([a,b],Z). T Call: (7) permutation([a, b], _G394) T Call: (8) extract(_G446, [a, b], _G478) T Exit: (8) extract(a, [a, b], [b]) T Call: (8) permutation([b], _G447) T Call: (9) extract(_G449, [b], _G481) T Exit: (9) extract(b, [b], []) T Call: (9) permutation([], _G450) T Call: (10) extract(_G452, [], _G484) T Fail: (10) extract(_G452, [], _G484) T Redo: (9) permutation([], _G450) T Exit: (9) permutation([], []) T Exit: (8) permutation([b], [b]) T Exit: (7) permutation([a, b], [a, b])

Z = [a, b] ;

Prolog V 40

T Fail: (9) permutation([], _G450) T Redo: (9) extract(_G449, [b], _G481) T Call: (10) extract(_G449, [], _G453) T Fail: (10) extract(_G449, [], _G453) T Fail: (9) extract(_G449, [b], _G481) T Fail: (8) permutation([b], _G447) T Redo: (8) extract(_G446, [a, b], _G478) T Call: (9) extract(_G446, [b], _G450) T Exit: (9) extract(b, [b], []) T Exit: (8) extract(b, [a, b], [a]) T Call: (8) permutation([a], _G447) T Call: (9) extract(_G452, [a], _G484) T Exit: (9) extract(a, [a], []) T Call: (9) permutation([], _G453) T Call: (10) extract(_G455, [], _G487) T Fail: (10) extract(_G455, [], _G487) T Redo: (9) permutation([], _G453) T Exit: (9) permutation([], []) T Exit: (8) permutation([a], [a]) T Exit: (7) permutation([a, b], [b, a])Z = [b, a] Yes

Prolog V 41

/*************************************************************** Una solución equivalente basada en la idea de insertar elementos****************************************************************/insert(L, X,[X|L]).insert([H|T],X,[H|L]):- insert(T,X,L).

permutation2([ ],[ ]).permutation2([X|Xs],Zs):-

permutation2(Xs,Ys),insert(Ys,X,Zs).

4 ?- insert([1,2],a,L).

L = [a, 1, 2] ;

L = [1, a, 2] ;

L = [1, 2, a] ;

No

Prolog V 42

%Problema 10, B/***************************************************B) combination(Xs, N, Ys), que devuelva en Ys las combinaciones posibles de los elementos de Xs cuando éstos se toman de N en N.****************************************************/

combination(_,0,[ ]).

combination(Xs,1,[X]):- extract(X,Xs,_).

combination([X|Xs],N,[X|Zs]):-N > 1,N1 is N-1,combination(Xs,N1,Zs).

combination([_|Xs],N,Zs):-N > 1,combination(Xs,N,Zs).

7 ?- combination([1,2,3],2,Cs).

Cs = [1, 2] ;

Cs = [1, 3] ;

Cs = [2, 3] ;

No

Prolog V 43

% Problema 10, CC) difference(Xs, Ys, Zs), que devuelva el Zs el conjunto diferencia de los conjuntos (listas) Xs e Ys. El conjunto diferencia debe contener los elementos que aparecen en sólo uno de los conjuntos.

difference(Xs,Ys,Zs):-list_to_set(Xs,Xs1), % Eliminar duplicadoslist_to_set(Ys,Ys1), % Eliminar duplicadosdif_aux(Xs1,Ys1,Zs).

dif_aux([ ],Zs,Zs).dif_aux([X|Xs],Ys,Zs):-

(memberchk(X,Ys), !, extract(X,Ys,Ys1);Ys1 = [X|Ys] ),dif_aux(Xs,Ys1,Zs).

Prolog V 44

%Problema 10, D

set_union(Xs, Ys, Zs), que devuelve en Zs la union (sin duplicados) de los conjuntos Xs e Ys.

set_union([ ], Ys, Zs):- list_to_set(Ys,Zs).set_union([X|Xs],Ys,Zs):-

\+member(X,Ys),!, set_union(Xs,[X|Ys],Zs);set_union(Xs,Ys,Zs).

% Alternativaset_union2(Xs,Ys,USs):-

append(Xs,Ys,ULs),list_to_set(ULs,USs).

Prolog V 45

set_intersection(Xs,Ys,Zs):- list_to_set(Xs,Xs1),inter_aux(Xs1,Ys,[ ],Zs).

inter_aux([ ], _, Zs, Zs).

inter_aux([X|Xs],Ys,Ws,Zs):-member(X,Ys),!, inter_aux(Xs,Ys,[X|Ws],Zs);inter_aux(Xs,Ys,Ws,Zs).

% Problema 10, E

E) set_intersection(Xs, Ys, Zs), que devuelve en Zs la intersección de los conjuntos Xs e Ys.

Prolog V 46

11. Implementar el predicado max_lista(Xs, Y) que permita recuperar en Y el máximo de los números contenidos en la lista Xs.

% Problema 11. max_lista([X],X) :- !. % Este cut evita una

% llamada inutil con [ ] max_lista([X|S],M) :-

max_lista(S,P), X < P, !, M is P;M is X.

SWI-Prolog

Prolog V 47

12. Dada una lista conteniendo números enteros, devolver dos listas conteniendo respectivamente los números positivos (incluido el cero) y los números negativos. Realizar dos implementaciones de este predicado: una sin emplear el predicado cut (!) y otra que sí lo utilice.

% Problema 12.separa([ ], [ ], [ ]).separa([X|S], [X|P], N) :- X >= 0, separa(S, P, N).separa([X|S], P, [X|N]) :- X < 0, separa(S, P, N).

Problemas

SWI-Prolog

separa_cut([ ], [ ], [ ]).separa_cut([X|S], [X|P], N) :- X >= 0, !, separa_cut(S, P, N).separa_cut([X|S], P, [X|N]) :- separa_cut(S, P, N).

Prolog V 48

?- separa([1,2,-3,4,0,-2],P,N).T Call: ( 7) separa([1, 2, -3, 4, 0, -2], _G250, _G251)T Call: ( 8) separa([2, -3, 4, 0, -2], _G386, _G251)T Call: ( 9) separa([-3, 4, 0, -2], _G389, _G251)T Redo: ( 9) separa([-3, 4, 0, -2], _G389, _G251)T Call: ( 10) separa([4, 0, -2], _G389, _G392)T Call: ( 11) separa([0, -2], _G395, _G392)T Call: ( 12) separa([-2], _G398, _G392)T Redo: ( 12) separa([-2], _G398, _G392)T Call: ( 13) separa([], _G398, _G401)T Exit: ( 13) separa([], [], [])T Exit: ( 12) separa([-2], [], [-2])T Exit: ( 11) separa([0, -2], [0], [-2])T Exit: ( 10) separa([4, 0, -2], [4, 0], [-2])T Exit: ( 9) separa([-3, 4, 0, -2], [4, 0], [-3, -2])T Exit: ( 8) separa([2, -3, 4, 0, -2], [2, 4, 0], [-3, -2])T Exit: ( 7) separa([1, 2, -3, 4, 0, -2], [1, 2, 4, 0], [-3, -2])P = [1, 2, 4, 0]N = [-3, -2] ;

T Redo: ( 11) separa([0, -2], _G395, _G392)T Fail: ( 11) separa([0, -2], _G395, _G392)T Redo: ( 10) separa([4, 0, -2], _G389, _G392)T Fail: ( 10) separa([4, 0, -2], _G389, _G392)T Fail: ( 9) separa([-3, 4, 0, -2], _G389, _G251)T Redo: ( 8) separa([2, -3, 4, 0, -2], _G386, _G251)T Fail: ( 8) separa([2, -3, 4, 0, -2], _G386, _G251)T Redo: ( 7) separa([1, 2, -3, 4, 0, -2], _G250, _G251)T Fail: ( 7) separa([1, 2, -3, 4, 0, -2], _G250, _G251)

No

?- separa_cut([1,2,-3,4,0,-2],P,N).T Call: ( 8) separa_cut([1, 2, -3, 4, 0, -2], _G274, _G275)T Call: ( 9) separa_cut([2, -3, 4, 0, -2], _G410, _G275)T Call: ( 10) separa_cut([-3, 4, 0, -2], _G413, _G275)T Redo: ( 10) separa_cut([-3, 4, 0, -2], _G413, _G275)T Call: ( 11) separa_cut([4, 0, -2], _G413, _G416)T Call: ( 12) separa_cut([0, -2], _G419, _G416)T Call: ( 13) separa_cut([-2], _G422, _G416)T Redo: ( 13) separa_cut([-2], _G422, _G416)T Call: ( 14) separa_cut([], _G422, _G425)T Exit: ( 14) separa_cut([], [], [])T Exit: ( 13) separa_cut([-2], [], [-2])T Exit: ( 12) separa_cut([0, -2], [0], [-2])T Exit: ( 11) separa_cut([4, 0, -2], [4, 0], [-2])T Exit: ( 10) separa_cut([-3, 4, 0, -2], [4, 0], [-3, -2])T Exit: ( 9) separa_cut([2, -3, 4, 0, -2], [2, 4, 0], [-3, -2])T Exit: ( 8) separa_cut([1, 2, -3, 4, 0, -2], [1, 2, 4, 0], [-3, -2])P = [1, 2, 4, 0]N = [-3, -2] ;No

Prolog V 49

Problemas13. Definir los operadores ‘if’, ‘then’, ‘else’ y ‘:=’ de manera que el siguiente término sea sintácticamente correcto:

if X >Y then Z:= X else Z:= Y

Elegir las precedencias de forma que ‘if’ sea el functor principal. Defina la relación ‘if’ como un pequeño intérprete para una expresión del tipo ‘if-then-else’ de la forma:

if Val1 > Val2 then Var:= Val3 else Var:= Val4

donde Val1, Val2, Val3 y Val4 son números, o variables instanciadas en

números, y Var es una variable. Lo que sigue es un ejemplo de cómo

debería utilizarse este intérprete:

?- X = 2, Y = 3, Val2 is 2*X, Val4 is 4*X,

if Y > Val2 then Z:= Y else Z:= Val4,

if Z > 5 then W:= 1 else W:= 0.

X = 2 Y = 3 Z = 8 W = 1 Val2 = 4 Val4 = 8 SWI-Prolog

Prolog V 50

% Problema 13.:- op(900, fx, if).:- op(800, xfx, then).:- op(700, xfx, else).:- op(600, xfx, :=).

if Val1 > Val2 then Var:= Val3 else Var:= Val4 :-Val1 > Val2, !, Var = Val3;Var = Val4.

SWI-Prolog

Prolog V 51

14. Definir el predicado freq(Xs, Ys) de manera que ante una lista de números enteros (Xs) obtenga una lista (Ys) que contenga las frecuencias de aparición de los diferentes elementos de la lista Xs. Por ejemplo:

?- freq([3,3,2,2,1,1,2,2,3,3], A).

A = [2*1,4*2,4*3]

donde la nomenclatura empleada en la lista A indica que existen 2 ocurrencias de 1, 4 de 2 y 4 de 3. Nota: El que la lista resultado salga ordenada puede facilitar la obtención de la solución.

Problemas

SWI-Prolog

Prolog V 52

% Problema 14.freq(L, S) :- freq(L, [], S).freq([], S, S).freq([N|L], S1, S3) :- actualiza(N, S1, S2), freq(L, S2, S3).

% actualiza(clave, listaentrada, listasalida)actualiza(N, [], [1*N]).actualiza(N, [F*N|S], [F1*N|S]) :- !, F1 is F+1.actualiza(N, [F*M|S], [1*N,F*M|S]) :- N < M, !.actualiza(N, [F*M|S], [F*M|S1]) :- N \== M, actualiza(N,S,S1).

?- freq([3,3,2,2,1,1,2,2,3,3], A).

A = [2*1,4*2,4*3]

SWI-Prolog

Recommended