Liste

liste/es1.pl - Divisione in testa e coda

?- [genova,milano,roma] = [X|Y].
X = genova
Y = [milano, roma]
?- [10,20,[30,40],cinquanta] = [X|Y].
X = 10
Y = [20, [30, 40], cinquanta]
?- [a,b,[C,D,[e]]] = [X|Y].
C = _G4382
D = _G4385
X = a
Y = [b, [_G4382, _G4385, [e]]]
?- [a]= [X|Y].
X = a
Y = []
?- [[a, b, c]] = [X|Y].
X = [a, b, c]
Y = []

liste/es2.pl - Matching

Dopo aver consultato i seguenti fatti:
 
 e_una_lista([questo,e,un,paragrafo,sulle,liste]).
 e_una_lista([la,vispa,teresa,[avea,tra,l,erbetta]]).
?-e_una_lista([X|Y]).
 X=questo Y=[e,un,paragrafo,sulle,liste];
 X=la Y=[vispa,teresa,[avea,tra,l,erbetta]]
?-e_una_lista([_|X]).
 X=[e,un,paragrafo,sulle,liste];
 X=[vispa,teresa,[avea,tra,l,erbetta]]
?-e_una_lista([_,_,_,[X|_]]).
 X=avea

liste/es3.pl Membro: appartenenza ad una lista

?-membro(a,[i,n,f,o,r,m,a,t,i,c,a]).
yes
?-membro(b,[c,o,m,p,u,t,e,r]).
no
?-membro(c,[m,i,[s,c,e],l,a]).
no
Notare che in questo caso la "c" appare in una lista interna alla lista principale. Per questo motivo l'interprete risponde no.

Approfondimemti: come il Prolog tratta la ricorsione

Con il goal:
?- trace, membro(new_york,[boston,chicago,filadelfia,
               san_francisco, los_angeles,denver]).
si ottiene:
   
Call:  ( 11) membro(new_york, [boston, chicago, filadelfia, san_francisco, los_angeles, denver]) ?    
Call:  ( 12) membro(new_york, [chicago, filadelfia, san_francisco, los_angeles, denver]) ?    
Call:  ( 13) membro(new_york, [filadelfia, san_francisco, los_angeles, denver]) ?    
Call:  ( 14) membro(new_york, [san_francisco, los_angeles, denver]) ?    
Call:  ( 15) membro(new_york, [los_angeles, denver]) ?    
Call:  ( 16) membro(new_york, [denver]) ?    
Call:  ( 17) membro(new_york, []) ?    
Fail:  ( 17) membro(new_york, []) ?    
Redo:  ( 16) membro(new_york, [denver]) ?    
Fail:  ( 16) membro(new_york, [denver]) ?    
Redo:  ( 15) membro(new_york, [los_angeles, denver]) ?    
Fail:  ( 15) membro(new_york, [los_angeles, denver]) ?    
Redo:  ( 14) membro(new_york, [san_francisco, los_angeles, denver]) ?    
Fail:  ( 14) membro(new_york, [san_francisco, los_angeles, denver]) ?    
Redo:  ( 13) membro(new_york, [filadelfia, san_francisco, los_angeles, denver]) ?    
Fail:  ( 13) membro(new_york, [filadelfia, san_francisco, los_angeles, denver]) ?    
Redo:  ( 12) membro(new_york, [chicago, filadelfia, san_francisco, los_angeles, denver]) ?    
Fail:  ( 12) membro(new_york, [chicago, filadelfia, san_francisco, los_angeles, denver]) ?    
Redo:  ( 11) membro(new_york, [boston, chicago, filadelfia, san_francisco, los_angeles, denver]) ?    
Fail:  ( 11) membro(new_york, [boston, chicago, filadelfia, san_francisco, los_angeles, denver]) ?  ^ 

Mentre con il goal:
?- trace, member(los_angeles,[boston,chicago,filadelfia,
 san_francisco, los_angeles,denver]).
otteniamo
Call:  ( 16) membro(los_angeles, [boston, chicago, filadelfia, san_francisco, los_angeles, denver]) ?    
Call:  ( 17) membro(los_angeles, [chicago, filadelfia, san_francisco, los_angeles, denver]) ?    
Call:  ( 18) membro(los_angeles, [filadelfia, san_francisco, los_angeles, denver]) ?    
Call:  ( 19) membro(los_angeles, [san_francisco, los_angeles, denver]) ?    
Call:  ( 20) membro(los_angeles, [los_angeles, denver]) ?    
Exit:  ( 20) membro(los_angeles, [los_angeles, denver]) ?    
Exit:  ( 19) membro(los_angeles, [san_francisco, los_angeles, denver]) ?    
Exit:  ( 18) membro(los_angeles, [filadelfia, san_francisco, los_angeles, denver]) ?    
Exit:  ( 17) membro(los_angeles, [chicago, filadelfia, san_francisco, los_angeles, denver]) ?    
Exit:  ( 16) membro(los_angeles, [boston, chicago, filadelfia, san_francisco, los_angeles, denver]) ?    
Notiamo che la ricorsione si ferma quando avviene la chiamata membro(los_angeles, [los_angeles, denver]) in quanto si può soddisfare questo goal direttamente, usando il fatto, e non la regola ricorsiva.

liste/es4.pl - Approfondimenti: pericoli insiti nella ricorsione

Usando i fatti:
genitore(tom,bob). 
genitore(bob,pat).  
genitore(pat,jim).  
e le clausole:
 antenato2(X,Y) :- genitore(X,Z),antenato2(Z,Y).
 antenato2(X,Y) :- genitore(X,Y).
