/*Implemente o predicado todos/2, tal que todos(Pred, Lst), em que Pred
é o nome de um predicado unário e Lst é uma lista, significa que todos os elemen-
tos de Lst satisfazem Pred. */

/*True if expression Expr1 evaluates to a number equal to Expr2.*/
par(N):- mod(N,2) =:= 0. 

todos(_, []) :- !.
todos(Pred, [P | R]) :- Lit =.. [Pred, P],writeln(Lit), Lit, todos(Pred, R).


/*algum(Pred, Lst), em que Pred
é o nome de um predicado unário e Lst é uma lista, significa que existe um el-
emento de Lst que satisfaz Pred.*/

algum(Pred, [P | _ ]) :- Lit =.. [Pred, P],  writeln(Lit), Lit, !.
algum(Pred, [_ | R]) :- algum(Pred, R).

/*Pred é o nome de um predicado unário e Lst é uma lista, significa que ex-
istem N elementos de Lst que satisfazem Pred. */

quantos(_, [], 0) :- !.
/*Initialization of N=0*/

quantos(Pred, [P | R], N) :-
                    Lit =.. [Pred, P], Lit, !,
                    quantos(Pred, R, NR), N is NR + 1.
/*Otherwise if Lit false execute this rule, order of the program matters!*/       
quantos(Pred, [_ | R], Q) :-
                    quantos(Pred, R, Q). 

/*Tst é o nome de um predicado unário e Lst1 é uma lista, significa
que Lst2 é a lista formada pelos elementos de Lst1 que satisfazem Tst.*/

filtra_inc([],_, []).
filtra_inc([P | R], Tst, L) :- Lit =.. [Tst, P],
                               write("Lit="),
                               writeln(Lit),
                               Lit, !, L = [P | S], 
                               write("L="),
                               writeln(L),
                               filtra_inc(R, Tst, S).
filtra_inc([_ | R], Tst, S) :- filtra_inc(R, Tst, S).

/*LISTAS*/

/*naoMembro(El, Lst), em que El
é um elemento e Lst é uma lista, significa que El não pertence a Lst*/

naoMembro(_, []).
naoMembro(El, [P | R]) :-
                        El \== P,
                        write("P="),
                        writeln(P),
                        naoMembro(El, R).

/*repete_el(El, N, L) significa
que L é a lista constituída por N (um inteiro não negativo) ocorrências do elemento
El*/

repete_el(El, N, Lst) :-
                    length(Lst, N),
                    writeln(Lst),
                    maplist(unifica(El), Lst),
                    writeln(Lst).
unifica(X, Y) :- X = Y.

/*maplist(P,L,M) succeeds by applying the predicate P to each element of list L */
