Prolog library: listut.pl
pereira at sri-unix.UUCP
pereira at sri-unix.UUCP
Mon Aug 15 15:54:13 AEST 1983
% File : LISTUT.PL
% Author : Lawrence Byrd + R.A.O'Keefe
% Updated: 20 May 1983
% Purpose: list processing utilities
% This module requires
% select/3 (from SetUtl.Pl) for perm/2
% listtoset/2 (from SetUtl.Pl) for remove_dups/2
% If you don't want those routines, it can be used on its own.
% The code was originally written by Lawrence Byrd. The layout
% and comments are by R.A.O'Keefe.
:- public
append/3, % List x List -> List
correspond/4, % Elem <- List x List -> Elem
delete/3, % List x Elem -> List
last/2, % List -> Elem
nextto/3, % Elem, Elem <- List
nmember/3, % Elem <- Set -> Integer
numlist/3, % Integer x Integer -> List
perm/2, % List -> List
perm2/4, % Elem x Elem -> Elem x Elem
remove_dups/2, % List -> Set
rev/2, % List -> List
reverse/2, % List -> List
sumlist/2. % List -> Integer
:- mode
append(?, ?, ?),
correspond(?, +, +, ?),
delete(+, +, -),
last(?, ?),
nextto(?, ?, ?),
nmember(?, +, ?),
numlist(+, +, ?),
perm(?, ?),
perm2(?,?, ?,?),
remove_dups(+, ?),
rev(?, ?),
reverse(?, ?),
reverse(?, +, ?),
sumlist(+, ?),
sumlist(+, +, ?).
% append(Prefix, Suffix, Combined)
% is true when all three arguments are lists, and the members of Combined
% are the members of Prefix followed by the members of Suffix. It may be
% used to form Combined from a given Prefix and Suffix, or to take a given
% Combined apart. E.g. we could defined member/2 (from SetUtl.Pl) as
% member(X, L) :- append(_, [X|_], L).
append([], L, L).
append([H|T], L, [H|R]) :-
append(T, L, R).
% correspond(X, Xlist, Ylist, Y)
% is true when Xlist and Ylist are lists, X is an element of Xlist, Y is
% an element of Ylist, and X and Y are in similar places in their lists.
correspond(X, [X|_], [Y|_], Y) :- !.
correspond(X, [_|T], [_|U], Y) :-
correspond(X, T, U, Y).
% delete(List, Elem, Residue)
% is true when List is a list, in which Elem may or may not occur, and
% Residue is a copy of List with all elements equal to Elem deleted.
delete([], _, []) :- !.
delete([Kill|Tail], Kill, Rest) :- !,
delete(Tail, Kill, Rest).
delete([Head|Tail], Kill, [Head|Rest]) :- !,
delete(Tail, Kill, Rest).
% last(Last, List)
% is true when List is a List and Last is its last element. This could
% be defined as last(X,L) :- append(_, [X], L).
last(Last, [Last]) :- !.
last(Last, [_|List]) :-
last(Last, List).
% nextto(X, Y, List)
% is true when X and Y appear side-by-side in List. It could be written as
% nextto(X, Y, List) :- append(_, [X,Y], List).
% It may be used to enumerate successive pairs from the list.
nextto(X,Y, [X,Y|_]).
nextto(X,Y, [_|List]) :-
nextto(X,Y, List).
% nmember(Elem, List, Index)
% is true when Elem is the Indexth member of List. Could be written as
% nmember(X, L, N) :- append(B, [X|_], L), length(B, M), N is M+1.
% It may be used to select a particular element, or to find where some
% given element occurs, or to enumerate the elements and indices together.
nmember(Elem, [Elem|_], 1).
nmember(Elem, [_|List], N) :-
nmember(Elem, List, M),
N is M+1.
% numlist(Lower, Upper, List)
% is true when List is [Lower, ..., Upper]
% Note that Lower and Upper must be integers, not expressions, and
% that if Upper < Lower numlist will FAIL rather than producing an
% empty list.
numlist(Upper, Upper, [Upper]) :- !.
numlist(Lower, Upper, [Lower|Rest]) :-
Lower < Upper,
Next is Lower+1,
numlist(Next, Upper, Rest).
% perm(List, Perm)
% is true when List and Perm are permutations of each other. Of course,
% if you just want to test that, the best way is to keysort/2 the two
% lists and see if the results are the same. Or you could use list_to_bag
% (from BagUtl.Pl) to see if they convert to the same bag. The point of
% perm is to generate permutations. The arguments may be either way round,
% the only effect will be the order in which the permutations are tried.
% Be careful: this is quite efficient, but the number of permutations of an
% N-element list is N!, even for a 7-element list that is 5040.
perm([], []).
perm(List, [First|Perm]) :-
select(First, List, Rest), % tries each List element in turn
perm(Rest, Perm).
% perm2(A,B, C,D)
% is true when {A,B} = {C,D}. It is very useful for writing pattern
% matchers over commutative operators. It is used more than perm is.
perm2(X,Y, X,Y).
perm2(X,Y, Y,X).
% remove_dups(List, Pruned)
% removes duplicated elements from List. Beware: if the List has
% non-ground elements, the result may surprise you.
remove_dups(List, Pruned) :-
listtoset(List, Pruned).
% reverse(List, Reversed)
% is true when List and Reversed are lists with the same elements
% but in opposite orders. rev/2 is a synonym for reverse/2.
rev(List, Reversed) :-
reverse(List, [], Reversed).
reverse(List, Reversed) :-
reverse(List, [], Reversed).
reverse([], Reversed, Reversed).
reverse([Head|Tail], Sofar, Reversed) :-
reverse(Tail, [Head|Sofar], Reversed).
% sumlist(Numbers, Total)
% is true when Numbers is a list of integers, and Total is their sum.
% Note that in Dec-10 compiled Prolog this will only work as stated;
% interpreters will almost certainly accept integer expressions. Also
% note here as elsewhere in Prolog arithmetic that machine arithmetic
% wraps round: on the Dec-10 (2^17 - 1)+1 = -2^17 .
sumlist(Numbers, Total) :-
sumlist(Numbers, 0, Total).
sumlist([], Total, Total).
sumlist([Head|Tail], Sofar, Total) :-
Next is Sofar+Head,
sumlist(Tail, Next, Total).
More information about the Comp.sources.unix
mailing list