:-use_module(library(lists)).

%%% Generate & Test
regine_get(N,Allocazione) :-
       statistics(runtime,_),
       genera(N,Allocazione),
       safe(Allocazione),
       statistics(runtime,[_,T]),
       format("Solution found in ~d ms ~n",[T]).
genera(N,Allocazione) :-
       length(Allocazione,N),
       dominio(N,ListaValori),
%%% Opt 1. 
       % funzione(Allocazione,ListaValori). 
%%% Opt 2.  
       permutation(ListaValori,Allocazione).
       
dominio(0,[]).
dominio(N,[N|R]) :-
       N>0,
       M is N-1,
       dominio(M,R).

funzione([A|R],Cod) :-
        member(A,Cod),
        funzione(R,Cod).
funzione([],_).

safe([]).
safe([Q|Qs]) :-
        safe(Qs),
        \+ attacca(Q,Qs).
        
attacca(X,Xs) :-
        att(X,1,Xs). 
att(X,Offset,[Y|_R]) :-
        X is Y+Offset.
att(X,_Offset,[X|_R]).
att(X,Offset,[Y|_R]) :-
        X is Y-Offset.
att(X,Offset,[_Y|R]) :-
        N1 is Offset+1,
        att(X,N1,R).

%%%% Aggiungi una alla volta

regine_opt(N,Allocazione) :- 
         statistics(runtime,_),
         dominio(N,ListaValori),
         aggiungi_regina(ListaValori,[],Allocazione),
         statistics(runtime,[_,T]),
         format("Solution found in ~d ms ~n",[T]).
aggiungi_regina(NonMesse,Sicure,Allocazione) :- 
         select(Q,NonMesse,Rimanenti),
         \+ attacca(Q,Sicure), 
         aggiungi_regina(Rimanenti,[Q|Sicure],Allocazione). 
aggiungi_regina([],Allocazione,Allocazione).

%%%%%%%%%% Fine
