/* Magic squares on Frénicle standard form in Picat. From http://en.wikipedia.org/wiki/Fr%C3%A9nicle_standard_form """ A magic square is in Frénicle standard form, named for Bernard Frénicle de Bessy, if the following two conditions apply: - the element at position [1,1] (top left corner) is the smallest of the four corner elements; and - the element at position [1,2] (top edge, second from left) is smaller than the element in [2,1]. """ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go ?=> N = 4, magic_square_frenicle_form(N, X), print_square(X), fail, nl. go => true. go2 => nolog, Timeout = 10_000, foreach(N in 2..20) println(n=N), time_out(time2(magic_square_frenicle_form(N,Magic)),Timeout,Status), println(status=Status), if nonvar(Magic) then print_square(Magic) else println(no_solution) end, nl end, nl. print_square(X) => N = X.len, foreach(I in 1..N) foreach(J in 1..N) printf("% 5d ", X[I,J]) end, nl end, nl. magic_square_frenicle_form(N, Magic) => Total = ( N * (N*N + 1)) div 2, Magic = new_array(N,N), Magic :: 1..N*N, all_different(Magic.vars), foreach(K in 1..N) sum([Magic[K,I] : I in 1..N]) #= Total, sum([Magic[I,K] : I in 1..N]) #= Total end, % diagonal1 sum([Magic[I,I] : I in 1..N]) #= Total, % diagonal2 sum([Magic[I,N-I+1] : I in 1..N]) #= Total, % Frénicle standard form % For n=4 this yields the 48 squares that's shown at % http://en.wikipedia.org/wiki/Associative_magic_square#4_x_4_associative_magic_square_-_complete_listing Magic[1,1] #= min([Magic[1,1], Magic[1,N], Magic[N,1], Magic[N,N]]), Magic[1,2] #< Magic[2,1], % solve([inout,updown],Magic.vars). solve([constr,rand_val],Magic.vars).