declare
fun {MagicSquare N}
NN=N*N
L1N={List.number 1 N 1} % [1..N]
in
proc {$ Square}
fun {Field I J}
Square.((I-1)*N + J)
end
proc {Assert F}
{FD.sum {Map L1N F} '=:' Sum}
end
Sum={FD.decl}
in
{FD.tuple square NN 1#NN Square}
{FD.distinct Square}
%Diagonals
{Assert fun {$ I} {Field I I} end}
{Assert fun {$ I} {Field I N+1-I} end}
%Columns
{For 1 N 1
proc {$ I} {Assert fun {$ J} {Field I J} end} end}
%Rows
{For 1 N 1
proc {$ J} {Assert fun {$ I} {Field I J} end} end}
%Eliminate Symmetries
{Field 1 1} <: {Field N N}
{Field N 1} <: {Field 1 N}
{Field 1 1} <: {Field N 1}
%Redundant: sum of all fields = (number rows) * Sum
NN*(NN+1) div 2 =: N*Sum
{FD.distribute split Square}
end
end
{ExploreOne {MagicSquare 5}}
The first three magic squares yopu get with domain splitting are
1#square( 1 2 13 24 25 2#square( 1 2 13 24 25 3#square( 1 2 13 24 25
3 22 19 6 15 3 23 16 8 15 3 23 17 6 16
23 16 10 11 5 21 19 10 6 9 20 21 11 8 5
21 7 9 20 8 22 4 14 20 5 22 4 14 18 7
17 18 14 4 12) 18 17 12 7 11) 19 15 10 9 12)
well, they seem to come in packs somehow, don't they?