%%%%% solution to exercise 3.4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:- 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) :-
length(Matrix,N),
diaglr(Matrix,DiagL,DiagR,1,N),
sumlist(DiagL,Sum),
sumlist(DiagR,Sum).
diaglr([],[],[],_,_).
diaglr([H|T],[ElemL|DiagL],[ElemR|DiagR],I,J) :-
get(I,H,ElemL),
get(J,H,ElemR),
IPlus1 is I+1,
JMinus1 is J-1,
diaglr(T,DiagL,DiagR,IPlus1,JMinus1).
get(1,[H|_],H).
get(N,[_|T],Elem) :-
N>1,
N1 is N-1,
get(N1,T,Elem).
%%%%%%%%%%%%%%%%%%%%%%%% c) %%%%%%%%%%%%%%%%%%%%%%%%
square(N) :-
magicC(N,Matrix),
term_variables(Matrix,Vars),
search(Vars,0,most_constrained,indomain_random,complete,[]),
print_list(Matrix),
nl.
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).