A magic square is an   NxN   square matrix whose numbers (usually integers) consist of consecutive numbers arranged so that the sum of each row and column,   and   both long (main) diagonals are equal to the same sum (which is called the   magic number   or   magic constant).

The numbers are usually (but not always) the first   N2   positive integers.

A magic square whose rows and columns add up to a magic number but whose main diagonals do not, is known as a semimagic square.



 8 
 1 
 6


 3 
 5 
 7


 4 
 9 
 2



Task
For any odd   N,   generate a magic square with the integers    1 ──► N,   and show the results here.

Optionally, show the magic number.

You should demonstrate the generator by showing at least a magic square for   N = 5.



 Related tasks
 Magic squares of singly even order
 Magic squares of doubly even order



 See also

 MathWorld™ entry: Magic_square 
 Odd Magic Squares (1728.org)


import util.
 
go =>
  foreach(N in [3,5,17])
    M=magic_square(N),
    print_matrix(M),
    check(M),
    nl
  end,
  nl.
 
%
% Not as nice as the J solution. 
% But I like the chaining of the functions.
%
magic_square(N) = MS =>
  if N mod 2 = 0 then
     printf("N (%d) is not odd!\n", N),
     halt
  end,
  R = make_rotate_list(N), % the rotate indices
  MS = make_square(N).transpose().rotate_matrix(R).transpose().rotate_matrix(R).
 
%
% make a square matrix of size N (containing the numbers 1..N*N)
%
make_square(N) = [[I*N+J : J in 1..N]: I in 0..N-1].
 
%
% rotate list:
%   rotate_list(11) = [-5,-4,-3,-2,-1,0,1,2,3,4,5]
%
make_rotate_list(N) = [I - ceiling(N / 2) : I in 1..N].
 
%
% rotate the matrix M according to rotate list R
%
rotate_matrix(M, R) = [rotate_n(Row,N) : {Row,N} in zip(M,R)].
 
%
% Rotate the list L N steps (either positive or negative N)
%   rotate(1..10,3) -> [4,5,6,7,8,9,10,1,2,3]
%   rotate(1..10,-3) -> [8,9,10,1,2,3,4,5,6,7]
%
rotate_n(L,N) = Rot => 
  Len = L.length,
  R = cond(N < 0, Len + N, N),
  Rot = [L[I] : I in (R+1..Len) ++ 1..R].
 
%
% Check if M is a magic square
%
check(M) => 
  N = M.length,
  Sum = N*(N*N+1) // 2, % The correct sum.
  println(sum=Sum),
  Rows = [sum(Row) : Row in M],
  Cols = [sum(Col) : Col in M.transpose()],
  Diag1 = sum([M[I,I] : I in 1..N]),
  Diag2 = sum([M[I,N-I+1] : I in 1..N]),
  All = Rows ++ Cols ++ [Diag1, Diag2],
  OK = true,
  foreach(X in All)
    if X != Sum then
      printf("%d != %d\n", X, Sum),
      OK := false
    end
  end,
  if OK then
    println(ok)
  else 
    println(not_ok)
  end,
  nl.
 
% Print the matrix
print_matrix(M) =>
  N = M.len,
  printf("N=%d\n",N),
  Format = to_fstring("%%%dd",max(flatten(M)).to_string().length+1),
  foreach(Row in M) 
     foreach(X in Row)
       printf(Format, X)
     end,
     nl
  end,
  nl.