%%%%%%%%%%%%%%%%%%%%

:-dynamic felice/1.

/* ======= meta-interprete semplice ========== */

solve(true) :- !.
solve((G1,G2)) :-
        !, solve(G1), solve(G2).
solve(Goal) :-
        clause(Goal,Body),
        solve(Body).


/* ========= fibonacci con memorizzazione dei risultati =========== */

:- dynamic(fib/2).         
fib(1,1).
fib(2,1).
fib(N,F) :-
        N>2,
        N1 is N-1, fib(N1,F1),
        N2 is N-2, fib(N2,F2),
        F is F1+F2,
        asserta(fib(N,F)).

fibb(N,F) :- fib(N,F), !.

cancella_fib :-
        clause(fib(N,F),true),
        N > 2,
        retract(fib(N,F)),
        fail.
cancella_fib.

/* ======= prodotto cartesiano ============ */

:- dynamic found/1.

pair_from((X,Y),A,B) :- member(X,A), member(Y,B).

cartprod(A,B,_) :-
	pair_from(Pair,A,B),
	assertz(found(Pair)),
	fail.
cartprod(_,_,Set) :-
	raccogli(Set). 

raccogli([Pair|Rest]) :-
	retract(found(Pair)), !,
	raccogli(Rest).
raccogli([]).

/*  oppure */
cartprod2(A,B,Cartprod) :-
	findall((X,Y),(member(X,A),member(Y,B)),Cartprod).

/* ======= usi di findall ========== */

pari(X) :- 0 is X mod 2.

filter(P,L,Result) :-
        findall(X,(member(X,L),Cond=..[P,X],Cond),Result).


intersect(S1,S2,S) :-
        findall(X, (member(X,S1),member(X,S2)), S).

figlio(carlo,mario).
%figlio(anna,mario).
figlio(carlo,maria).
%figlio(anna,maria).
figlio(mario,alberto).
figlio(maria,alberto).

discendente(X,Y) :- figlio(X,Y).
discendente(X,Y) :- figlio(X,Z), discendente(Z,Y).


/* ======== definizione di findall ======= */

fall(X,Goal,_) :-
        Goal,
        assertz(found(X)),
        fail.
fall(_,_,List) :-
        costruisci(List).

costruisci([X|Rest]) :-
        retract(found(X)), !,
        costruisci(Rest).
costruisci([]).

padre(pippo,pluto).
padre(pippo,ciccio).
