
% Miscellaneous utilites

% $Id: utils.pl,v 2.4 1994/05/05 16:21:57 dbc Exp dbc $

% $Log: utils.pl,v $
% Revision 2.4  1994/05/05  16:21:57  dbc
% Add `size' and `enum'.
%
% Revision 2.3  1994/04/26  15:52:17  dbc
% Add miscellaneous set operations.
% Add `printString'.
%
% Revision 1.1  1994/04/11  10:37:47  dbc
% Initial revision
%
 

% isNth(N, Xs, X) : `X' is the `N'th element of list `Xs'.

isNth(N, Xs, X) :- ground(N), !, N > 0, getNth(N, Xs, X).
isNth(N, Xs, X) :- locate(N, Xs, X).

getNth(1, Xs, X)       :- !, Xs = [X | _].
getNth(N, [_ | Xs], X) :- N1 is N - 1, getNth(N1, Xs, X).

locate(1,  [X | _], X).
locate(N, [_ | Xs], X) :- locate(N1, Xs, X), N is N1 + 1.


% gather : plural of `isNth'.

gather([], _, []).
gather([I | Is], D, [V | Vs]) :- isNth(I, D, V), gather(Is, D, Vs).


% gathers : plural of `gather'.

gathers([], _, []).
gathers([IList | ILists], D, [VList | VLists]) :-
    gather(IList, D, VList),
    gathers(ILists, D, VLists).


% sameSize(As, Bs) : List `As' is same size as list `Bs'.

sameSize([], []).
sameSize([_ | As], [_ | Bs]) :- sameSize(As, Bs).

% sameSizes : plural of `sameSize'

sameSizes([], []).
sameSizes([A | As], [B | Bs]) :- sameSize(A, B), sameSizes(As, Bs).


% size(Xs, N) : List `Xs' is size `N'.

size([], 0).
size([_ | R], N) :- ground(N), !, N > 0, N1 is N - 1, size(R, N1).
size([_ | R], N) :- size(R, N1), N is N1 + 1.
 

% enum(N, [1, 2, ..., N]).
 
enum(N, Is) :- enumFrom(1, N, Is).
 
enumFrom(I, N, [I | Is]) :- I =< N, !, I1 is I + 1, enumFrom(I1, N, Is).
enumFrom(_, _, []).
 

% mapConstant(Cs, Xs, C) : 
% List `Cs' is same size as list `Xs', and every element is `C'.

mapConstant([], [], _).
mapConstant([C | Cs], [_ | Xs], C) :- mapConstant(Cs, Xs, C).


% Miscellaneous ``set'' operations.

union([], X, X).
union([X | R], Y, Z)       :- member(X, Y), !, union(R, Y, Z).
union([X | R], Y, [X | Z]) :- union(R, Y, Z).

unionList([], []).
unionList([S | Ss], V) :- unionList(Ss, U), union(U, S, V).

intersection(X, Y, Z) :- subtract(X, Y, W), subtract(X, W, Z).

subtract(M, [], M).
subtract(M, [X | I], N) :- remove(X, M, P), subtract(P, I, N).

member(X, [X | _]).
member(X, [_ | Y]) :- member(X, Y).

removeMember(X, [X | L], L).
removeMember(X, [Y | L], [Y | M]) :- removeMember(X, L, M).

notMember(_, []).
notMember(X, [X | _]) :- !, fail.
notMember(X, [_ | L]) :- notMember(X, L).

remove(_, [], []).
remove(X, [X | L], L)       :- !.
remove(X, [Y | L], [Y | M]) :- remove(X, L, M).

subset([], _).
subset([X | M], N) :- member(X, N), !, subset(M, N).


% cat(L, A, B) : list `L' is the concatentation of lists `A' and `B'.

cat(L, [], L).
cat([X | LTail], [X | ATail], B) :- cat(LTail, ATail, B).

% catList(L, Ls) : list `L' is the concatenation of list of lists in `Ls'.

catList([], []).
catList(Res, [L | Ls]) :- cat(Res, L, ResTail), catList(ResTail, Ls).


% printString.

printString([]) :- !.
printString([X | T]) :- put(X), printString(T).

