% PD 2007-08: Examen 2 (Grupos 1A y 1B) (14 de enero de 2008)
% ====================================================================== 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 1: Definir en Prolog la relación filtra(+L,+L1,-L2) que
% recibe una lista de predicados unarios, L, y una lista de elementos,
% L1, y devuelve la lista L2 de los elementos de L1 que satisfacen
% alguno de los predicados de L. Por ejemplo, 
%    ?- filtra([number],[1,a,[3],-7,[1,b],d],L).
%    L = [1, -7] 
%    ?- filtra([atom],[1,a,[3],-7,[1,b],d],L).
%    L = [a, d] 
%    ?- filtra([compound],[1,a,[3],-7,[1,b],d],L).
%    L = [[3], [1, b]] 
%    ?- filtra([number, atom],[1,a,[3],-7,[1,b],d],L).
%    L = [1, a, -7, d] 
%    ?- filtra([],[1,a,[3],-7,[1,b],d],L).
%    L = [] 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

filtra(L,L1,L2) :-
   findall(X, (member(X,L1), satisface_alguno(L,X)), L2).

% satisface_alguno(+L,+X) se verifica si X satisface alguno de los
% predicados unarios de L. Por ejemplo,
%    ?- satisface_alguno([number,atom],12).
%    Yes
%    ?- satisface_alguno([number,atom],[1,2]).
%    No
satisface_alguno([P|_],X) :-
   apply(P,[X]).
satisface_alguno([_|L],X) :-
   satisface_alguno(L,X).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ejercicio 3: Definir en Prolog la relación
%    subconjunto_suma(+L1,+N,?L2)
% que se verifique si L2 es un subconjunto de L1 tal que la suma de los
% elementos de L2 es N. Por ejemplo,  
%    ?- subconjunto_suma([10,3,1,7,4,2],7,L).
%    L = [3, 4] ;
%    L = [1, 4, 2] ;
%    L = [7] ;
%    No
%    ?- subconjunto_suma([1,2,3],0,L).
%    L = [] ;
%    No
%    ?- subconjunto_suma([1,2,3],9,L).
%    No
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

subconjunto_suma([],0,[]).
subconjunto_suma([X|L1],N,[X|L2]) :-
   N >= X,
   N1 is N-X,
   subconjunto_suma(L1,N1,L2).
subconjunto_suma([_|L1],N,L2) :-
   subconjunto_suma(L1,N,L2).
