%SOLUZIONE ESERCIZIO 2 compitino

% A)  i costruttori
%     uso 1,2,3,4,5  per denotare i 5 pezzi
%     uso pl(Seq,Pz) per costruire una sequenza
%         in cui un pezzo Pz viene aggiunto
%         in fondo ad una sequenza di pezzi Seq
%         e uso v per la sequenza vuota
%     Chiamo:
%     tipo_pezzi l'insieme dei termini contente
%     le variabili e le costanti 1,2,3,4,5;
%     seq_pezzi il tipo contenente termini costruiti
%     usando solo termini di tipo_pezzi o termini
%     della forma v o pz(TS,TP), dove TP è un termine
%     di tipo_pezzi e TS è (ricorsivamente) un termine
%     di seq_pezzi

%B) SPECIFICA
% pezzo(out:tipo_pezzi)
% pezzo(x) sse x appartiene a 1..5

pezzo(1).
pezzo(2).
pezzo(3).
pezzo(4).
pezzo(5).

% C)SPECIFICA
% non_rip(in:seq_pezzi)
% non_rip(s) sse s non contiene ripetizioni

% Per verificare che non ci siano ripetizioni,
% uso il predicato:
% SPECIFICA
% non_occ(in:tipo_pezzi, in:seq_pezzi)
% non_occ(x,s) vero sse x non occorre in s

% COMMENTO:
% per brevità, uso il predicato predefinito
% in:termini =\= in:termini

non_rip(v).
non_rip(pl(S,P)) :- pezzo(P),
                    non_occ(P,S),
                    non_rip(S).
non_occ(_,v).
non_occ(P, pl(S,Q)) :- div(P,Q),
                       non_occ(P,S).
div(P,Q) :- pezzo(P),
            pezzo(Q),
            P =\= Q.

% D) SPECIFICA
% puzzle(in:seq_pezzi)
% puzzle(s) sse s è un puzzle costruibile;

% Uso il predicato ausiliario
% ok(in:seq_pezzi)
% ok(s) sse s è un puzzle rispetto alla relazione
% di incastro fra i pezzi

puzzle(S) :- ok(S), non_rip(S).

% Per ok, procedo trattando gli incastri come segue:
% SPECIFICA:
% incastro(in:seq_pezzi,in:tipo_pezzi)
% incastro(s,q) sse p si incastra DOPO s in base
% all'incastrabilità fra pezzi; per quest'ultima 
% specifico:
% incastro_pezzi(in: tipo_pezzi, in: tipo_pezzi)
% incastro_pezzi(p,q) sse posso incastrare p su q

ok(v).
ok(pl(S,Q)) :- incastro(S,Q),
               ok(S).
incastro(v,P):- pezzo(P).
incastro(pl(_,Q),P) :- pezzo(P),
                       incastro_pezzi(P,Q).



%%%%% Una relazione di incastro pezzi

incastro_pezzi(1,2).
incastro_pezzi(1,3).
incastro_pezzi(2,3).
incastro_pezzi(3,4).
incastro_pezzi(4,1).
incastro_pezzi(5,4).

%  NB.   Per semplificare i problemi di terminazione, 
%  si e' usato il modo in.  Se si volesse enumerare
%  i puzzle, ovvero usare il modo out, come si potrebbe
%  fare?



