% prefix(list, list):
%   prefix(Xs, Ys) true iff Xs is a prefix of Ys
%
% NB: named prefix1 since prefix is a builtin

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


% suffix(list, list):
%   suffix(Xs, Ys) true iff Xs is a suffix of Ys
% NB: named suffix1 since suffix is a builtin

% unnecessary clause that causes multiple [] answers:
% suffix1([], Ys).
suffix1(Xs, Xs).
suffix1(Xs, [Y|Ys]) :- suffix1(Xs, Ys).


% implementations in terms of append:

% Xs is a prefix of Ys if Xs appended with something is equal to Ys
%
% [ ... Xs ... ] [ ... something ... ]
% [ .............. Ys .............. ]
prefix2(Xs, Ys) :- append(Xs, _, Ys).

% Xs is a suffix of Ys if something appended with Xs is equal to Ys
%
% [ ... something ... ] [ ... Xs ... ]
% [ .............. Ys .............. ]
suffix2(Xs, Ys) :- append(_, Xs, Ys).



% minimum defined using a green cut: since the clauses have mutually
% exclusive preconditions, the cut does not eliminate any solutions,
% just needless search.
minimum(X, Y, X) :- X =< Y, !.
minimum(X, Y, Y) :- X > Y.

% minimum INCORRECTLY defined using a red cut: this cut is supposed to
% eliminate extraneous solutions once X =< Y has been established.  the
% second precondition has been deleted since if X not =< Y, it must be
% the case that X > Y, so why bother verifying it?  but the code written
% this way is INCORRECT for certain queries.  See Lecture Notes 14.
badminimum(X, Y, X) :- X =< Y, !.
badminimum(X, Y, Y).
