/* Pi square in Picat. From Chris Smith's Math Newsletter #549 """ You've got nine 4s, nine 3s, nine 2s, and nine 1s and your task is to greate a magic square of four-digit numbers. ... So, let's say that all of the four-digit numbers have got to be different and to satisfy my obsesson for pi, one of them must be 3141 and another has to be 3142. """ Some - of many - solutions: [1234,1241,1242] [1243,1244,2233] [3141,3142,3334] [1234,1241,1242] [1243,1244,2233] [3141,3142,3343] [1234,1241,1242] [1243,1244,2233] [3141,3142,3433] This model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import util. import cp. main => go. go ?=> N = 3, % The number square X = new_array(N,N), X :: 1234..4321, % for checking the number of digits Y = new_array(N,N,4), Y :: 1..4, S :: 0..4321*N*N, % magic_sum % conncect X and Y foreach(I in 1..N, J in 1..N) to_num(Y[I,J],10,X[I,J]) end, all_different(X.vars), % exactly nine occurrences of 4s, 3s, 2s, and 1s respectively global_cardinality(Y.vars,$[1-9,2-9,3-9,4-9]), % 3141 and 3142 must be in the square element(_,X.vars,3141), element(_,X.vars,3142), % It's a magic square! foreach(I in 1..N) S #= sum([X[I,J] : J in 1..N]), S #= sum([X[J,I] : J in 1..N]) end, % diagonal sums S #= sum([X[I,I] : I in 1..N]), S #= sum([X[I,N-I+1] : I in 1..N]), % Symmetry breaking (Frénicle form) X[1,1] #= min([X[1,1], X[1,N], X[N,1], X[N,N]]), X[1,2] #< X[2,1], Vars = Y.vars ++ X.vars ++ [S], solve($[ff,split],Vars), println(s=S), foreach(Row in X) println(Row.to_list) end, nl, fail, nl. go => true. % % converts a number Num to/from a list of integer List given a base Base % to_num(List, Base, Num) => Len = length(List), Num #= sum([List[I]*Base**(Len-I) : I in 1..Len]). to_num(List, Num) => to_num(List, 10, Num).