% ILP-503 (Prof. Dr. Silvio do Lago Pereira)

% ---------------------------------------------------------------------
% EXEMPLO 5
% ---------------------------------------------------------------------

fib(1, 1) :- !.
fib(2, 1) :- !.
fib(N, F) :-
   N1 is N-1,
   N2 is N-2,
   fib(N1, F1),
   fib(N2, F2),
   F is F1 + F2.

fib(N) :- fib(N, F), writeln(fib(N) = F).

fib :- forall(between(1, 35, N), fib(N)).

% ---------------------------------------------------------------------
% EXEMPLO 6
% ---------------------------------------------------------------------

:- dynamic(fibm/2).

fibm(1, 1) :- !.
fibm(2, 1) :- !.
fibm(N, F) :-
   N1 is N-1,
   N2 is N-2,
   fibm(N1, F1),
   fibm(N2, F2),
   F is F1 + F2,
   asserta(fibm(N, F) :- !).

fibm(N) :- fibm(N, F), writeln(fibm(N) = F).

fibm :- forall(between(1, 35, N), fibm(N)).

% ---------------------------------------------------------------------
% EXEMPLO 7
% ---------------------------------------------------------------------

:- dynamic resposta/1.

encontre(X,C,L) :- forall(C,assertz(resposta(X))), colete(L).

colete([X|R]) :- retract(resposta(X)), !, colete(R).
colete([]).

% dados para teste

q(a).
q(b).
q(c).
q(b).

% ---------------------------------------------------------------------
% EXEMPLO 8
% ---------------------------------------------------------------------

:- dynamic lâmpada/1.

lâmpada(acesa).

apaga :- retract(lâmpada(acesa)), assertz(lâmpada(apagada)).

acende :- retract(lâmpada(apagada)), assertz(lâmpada(acesa)).

% ---------------------------------------------------------------------
% EXEMPLO 9
% ---------------------------------------------------------------------

:- dynamic pos/2, seg/1.

:- initialization
   retractall(pos(_,_)),
   retractall(seg(_)),
   assertz(pos(agente, garagem)),
   assertz(pos(micro, cozinha)),
   assertz(pos(rádio, quarto)).

ande(L) :- pos(agente, L), !.
ande(L) :- retract(pos(agente, P)), assertz(pos(agente, L)),
           format('\nAnda de ~w até ~w.', [P, L]), !.

pegue(O) :- seg(O), !.
pegue(O) :- pos(O,P), ande(P),
            retract(pos(O,_)), assertz(seg(O)),
            format('\nPega ~w.', [O]), !.

solte(O) :- not(seg(O)), !.
solte(O) :- pos(agente, P),
            retract(seg(O)), assertz(pos(O, P)),
            format('\nSolta ~w.', [O]), !.

% ---------------------------------------------------------------------
% EXEMPLO 10
% ---------------------------------------------------------------------

memorize :-
   tell('mundo.pl'),
   forall(pos(X,Y), format('~w.~n', [pos(X,Y)])),
   forall(seg(X), format('~w.~n', [seg(X)])),
   told.

relembre :-
   retractall(pos(_,_)),
   retractall(seg(_)),
   see('mundo.pl'),
   repeat,
     read(C),
     assertz(C),
     C = end_of_file,
   retract(end_of_file), !,
   seen.

% ---------------------------------------------------------------------
% EXEMPLO 11
% ---------------------------------------------------------------------

filtra(_, [],    [])    :- !.
filtra(P, [X|L], [X|R]) :- call(P, X), !, filtra(P, L, R).
filtra(P, [_|L], R)     :- filtra(P, L, R).
