A list is an ordered sequence of elements that can have any length. Lists are a common data structure in computer programming.
In Prolog, lists are represented as a tree consisting of structures that have no arguments, an empty list, or two arguments: a head and a tail. The head is a used to store a particular term in the list and the tail is recursively the rest of the list. The end of a list is customarily represented as a tail that is set to an empty list.
The data structure used to represent lists in Prolog has a functor (name) of ".
". Thus, a list with the single element a
can be represented as: .(a, .())
and a list with elements a
, b
and c
can be represented as: .(a, .(b, .(c, .())))
. Prolog also supports a more concise syntax for writing lists. List notation consists of elements of the list separated by commas, and the whole list enclosed in square brackets. Thus, a list with the single element a
can be represented as: [a]
and a list with elements a
, b
and c
can be represented as: [a, b, c]
. An empty list can be represented by a opening square bracket followed by a closing square bracket: []
.
It is common for Prolog programs to manipulate lists by splitting them into a head and a tail. The |
character has a special meaning in Prolog syntax to separate the head and tail of a list. Thus the Prolog syntax [X|Y]
represents a list with head X
and tail Y
.
Examples
Determining if a term is a list. (Note: Projog provides a built-in is_list(X) predicate.)
list([]).
list([X|Xs]) :- list(Xs).
?- list([a,b,c]).
yes
?- list(abc).
no
Determining is a term is contained in a list. (Note: Projog provides built-in member(X,Y) and memberchk(X,Y) predicates.)
list_member(X,[X|Xs]).
list_member(X,[Y|Ys]) :- list_member(X,Ys).
?- list_member(X, [a,b,c]).
X = a
yes;
X = b
yes;
X = c
yes;
no
?- list_member(a, [a,b,c]).
yes;
no
?- list_member(b, [a,b,c]).
yes;
no
?- list_member(c, [a,b,c]).
yes;
no
?- list_member(d, [a,b,c]).
no
?- list_member(a,[a,a,a]).
yes;
yes;
yes;
no
Finding prefixes of a list.
prefix([],Ys).
prefix([X|Xs],[X|Ys]) :- prefix(Xs,Ys).
?- prefix(X, [a,b,c,d,e,f]).
X = []
yes;
X = [a]
yes;
X = [a,b]
yes;
X = [a,b,c]
yes;
X = [a,b,c,d]
yes;
X = [a,b,c,d,e]
yes;
X = [a,b,c,d,e,f]
yes;
no
?- prefix([a],[a,b,c]).
yes
?- prefix([a,b],[a,b,c]).
yes
?- prefix([a,b,c],[a,b,c]).
yes
?- prefix([x,a,b,c],[a,b,c]).
no
?- prefix([a,c],[a,b,c]).
no
?- prefix([b,c],[a,b,c]).
no
?- prefix([X,b],[a,b,c]).
X = a
yes;
no
Finding suffixes of a list.
suffix(Xs,Xs).
suffix(Xs,[Y|Ys]) :- suffix(Xs,Ys).
?- suffix(X, [a,b,c,d,e,f]).
X = [a,b,c,d,e,f]
yes;
X = [b,c,d,e,f]
yes;
X = [c,d,e,f]
yes;
X = [d,e,f]
yes;
X = [e,f]
yes;
X = [f]
yes;
X = []
yes;
no
?- suffix([c],[a,b,c]).
yes;
no
?- suffix([b,c],[a,b,c]).
yes;
no
?- suffix([a,b,c],[a,b,c]).
yes;
no
?- suffix([x,a,b,c],[a,b,c]).
no
?- suffix([a,c],[a,b,c]).
no
?- suffix([a,b],[a,b,c]).
no
?- suffix([X,c],[a,b,c]).
X = b
yes;
no
Determining sublists of lists.
sublist(Xs,Ys) :- prefix(Xs,Ys).
sublist(Xs,[Y|Ys]) :- sublist(Xs,Ys).
?- sublist([a,b,c],[a,b,c,d,e,f]).
yes;
no
?- sublist([b,c,d],[a,b,c,d,e,f]).
yes;
no
?- sublist([c,d,e],[a,b,c,d,e,f]).
yes;
no
?- sublist([b,c,e],[a,b,c,d,e,f]).
no
?- sublist([b,X,d],[a,b,c,Y,e,f]).
X = c
Y = d
yes;
no
Appending two lists. (Note: Projog provides a built-in append(X,Y,Z) predicate.)
append_to_list([],Ys,Ys).
append_to_list([X|Xs],Ys,[X|Zs]) :- append_to_list(Xs,Ys,Zs).
?- append_to_list([a,b,c],[d,e,f],[a,b,c,d,e,f]).
yes
?- append_to_list([a,b,c],[d,e,f],[a,b,c,d,e,g]).
no
?- append_to_list([a,b,c],[d,e,f],[a,b,c,d,e,f,g]).
no
?- append_to_list([a,X,c],[d,e,Y],[a,b,c,Z,e,f]).
X = b
Y = f
Z = d
yes;
no
?- append_to_list([a,X,c],[Y,e(X,Y),f],[a,b,c,d,Z,f]).
X = b
Y = d
Z = e(b, d)
yes;
no
?- append_to_list([a,b,c],[d,e,f],X).
X = [a,b,c,d,e,f]
yes
?- append_to_list([a,b,c],X,[a,b,c,d,e,f]).
X = [d,e,f]
yes
?- append_to_list(X,[d,e,f],[a,b,c,d,e,f]).
X = [a,b,c]
yes;
no
Reversing the order of terms in a list. (Note: Projog provides a built-in reverse(X,Y) predicate.)
reverse_list(Xs,Ys) :- reverse_list(Xs,[],Ys).
reverse_list([X|Xs],Acc,Ys) :- reverse_list(Xs,[X|Acc],Ys).
reverse_list([],Ys,Ys).
?- reverse_list([],[]).
yes
?- reverse_list([a],[a]).
yes;
no
?- reverse_list([a],[b]).
no
?- reverse_list([a,b],[b,a]).
yes;
no
?- reverse_list([a,b],[a,b]).
no
?- reverse_list([a,b],[a,a]).
no
?- reverse_list([a,b],[b,b]).
no
?- reverse_list([a,b],[a]).
no
?- reverse_list([a,b],[b]).
no
?- reverse_list([a,b],[c,b,a]).
no
?- reverse_list([a,b,c,d,e,f],[f,e,d,c,b,a]).
yes;
no
?- reverse_list([a,b,c,d,e,f],[f,e,d,c,a,b]).
no
?- reverse_list([a,b,c,X,e,Y],[f,Z,d,c,b,a]).
X = d
Y = f
Z = e
yes;
no
?- reverse_list([a,b,c,d,e,f],X).
X = [f,e,d,c,b,a]
yes;
no
?- reverse_list([a,b,c,[1,2,3]],X).
X = [[1,2,3],c,b,a]
yes;
no
Determine if elements are next to each other in a list.
adjacent(X,Y,Zs) :- append_to_list(As,[X,Y|Ys],Zs).
?- adjacent(a,b,[a,b,c,d,e,f]).
yes;
no
?- adjacent(c,d,[a,b,c,d,e,f]).
yes;
no
?- adjacent(e,f,[a,b,c,d,e,f]).
yes;
no
?- adjacent(a,c,[a,b,c,d,e,f]).
no
?- adjacent(b,z,[a,b,c,d,e,f]).
no
?- adjacent(b,X,[a,b,c,d,e,f]).
X = c
yes;
no
?- adjacent(X,e,[a,b,c,d,e,f]).
X = d
yes;
no
?- adjacent(X,Y,[a,b,c,d,e,f]).
X = a
Y = b
yes;
X = b
Y = c
yes;
X = c
Y = d
yes;
X = d
Y = e
yes;
X = e
Y = f
yes;
no
Find the last element of a list. (Note: Projog provides a built-in last(X,Y) predicate.)
last_element(X,Xs) :- append_to_list(As,[X],Xs).
?- last_element(f,[a,b,c,d,e,f]).
yes;
no
?- last_element(a,[a,b,c,d,e,f]).
no
?- last_element(b,[a,b,c,d,e,f]).
no
?- last_element(c,[a,b,c,d,e,f]).
no
?- last_element(d,[a,b,c,d,e,f]).
no
?- last_element(e,[a,b,c,d,e,f]).
no
?- last_element(f,[a,b,c,d,e,f]).
yes;
no
?- last_element(z,[a,b,c,d,e,f]).
no
?- last_element(X,[a,b,c,d,e,f]).
X = f
yes;
no
?- last_element(f,[a,b,c,d,e,X]).
X = f
yes;
no
Get a count of the number of terms contained in a list. (Note: Projog provides a built-in length(X,Y) predicate.)
list_length([],0).
list_length([X|Xs],A) :- list_length(Xs,B), A is B+1.
?- list_length([],X).
X = 0
yes
?- list_length([a],X).
X = 1
yes;
no
?- list_length([a,b],X).
X = 2
yes;
no
?- list_length([a,b,c,d,e,f],X).
X = 6
yes;
no
?- list_length([a,b,c,d,e,f],6).
yes;
no
?- list_length([a,b,c,d,e,f],5).
no
Delete elements from a list. (Note: Projog provides a built-in delete(X,Y,Z) predicate.)
delete_from_list([X|Xs],X,Ys) :- delete_from_list(Xs,X,Ys).
delete_from_list([X|Xs],Z,[X|Ys]) :- \+ X==Z, delete_from_list(Xs, Z, Ys).
delete_from_list([],X,[]).
?- delete_from_list([a,z,c],z,[a,c]).
yes;
no
?- delete_from_list([a,z,c],y,X).
X = [a,z,c]
yes;
no
?- delete_from_list([z,a,z,z,b,c,z,d,e,f,z],z,[a,b,c,d,e,f]).
yes;
no
?- delete_from_list([z,a,z,z,b,c,z,d,e,f,z],X,[a,b,c,d,e,f]).
X = z
yes;
no
Select elements from a list. (Note: Projog provides a built-in select(X,Y,Z) predicate.)
select_from_list(X,[X|Xs],Xs).
select_from_list(X,[Y|Ys],[Y|Zs]) :- select_from_list(X,Ys,Zs).
?- select_from_list(b,[a,b,c],[a,c]).
yes;
no
?- select_from_list(z,[a,b,c],[a,b,c]).
no
?- select_from_list(z,[z,a,z,z,b,c,z,d,e,f,z],X).
X = [a,z,z,b,c,z,d,e,f,z]
yes;
X = [z,a,z,b,c,z,d,e,f,z]
yes;
X = [z,a,z,b,c,z,d,e,f,z]
yes;
X = [z,a,z,z,b,c,d,e,f,z]
yes;
X = [z,a,z,z,b,c,z,d,e,f]
yes;
no
Checks terms in list are ordered.
ordered([]).
ordered([X]).
ordered([X,Y|Ys]) :- X @=< Y, ordered([Y|Ys]).
?- ordered([a,b,c,d,e,f]).
yes;
no
?- ordered([a,b,c,e,d,f]).
no
Find permuatations of terms in a list.
permutation(Xs,[Z|Zs]) :- select_from_list(Z,Xs,Ys), permutation(Ys,Zs).
permutation([],[]).
?- permutation([a,b],X).
X = [a,b]
yes;
X = [b,a]
yes;
no
?- permutation([a,b,c],X).
X = [a,b,c]
yes;
X = [a,c,b]
yes;
X = [b,a,c]
yes;
X = [b,c,a]
yes;
X = [c,a,b]
yes;
X = [c,b,a]
yes;
no
?- permutation([a,b,c,d,e,f],[f,e,d,c,b,a]).
yes;
no
?- permutation([q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m],[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,Z]).
Z = z
yes;
no