con il goal:
trace,antenato2(tom,jim).
si ottiene:
Call:  ( 12) antenato2(tom, jim) ?    
Call:  ( 13) genitore(tom, _L158) ?    
Exit:  ( 13) genitore(tom, bob) ?    
Call:  ( 13) antenato2(bob, jim) ?    
Call:  ( 14) genitore(bob, _L170) ?    
Exit:  ( 14) genitore(bob, pat) ?    
Call:  ( 14) antenato2(pat, jim) ?    
Call:  ( 15) genitore(pat, _L182) ?    
Exit:  ( 15) genitore(pat, jim) ?    
Call:  ( 15) antenato2(jim, jim) ?    
Call:  ( 16) genitore(jim, _L194) ?    
Fail:  ( 16) genitore(jim, _L194) ?    
Redo:  ( 15) antenato2(jim, jim) ?    
Call:  ( 16) genitore(jim, jim) ?    
Fail:  ( 16) genitore(jim, jim) ?    
Redo:  ( 15) antenato2(jim, jim) ?    
Fail:  ( 15) antenato2(jim, jim) ?    
Redo:  ( 14) antenato2(pat, jim) ?    
Call:  ( 15) genitore(pat, jim) ?    
Exit:  ( 15) genitore(pat, jim) ?    
Exit:  ( 14) antenato2(pat, jim) ?    
Exit:  ( 13) antenato2(bob, jim) ?    
Exit:  ( 12) antenato2(tom, jim) ? 
usando la definizione:
 antenato3(X,Y) :- genitore(X,Y).
 antenato3(X,Y) :- genitore(X,Z),antenato3(Z,Y).

ed il goal:
trace, antenato3(tom,jim).
si ottiene:
Call:  ( 13) antenato3(tom, jim) ?    
Call:  ( 14) genitore(tom, jim) ?    
Fail:  ( 14) genitore(tom, jim) ?    
Redo:  ( 13) antenato3(tom, jim) ?    
Call:  ( 14) genitore(tom, _L167) ?    
Exit:  ( 14) genitore(tom, bob) ?    
Call:  ( 14) antenato3(bob, jim) ?    
Call:  ( 15) genitore(bob, jim) ?    
Fail:  ( 15) genitore(bob, jim) ?    
Redo:  ( 14) antenato3(bob, jim) ?    
Call:  ( 15) genitore(bob, _L179) ?    
Exit:  ( 15) genitore(bob, pat) ?    
Call:  ( 15) antenato3(pat, jim) ?    
Call:  ( 16) genitore(pat, jim) ?    
Exit:  ( 16) genitore(pat, jim) ?    
Exit:  ( 15) antenato3(pat, jim) ?    
Exit:  ( 14) antenato3(bob, jim) ?    
Exit:  ( 13) antenato3(tom, jim) ? 

liste/es5.pl - Conc(Append): concatena due liste

Definito il predicato:
conc([],L,L).
conc([X|L1],L2,[X|L3]) :- conc(L1,L2,L3).
per concatenare due liste:
?- conc([a,b,c],[d,e,f],L).

L = [a, b, c, d, e, f]
Yes
per dividere in due parti una lista:
?- conc(X,Y,[a,b,c]).

X = []
Y = [a, b, c]
Yes

X = [a]
Y = [b, c]
Yes

X = [a, b]
Y = [c]
Yes

X = [a, b, c]
Y = []
Yes

liste/es6.pl - Sublist

La definizione di sublist è la seguente:
sublist(S,L) :-
  conc(L2,L3,L), % la lista L viene divisa nelle due parti L2 e L3
  conc(L1,S,L2). % la lista L1 viene a sua volta divisa in L1 e S
Un possibile goal è il seguente:
?- sublist([b,c,d],[a,b,c,d,e]).
Le possibili sottoliste di [a,b,c,d,e] si ottengono con il goal
?- sublist(S,[a,b,c,d,e]).
Tuttavia se non si vogliono avere fra le rispote liste vuote, si può usare come goal il seguente:
?- sublist(S,[a,b,c,d,e]),S=[_|_].
Il sottogoal S=[_|_] assicura che S abbia una testa e una coda, e quindi che S non sia la lista vuota.

liste/es7.pl - Add - Del - Insert

Avendo dato le seguenti definizioni :
% add
add(X,L,[X|L])

%delete
delete(X,L,L1).
del(X,[T|C],[T|C1]) :- del(X,C,C1).

%insert
insert(X,L,L1) :- delete(X,L1,L).
si ottiene:
?- add(x,[y,z,t],L).

L = [x, y, z, t]
Yes


?- del(b,[a,b,c,b,d,b],L).


L = [a, c, b, d, b]
Yes

L = [a, b, c, d, b]
Yes

L = [a, b, c, b, d]
Yes



?- insert(z,[a,b,c,d,e],L).


L = [z, a, b, c, d, e]
Yes

L = [a, z, b, c, d, e]
Yes

L = [a, b, z, c, d, e]
Yes

L = [a, b, c, z, d, e]
Yes

L = [a, b, c, d, z, e]
Yes

L = [a, b, c, d, e, z]
Yes


liste/es8.pl - Permutazioni degli elementi di una lista

Scrivete un goal per controllare se [b,c,a] è una permutazione di [a,b,c].
?- permutazione([a,b,c],[b,c,a]).
Yes                      
Scrivete inoltre un goal per ottenere tutte le permutazioni degli elementi della lista [a,b,c].
 
?- permutazione([a,b,c],P).

P = [a, b, c]
Yes

P = [b, a, c]
Yes

P = [b, c, a]
Yes

P = [a, c, b]
Yes

P = [c, a, b]
Yes

P = [c, b, a]
Yes