% vim: set ft=prolog:

%% tamanho(+L, ?T) is semidet
%
%  Verdadeiro se T é a quantidade de elementos de L.
%  Predicado pré-definido: length/2.
%  Exemplos
%  ?- tamanho([4, 5, 2], T).
%  T = 3.
%  ?- tamanho([7], 1).
%  true.

tamanho([], 0).

tamanho([_|R], T) :-
    tamanho(R, T0),
    T is T0 + 1.

%% tamanho_acc(+L, ?T) is semidet
%  Versão de tamanho usando acumulador.
%  Exemplos
%  ?- tamanho_acc([4, 5, 2], T).
%  T = 3.
%  ?- tamanho_acc([7], 1).
%  true.

tamanho_acc(L, T) :-
    tamanho_acc(L, 0, T).

%% tamanho(+L, +Acc, ?T) is semidet
%
%  Verdadeiro se T é a quantidade de elemetos de L + Acc.
%  Exemplo
%  ?- tamanho_acc([4, 5, 2], 15, T).
%  T = 18.

tamanho_acc([], Acc, Acc).

tamanho_acc([_|R], Acc, T) :-
    Acc1 is Acc + 1,
    tamanho_acc(R, Acc1, T).

%% intervalo(+A, +B, ?R) is semidet
%
%  Verdadeiro se R é uma lista com os valores A, A + 1, .., B
%  Exemplos
%  ?- intervalo(3, 7, R).
%  R = [3, 4, 5, 6, 7].
%  ?- intervalo(4, 2, R).
%  R = [].

intervalo(A, B, []) :-
    A > B, !.

intervalo(A, B, [A|R]) :-
    A =< B,
    A1 is A + 1,
    intervalo(A1, B, R).

%% pares(+X, ?P) is semidet
%
%  Verdadeiro se P contém apenas os elementos pares de X.
%  Exemplos
%  ?- pares([4, 5, 7, 2, 8], P).
%  P = [4, 2, 8].
%  ?- pares([1, 3, 5], P).
%  P = [].

pares([], []).

pares([X|Xs], [X|P]) :-
    par(X), !,
    pares(Xs, P).

pares([X|Xs], P) :-
    impar(X),
    pares(Xs, P).

par(X) :-
    X mod 2 =:= 0.

impar(X) :-
    \+ par(X).

%% concat(?A, ?B, ?C) is nondet
%  
%  Verdadeiro se C é a contatenação de A com B.
%  Predicado pré-definido: append/3
%  Exemplos
%  ?- concat([1, 7], [2, 5], C).
%  C = [1, 7, 2, 5].
%  ?- concat(A, [8], [1, 4, 8]).
%  A = [1, 4].
%  ?- concat([5, 2], B, [5, 2, 3]).
%  B = [3].

concat([], B, B) :- !.

concat([A|As], B, [A|Cs]) :-
    concat(As, B, Cs).

%% reverso(?A, ?R) is nondet 
%
%  Verdadeiro se R é o reverso de A.
%  Predicado pré-definido: reverse/2
%  Exemplos
%  ?- reverso([4, 3, 8], R).
%  R = [8, 3, 4].
%  ?=- reverso(A, [6, 9, 2, 1]).
%  A = [1, 2, 9, 6].

reverso([], []).

reverso([A|As], R) :-
    reverso(As, Rs),
    concat(Rs, [A], R).

%% reverso_acc(+A, ?R) is nondet
%
%  Versão de reverso/2 usando acumulador.

reverso_acc(A, R) :-
    reverso_acc(A, [], R).

reverso_acc([], Acc, Acc) :- !.

reverso_acc([A|As], Acc, R) :-
    Acc1 = [A|Acc],
    reverso_acc(As, Acc1, R).
