/* memb( X,L) if X occurs in the list L; member is built in! */
memb( X, [X | _]).
memb( X, [Head | Tail]) :- memb( X, Tail).

/* conc( L1,L2,L3) if L3 is the concatenation (juxtaposition) of L1 and L2 */
conc( [],L,L).
conc( [ X | L1], L2, [ X | L3]) :- conc( L1,L2,L3).
memb1( X,L) :- conc( L1, [ X | L2], L).  % alternative member

/* add( X, L, L1) if L1 is the list resulting from adding X 
at the beginning of to L */
add( X, L, [ X | L]).

/* del( X, L, L1) if L1 is the list resulting from deleting
   one occurrence of X from L
   SWI-Prolog's delete/3 deletes _all_ occurrences of X from L                        */
del( X, [ X | L], L).
del( X, [ Y | Tail], [ Y | Tail1]) :- del( X, Tail, Tail1).

/* insert( X, L, L1) if L1 is the result of inserting X into L in some place */
insert( X, L, L1) :- del( X, L1, L).
memb2( X,List) :- del( X,List,_).  % alternative member

/* sublist( S,L) if S is a sublist of L; sublist/3 is built in:
        sublist(+Pred, +List1, ?List2)
        Unify List2 with a list of all elements of List1 to which Pred applies. */
sublist( S,L) :- conc( L1,L2,L), conc( S,L3,L2b).

/* permutation( L1,L2) if L1 is a permutation of L2
  Neither versions are completely general.  See Bratko, pp.71-72 */
permutation( [],[]).
permutation( [ X | L], P) :-
  permutation( L,L1),
  insert( X,L1,P).
perm2( [],[]).
perm2( L,[ X | P]) :-
  del( X,L,L1),
  perm2( L1,P).

/* Ex 3.6 */
shift([],[]).
shift([H|T], L2) :- conc(T,[H],L2).
