declare fun {MagicSquare N} NN=N*N L1N={List.number 1 N 1} % [1..N] in proc {$ Square} fun {Field A B} % modified to align bounds I=(A mod N) + N* (A div N) J=(B mod N) + N *(B div N) in Square.((I-1)*N + J) end proc {Assert F} {FD.sum {Map L1N F} '=:' Sum} end proc {AssertPrime F} F :: [ 1 2 3 5 7 11 13 17 19 23] % Primes between 1 and 25 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} %Assert first Row to consist of primes {For 1 N 1 proc {$ I} {AssertPrime {Field 1 I}} end} %Assert other 'T' constituents to be primes {ForAll [[2 1] [2 3] [2 5] [3 3]] proc {$ I} [A B]=I in {AssertPrime {Field A B}} 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}}
This first solution is
square( 3 7 13 19 23 11 22 17 10 5 12 21 2 14 16 15 6 25 18 1 24 9 8 4 20)