
%%%%% 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).
