Magic squares/Lua

From Rosetta Code

Lua


function makeArray( s )
    local q = {}
    for j = 1, s do
        table.insert( q, {} )
        for i = 1, s do
            table.insert( q[j], 0 )
        end
    end
    return q
end

-- [[ odd magic square ]] --
function buildOMS( s )
    if s % 2 == 0 then s = s + 1 end
    local q, p = makeArray( s ), 1
    local i, j, ti, tj = 1 + math.floor( s / 2 ), 1
    while( p <= s * s ) do
        q[i][j] = p
        ti = i + 1; if ti > s then ti = 1 end
        tj = j - 1; if tj < 1 then tj = s end
        if q[ti][tj] ~= 0 then
            ti = i; tj = j + 1
        end
        i = ti; j = tj; p = p + 1;
    end
    return q, s
end

-- [[ singly even magic square ]] --
function buildSEMS( s )
    if s % 2 == 1 then s = s + 1 end
    while( s % 4 == 0 ) do s = s + 2 end

    local q, z, o = makeArray( s ), math.floor( s / 2 )
    local b, c, d, a = z * z; c = 2 * b; d = 3 * b

    o = buildOMS( z )
    for j = 1, z do
        for i = 1, z do
            a = o[i][j]
            q[i][j] = a
            q[i + z][j + z] = a + b
            q[i + z][j] = a + c
            q[i][j + z] = a + d
        end
    end

    local lc = math.floor( z / 2 )
    local rc, t = lc - 1 
    for j = 1, z do
        for i = 1, s do  
            if i <= lc or i > s - rc or ( i == lc + 1 and j == lc + 1 ) then
                if not( i == 1 and j == lc+ 1 ) then
                    t = q[i][j]
                    q[i][j] = q[i][j + z]
                    q[i][j + z] = t
                end
            end
        end
    end
    return q, s
end

-- [[ doubly even magic square ]] --
function buildDEMS( s )
    while( s % 4 > 0 ) do s = s + 1 end
    local q = makeArray( s )
    local temp, n, tot, sx, sy = {{1,0,0,1}, {0,1,1,0}, {0,1,1,0}, {1,0,0,1}}, 
          0, s * s
    for j = 1, s do
        for i = 1, s do
            sx = i % 4; if sx < 1 then sx = 4 end
            sy = j % 4; if sy < 1 then sy = 4 end
            if temp[sy][sx] == 1 then q[i][j] = n + 1
            else q[i][j] = tot - n end
            n = n + 1
        end
    end
    return q, s
end

function myFormat( s, l )
    for i = 1, l - #s do
        s = "0" .. s
    end
    return s .. " "
end

LOG_10 = 2.302585092994
function display( q, s )
    io.write( string.format( " - %d x %d\n", s, s ) )
    local k = 1 + math.floor( math.log( s * s ) / LOG_10 )
    for j = 1, s do
        for i = 1, s do
            io.write( myFormat( string.format( "%d", q[i][j] ), k ) )
        end
        print()
    end
    io.write( string.format( "Magic sum: %d\n", s * ( ( s * s ) + 1 ) / 2 ) )
end

--[[ entry point ]]--
io.write( "\nOdd Magic Square" )
display( buildOMS( 9 ) )

io.write( "\nSingly Even Magic Square" )
display( buildSEMS( 6 ) )

io.write( "\nDoubly Even Magic Square" )
display( buildDEMS( 8 ) )
Output:
Odd Magic Square - 9 x 9
47 58 69 80 01 12 23 34 45
57 68 79 09 11 22 33 44 46
67 78 08 10 21 32 43 54 56
77 07 18 20 31 42 53 55 66
06 17 19 30 41 52 63 65 76
16 27 29 40 51 62 64 75 05
26 28 39 50 61 72 74 04 15
36 38 49 60 71 73 03 14 25
37 48 59 70 81 02 13 24 35
Magic sum: 369

Singly Even Magic Square - 6 x 6
35 01 06 26 19 24
03 32 07 21 23 25
31 09 02 22 27 20
08 28 33 17 10 15
30 05 34 12 14 16
04 36 29 13 18 11
Magic sum: 111

Doubly Even Magic Square - 8 x 8
01 63 62 04 05 59 58 08
56 10 11 53 52 14 15 49
48 18 19 45 44 22 23 41
25 39 38 28 29 35 34 32
33 31 30 36 37 27 26 40
24 42 43 21 20 46 47 17
16 50 51 13 12 54 55 09
57 07 06 60 61 03 02 64
Magic sum: 260