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)


magic_square = cluster is create, unparse, magic_number
    rep = array[array[int]]
 
    create = proc (order: int) returns (cvt) signals (invalid)
        if order<1 cor order//2 = 0 then signal invalid end
        sq: rep := rep$fill_copy(1, order, array[int]$fill(1, order, 0))
        x: int := (order+1)/2
        y: int := 1
 
        for i: int in int$from_to(1, order**2) do
            sq[y][x] := i
            next_x: int := inc(sq,x)
            next_y: int := dec(sq,y)
            if sq[next_y][next_x]=0          
                then x, y := next_x, next_y
                else y := inc(sq,y)
            end
        end
        return(sq)
    end create
 
    inc = proc (sq: rep, co: int) returns (int)
        order: int := rep$size(sq)
        if co=order then return(1) else return(co+1) end
    end inc
 
    dec = proc (sq: rep, co: int) returns (int)
        order: int := rep$size(sq)
        if co=1 then return(order) else return(co-1) end
    end dec
 
    unparse = proc (sq: cvt) returns (string)
        order: int := rep$size(sq)        
        col_size: int := string$size(int$unparse(order ** 2)) + 1
        ss: stream := stream$create_output()
        for y: int in int$from_to(1, order) do
            for x: int in int$from_to(1, order) do
                stream$putright(ss, int$unparse(sq[y][x]), col_size)
            end
            stream$putl(ss, "")
        end
        return(stream$get_contents(ss))
    end unparse
 
    magic_number = proc (sq: cvt) returns (int)
        order: int := rep$size(sq)
        n: int := 0
        for x: int in int$from_to(1, order) do n := n + sq[1][x] end
        return(n)
    end magic_number
end magic_square
 
 
print_magic_square = proc (order: int)
    po: stream := stream$primary_output()
    ms: magic_square := magic_square$create(order)
    stream$putl(po, "Magic square of order "
                 || int$unparse(order)
                 || " with magic number "
                 || int$unparse(magic_square$magic_number(ms))
                 || ": ")
    stream$putl(po, magic_square$unparse(ms))
end print_magic_square
 
start_up = proc ()
    for n: int in int$from_to_by(1, 7, 2) do
        print_magic_square(n)
    end
end start_up