%%%%% solution to exercise 2.3 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:- lib(ic).
:- lib(ic_global).
%%%%%%%%%%%%%%%%%%%%%%%% a) %%%%%%%%%%%%%%%%%%%%%%%%
assignM(Matrix,N,Nsq) :- length(Matrix,N), assignRows(Matrix,N,Nsq).
assignRows([],_,_).
assignRows([H|T],N,Nsq) :-
length(H,N), H#::[1..Nsq], assignRows(T,N,Nsq).
%%%%%%%%%%%%%%%%%%%%%%%% b) %%%%%%%%%%%%%%%%%%%%%%%%
rowC([],_).
rowC([H|T],Sum) :- sumlist(H,Sum), rowC(T,Sum).
colC(Matrix,Sum) :- colC([],Matrix,[],Sum).
colC([],[[]|_],[],_).
colC(ColElems,[],RestMatrix,Sum) :- sumlist(ColElems,Sum), colC([],RestMatrix,[],Sum).
colC(ColElems,[[H|T]|Rows],RestMatrix,Sum) :- colC([H|ColElems],Rows,[T|RestMatrix],Sum).
diagC(Matrix,Sum) :-
diaglr(Matrix,DiagL,DiagR,0),
sumlist(DiagL,Sum), sumlist(DiagR,Sum).
diaglr([],[],[],_).
diaglr([H|T],[ElemL|DiagL],[ElemR|DiagR],I) :-
IPlus1 is I+1,
length(H,N), NminusI is N-I,
get(IPlus1,H,ElemL), get(NminusI,H,ElemR),
diaglr(T,DiagL,DiagR,IPlus1).
get(1,[H|_],H).
get(N,[_|T],Elem) :- N>1, N1 is N-1, get(N1,T,Elem).
%%%%%%%%%%%%%%%%%%%%%%%% c) %%%%%%%%%%%%%%%%%%%%%%%%
square(N) :-
squareNoOut(N,Matrix),
show(Matrix).
squareNoOut(N,Matrix) :-
magicC(N,Matrix), term_variables(Matrix,Vars),
search(Vars,0,most_constrained,indomain_random,complete,[]).
allsquare(N) :-
findall(_,squareNoOut(N,_),List), length(List,Length),
write("solutions: "), writeln(Length).
magicC(N,Matrix) :-
Nsq is N*N, Sum is (Nsq+1)*N//2, printf("Sum = %d%n", [Sum]),
assignM(Matrix,N,Nsq),
rowC(Matrix,Sum), colC(Matrix,Sum), diagC(Matrix,Sum),
term_variables(Matrix,Vars), ic_global:alldifferent(Vars).
show([]) :- nl.
show([H|T]) :- writeln(H), show(T).