% Programs B.2
% Utility predicates
% append(Xs, Ys, Zs) ---list Zs is list Xs followed by list Ys

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


% reverse(Xs, Ys) ---list Ys is list Xs in reverse order

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


% Prolog code which executes other Prolog code, such as would be
% enclosed between curly braces in BH-GRN rules

'{}'(X) :- call(X).

evaluate(no_code) :- !.
evaluate(((C1), C2)) :- !, evaluate(C1), evaluate(C2).
evaluate(Code) :- !, call(Code).


% remove(X, Ys, Zs) ---lists Zs is the results of removing an occurrence of
%                      item X from list Ys

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


% member(X, Ys) ---determine whether X is a member of list Ys

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


% read_string(Xs)  ---Xs will be a list of atoms read in from user input
%                     This code is based on code given in Clocksin & Mellish (1984)

read_string(Words) :-
   get0(Char),
   read_string(Char, Words).

read_string(C, []) :- newline(C), !.

read_string(C, Words) :- space(C), !,
   get0(Char),
   read_string(Char, Words).

read_string(Char, [Word|Words]) :-
   read_word(Char, Chars, Next),
   name(Word, Chars),
   read_string(Next, Words).


read_word(C, [], C) :- space(C), !.
read_word(C, [], C) :- newline(C), !.

read_word(Char, [Char|Chars], Last) :-
   get0(Next),
   read_word(Next, Chars, Last).


space(32).

newline(10).


% length(Xs, N) ---N is the length of list Xs
%               ---This is in-built in our Prolog, so we have commented out
%               ---this definition.

% length([], 0).
% length([X|Xs], N) :- length(Xs, M), N is M+1.


% subset(Xs, Ys) ---determine whether all members of list Xs are contained
% in list Ys

subset([], Ys).
subset([X|Xs], Ys) :- member(X, Ys), subset(Xs, Ys).


SJ Harlow