list_length([], 0).
list_length([_|T], N) :- list_length(T, N1), N is N1 + 1.

%% 1. Find the sum of all elements of the list L
sum_elements([], 0).
sum_elements([H|T], N) :- sum_elements(T, N1), N is N1 + H.

%% 2. Find the sum of all even elements of the list L
even_sum([], 0).
even_sum([H|T], N) :- even_sum(T, N1), N is N1 + H, 0 is mod(H, 2).
even_sum([_|T], N) :- even_sum(T, N).

%% 3. Find the max element
% max_element(M, L) :- M is the largest element of the list L
max_element(H, [H]).
max_element(H, [H|T]) :- max_element(Y, T), H >= Y.
max_element(Y, [H|T]) :- max_element(Y, T), Y > H.

%% 4. Check if nondecreasing list is given
nondecreasing([]).
nondecreasing([_]).
nondecreasing([F, S|T]) :- F =< S, nondecreasing([S|T]).

%% 5. Sort a list using permutations
member(H, [H|_]).
member(X, [_|T]) :- member(X, T).

append([], L, L).
append([X|T], L, [X|M]) :- append(T, L, M).

remove_first(E, L, M) :- append(A, [E|B], L), not(member(E, A)), append(A, B, M).

perm([], []).
perm([H|T], M) :- member(H, M), remove_first(H, M, N), perm(T,N).

sorted(L) :- not((append(_, [A, B|_], L), A >=B)).

sort_list(L, S) :- perm(S, L), sorted(S).

%% Last element of a list
last_element(X, [X]).
last_element(X, [_|T]) :- last_element(X, T).

%% Find the k-th element of a list
k_element(X, [X|_], 1).
k_element(X, [_|T], K) :- K > 1, K1 is K - 1, k_element(X, T, K1).

%% reverse_list(L, R) :- R is the reverse of L
rev([], A, A).
rev([H|T], Acc, R) :- rev(T, [H|Acc], R).

reverse_list(L, R) :- rev(L, [], R).
