%:- use_module(library(clpfd)).
%:- use_module(library(lists)).

schur(I,N,P) :-
%    retractall(count(X)), assert(count(0)),
    statistics(runtime,_),
    length(List,N),   %% List = [X1...Xn], Xi is the part to which i belongs
    domain(List,1,P), %% there are P parts 
    constraints(List, N),
    special_constraints(I,List),
    statistics(runtime,[_,T1]),
    labeling([],List),
%    retract(count(C)),C1 is C + 1,assert(count(C1)),
    statistics(runtime,[_,T2]),
    format("Constraint time: ~q~n",[T1]),
    format("Resolution time: ~q~n",[T2]),
    stampa(List).
%    , fail.
    
schur(_,_,_) :-
    write('No (more) solutions'), nl, 
    statistics(runtime,[_,T2]),
    format("Time: ~q~n",[T2]),
    retract(count(C)),
    format("Solutions: ~q~n",[C]). 

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

schur(N,K) :-
    statistics(runtime,_),
    length(List,N),   %% List = [X1...Xn], Xi is the part to which i belongs
    domain(List,1,K), %% there are P parts 
    constraints(List, N),
    labeling([],List),
    statistics(runtime,[_,T2]),
    format("Resolution time: ~q~n",[T2]),
    stampa(List).

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

special_constraints( 0, [1,2|_]). %%% all

special_constraints( 1, [1,2,3,4|R]) :-
     nosimmetry(R,4).
special_constraints( 2, [1,2,2,1,3|R]) :-
     nosimmetry(R,3).
special_constraints( 3, [1,2,3,1|R]) :-
     nosimmetry(R,3).
special_constraints( 4, [1,2,1,3|R]) :-
     nosimmetry(R,3).
special_constraints( 5, [1,2,2,3|R]) :-
     nosimmetry(R,3).
special_constraints( 6, [1,2,3,3|R]) :-
     nosimmetry(R,3).

nosimmetry(_,_). %% DA FARE

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

constraints(List, N) :-
    recursion(List,1,1,N).
recursion(_,M,_,N):- 
    M > N, !.
recursion(List,I,J,N):-  
    I + J > N,!,
    I1 is I + 1,
    recursion(List,I1,1,N).
recursion(List,I,J,N):-  
    I > J,!,
    J1 is J + 1,
    recursion(List,I,J1,N).
recursion(List,I,J,N) :-
     K is I + J,
    nth1(I,List,BlockI),
    nth1(J,List,BlockJ),
    nth1(K,List,BlockK),
    (BlockI #= BlockJ) #=> (BlockK #\= BlockI),
    J1 is J+1,
    recursion(List,I,J1,N).
    
%%%%%%%%%%%%%%%%%


stampa(List) :- 
    dump(List,1).
dump([],_).
dump([A|B],N) :-
    (0 is N mod 4, !, format("~q -> part ~q~n",[N,A]);
    format("~q -> part ~q  ",[N,A])), 
    N1 is N+1,
    dump(B,N1).

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