% Lecture slide 25
% append(L1,L2,L3) holds if L3 is the result of appending L1 and L2
append([],L,L).
append([X|L1],L2,[X|L3]) :- append(L1,L2,L3).
% Lecture slide 26/29
% member(E,L) holds if E is an element of list L
member(X,[X|_]).
member(X,[_|L]) :- member(X,L).
% Lecture slide 30
% swap_first_two(L1,L2) holds if list L1 is list L2 with the two first
% elements swapped.
swap_first_two([X,Y|L],[Y,X|L]).
% Lecture slide 31
% length(L,N) holds if N is the length of list L.
% This is the code we saw in class, and as we saw it does not work
% properly if N is pre-specified.
% length1(L,N) works if N is a variable
% Precondition: N is a variable
length1([], 0).
length1([_|R], N) :- length1(R, N1), N is N1 + 1.
% This is an alternate version which we didn't discuss in class, which
% works when N is a number.
% length2(L,N) works if N is specified
% Precondition: N is a number
length2(L,N) :- N =< 0, !, L = [].
length2(L,N) :- N1 is N-1, L=[_|L1],
length2(L1,N1).
% Finally, this length predicate puts the two versions above together in
% one single predicate which works with any input.
length(L,N) :- var(N), !, length1(L,N); length2(L,N).
% Lecture slide 32
% list_of_elem(L,E,N) holds if L is a list of N elements E. (Broken!)
list_of_elem(L,E,N) :-
all_elem(L,E),
length(L,N).
% all_elem(L,E) holds if L is a list of elements E.
all_elem([],_).
all_elem([E|L],E) :-
all_elem(L,E).
% Lecture slide 33
% working_list_elem(L,E,N) holds if L is a list of N elements E. (Fixed!)
working_list_elem(L,E,N) :-
length(L,N),
all_elem(L,E).
% Lecture slide 56
% sumlist(L,S) holds if S is the sum of all elements of L
% Precondition: L must be a list of numbers.
sumlist([],0).
sumlist([N|L],S) :- sumlist(L,T),
S is N + T.