Magic squares of singly even order
A magic square is an NxN square matrix whose numbers consist of consecutive numbers arranged so that the sum of each row and column, and both diagonals are equal to the same sum (which is called the magic number or magic constant).
You are encouraged to solve this task according to the task description, using any language you may know.
A magic square of singly even order has a size that is a multiple of 4, plus 2 (e.g. 6, 10, 14). This means that the subsquares have an odd size, which plays a role in the construction.
- Task
Create a magic square of 6 x 6.
- Related tasks
- See also
C++
<lang cpp>
- include <iostream>
- include <sstream>
- include <iomanip>
using namespace std;
class magicSqr { public:
magicSqr() { sqr = 0; } ~magicSqr() { if( sqr ) delete [] sqr; } void create( int d ) { if( sqr ) delete [] sqr; if( d & 1 ) d++; while( d % 4 == 0 ) { d += 2; } sz = d; sqr = new int[sz * sz]; memset( sqr, 0, sz * sz * sizeof( int ) ); fillSqr(); } void display() { cout << "Singly Even Magic Square: " << sz << " x " << sz << "\n"; cout << "It's Magic Sum is: " << magicNumber() << "\n\n"; ostringstream cvr; cvr << sz * sz; int l = cvr.str().size(); for( int y = 0; y < sz; y++ ) { int yy = y * sz; for( int x = 0; x < sz; x++ ) { cout << setw( l + 2 ) << sqr[yy + x]; } cout << "\n"; } cout << "\n\n"; }
private:
void siamese( int from, int to ) { int oneSide = to - from, curCol = oneSide / 2, curRow = 0, count = oneSide * oneSide, s = 1;
while( count > 0 ) { bool done = false; while ( false == done ) { if( curCol >= oneSide ) curCol = 0; if( curRow < 0 ) curRow = oneSide - 1; done = true; if( sqr[curCol + sz * curRow] != 0 ) { curCol -= 1; curRow += 2; if( curCol < 0 ) curCol = oneSide - 1; if( curRow >= oneSide ) curRow -= oneSide;
done = false; } } sqr[curCol + sz * curRow] = s; s++; count--; curCol++; curRow--; } } void fillSqr() { int n = sz / 2, ns = n * sz, size = sz * sz, add1 = size / 2, add3 = size / 4, add2 = 3 * add3;
siamese( 0, n );
for( int r = 0; r < n; r++ ) { int row = r * sz; for( int c = n; c < sz; c++ ) { int m = sqr[c - n + row]; sqr[c + row] = m + add1; sqr[c + row + ns] = m + add3; sqr[c - n + row + ns] = m + add2; } }
int lc = ( sz - 2 ) / 4, co = sz - ( lc - 1 ); for( int r = 0; r < n; r++ ) { int row = r * sz; for( int c = co; c < sz; c++ ) { sqr[c + row] -= add3; sqr[c + row + ns] += add3; } } for( int r = 0; r < n; r++ ) { int row = r * sz; for( int c = 0; c < lc; c++ ) { int cc = c; if( r == lc ) cc++; sqr[cc + row] += add2; sqr[cc + row + ns] -= add2; } } } int magicNumber() { return sz * ( ( sz * sz ) + 1 ) / 2; } void inc( int& a ) { if( ++a == sz ) a = 0; } void dec( int& a ) { if( --a < 0 ) a = sz - 1; } bool checkPos( int x, int y ) { return( isInside( x ) && isInside( y ) && !sqr[sz * y + x] ); } bool isInside( int s ) { return ( s < sz && s > -1 ); } int* sqr; int sz;
}; int main( int argc, char* argv[] ) {
magicSqr s; s.create( 6 ); s.display(); return 0;
} </lang>
- Output:
Singly Even Magic Square: 6 x 6 It's Magic Sum is: 111 35 1 6 26 19 24 3 32 7 21 23 25 31 9 2 22 27 20 8 28 33 17 10 15 30 5 34 12 14 16 4 36 29 13 18 11
D
<lang d> import std.exception; import std.stdio;
void main() {
int n = 6; foreach (row; magicSquareSinglyEven(n)) { foreach (x; row) { writef("%2s ", x); } writeln(); } writeln("\nMagic constant: ", (n * n + 1) * n / 2);
}
int[][] magicSquareOdd(const int n) {
enforce(n >= 3 && n % 2 != 0, "Base must be odd and >2");
int value = 0; int gridSize = n * n; int c = n / 2; int r = 0;
int[][] result = new int[][](n, n);
while(++value <= gridSize) { result[r][c] = value; if (r == 0) { if (c == n - 1) { r++; } else { r = n - 1; c++; } } else if (c == n - 1) { r--; c = 0; } else if (result[r - 1][c + 1] == 0) { r--; c++; } else { r++; } }
return result;
}
int[][] magicSquareSinglyEven(const int n) {
enforce(n >= 6 && (n - 2) % 4 == 0, "Base must be a positive multiple of four plus 2");
int size = n * n; int halfN = n / 2; int subSquareSize = size / 4;
int[][] subSquare = magicSquareOdd(halfN); int[] quadrantFactors = [0, 2, 3, 1]; int[][] result = new int[][](n, n);
for (int r = 0; r < n; r++) { for (int c = 0; c < n; c++) { int quadrant = (r / halfN) * 2 + (c / halfN); result[r][c] = subSquare[r % halfN][c % halfN]; result[r][c] += quadrantFactors[quadrant] * subSquareSize; } }
int nColsLeft = halfN / 2; int nColsRight = nColsLeft - 1;
for (int r = 0; r < halfN; r++) { for (int c = 0; c < n; c++) { if (c < nColsLeft || c >= n - nColsRight || (c == nColsLeft && r == nColsLeft)) { if (c == 0 && r == nColsLeft) { continue; } int tmp = result[r][c]; result[r][c] = result[r + halfN][c]; result[r + halfN][c] = tmp; } } }
return result;
} </lang>
Elixir
wp:Conway's LUX method for magic squares: <lang elixir>defmodule Magic_square do
@lux %{ L: [4, 1, 2, 3], U: [1, 4, 2, 3], X: [1, 4, 3, 2] } def singly_even(n) when rem(n-2,4)!=0, do: raise ArgumentError, "must be even, but not divisible by 4." def singly_even(2), do: raise ArgumentError, "2x2 magic square not possible." def singly_even(n) do n2 = div(n, 2) oms = odd_magic_square(n2) mat = make_lux_matrix(n2) square = synthesis(n2, oms, mat) IO.puts to_string(n, square) square end defp odd_magic_square(m) do # zero beginning, it is 4 multiples. for i <- 0..m-1, j <- 0..m-1, into: %{}, do: {{i,j}, (m*(rem(i+j+1+div(m,2),m)) + rem(i+2*j-5+2*m, m)) * 4} end defp make_lux_matrix(m) do center = div(m, 2) lux = List.duplicate(:L, center+1) ++ [:U] ++ List.duplicate(:X, m-center-2) (for {x,i} <- Enum.with_index(lux), j <- 0..m-1, into: %{}, do: {{i,j}, x}) |> Map.put({center, center}, :U) |> Map.put({center+1, center}, :L) end defp synthesis(m, oms, mat) do range = 0..m-1 Enum.reduce(range, [], fn i,acc -> {row0, row1} = Enum.reduce(range, {[],[]}, fn j,{r0,r1} -> x = oms[{i,j}] [lux0, lux1, lux2, lux3] = @lux[mat[{i,j}]] {[x+lux0, x+lux1 | r0], [x+lux2, x+lux3 | r1]} end) [row0, row1 | acc] end) end defp to_string(n, square) do format = String.duplicate("~#{length(to_char_list(n*n))}w ", n) <> "\n" Enum.map_join(square, fn row -> :io_lib.format(format, row) end) end
end
Magic_square.singly_even(6)</lang>
- Output:
5 8 36 33 13 16 6 7 34 35 14 15 28 25 17 20 12 9 26 27 18 19 10 11 24 21 4 1 32 29 22 23 2 3 30 31
FreeBASIC
<lang freebasic>' version 18-03-2016 ' compile with: fbc -s console ' singly even magic square 6, 10, 14, 18...
Sub Err_msg(msg As String)
Print msg Beep : Sleep 5000, 1 : Exit Sub
End Sub
Sub se_magicsq(n As UInteger, filename As String = "")
' filename <> "" then save square in a file ' filename can contain directory name ' if filename exist it will be overwriten, no error checking
If n < 6 Then Err_msg( "Error: n is to small") Exit Sub End If
If ((n -2) Mod 4) <> 0 Then Err_msg "Error: not possible to make singly" + _ " even magic square size " + Str(n) Exit Sub End If
Dim As UInteger sq(1 To n, 1 To n) Dim As UInteger magic_sum = n * (n ^ 2 +1) \ 2 Dim As UInteger sq_d_2 = n \ 2, q2 = sq_d_2 ^ 2 Dim As UInteger l = (n -2) \ 4 Dim As UInteger x = sq_d_2 \ 2 + 1, y = 1, nr = 1 Dim As String frmt = String(Len(Str(n * n)) +1, "#")
' fill pattern A C ' D B ' main loop for creating magic square in section A ' the value for B,C and D is derived from A ' uses the FreeBASIC odd order magic square routine Do If sq(x, y) = 0 Then sq(x , y ) = nr ' A sq(x + sq_d_2, y + sq_d_2) = nr + q2 ' B sq(x + sq_d_2, y ) = nr + q2 * 2 ' C sq(x , y + sq_d_2) = nr + q2 * 3 ' D If nr Mod sq_d_2 = 0 Then y += 1 Else x += 1 : y -= 1 End If nr += 1 End If If x > sq_d_2 Then x = 1 Do While sq(x,y) <> 0 x += 1 Loop End If If y < 1 Then y = sq_d_2 Do While sq(x,y) <> 0 y -= 1 Loop End If Loop Until nr > q2
' swap left side For y = 1 To sq_d_2 For x = 1 To l Swap sq(x, y), sq(x,y + sq_d_2) Next Next ' make indent y = (sq_d_2 \ 2) +1 Swap sq(1, y), sq(1, y + sq_d_2) ' was swapped, restore to orignal value Swap sq(l +1, y), sq(l +1, y + sq_d_2)
' swap right side For y = 1 To sq_d_2 For x = n - l +2 To n Swap sq(x, y), sq(x,y + sq_d_2) Next Next
' check columms and rows For y = 1 To n nr = 0 : l = 0 For x = 1 To n nr += sq(x,y) l += sq(y,x) Next If nr <> magic_sum Or l <> magic_sum Then Err_msg "Error: value <> magic_sum" Exit Sub End If Next
' check diagonals nr = 0 : l = 0 For x = 1 To n nr += sq(x, x) l += sq(n - x +1, n - x +1) Next If nr <> magic_sum Or l <> magic_sum Then Err_msg "Error: value <> magic_sum" Exit Sub End If ' printing square's on screen bigger when ' n > 19 results in a wrapping of the line Print "Single even magic square size: "; n; "*"; n Print "The magic sum = "; magic_sum Print For y = 1 To n For x = 1 To n Print Using frmt; sq(x, y); Next Print Next
' output magic square to a file with the name provided If filename <> "" Then nr = FreeFile Open filename For Output As #nr Print #nr, "Single even magic square size: "; n; "*"; n Print #nr, "The magic sum = "; magic_sum Print #nr, For y = 1 To n For x = 1 To n Print #nr, Using frmt; sq(x,y); Next Print #nr, Next Close #nr End If
End Sub
' ------=< MAIN >=------
se_magicsq(6, "magicse6.txt") : Print
' empty keyboard buffer While Inkey <> "" : Wend Print : Print "hit any key to end program" Sleep End</lang>
- Output:
Single even magic square size: 6*6 The magic sum = 111 35 1 6 26 19 24 3 32 7 21 23 25 31 9 2 22 27 20 8 28 33 17 10 15 30 5 34 12 14 16 4 36 29 13 18 11
Haskell
Using Conway's LUX method for magic squares <lang haskell>import Data.List
(mapAccumR, sortBy, groupBy, transpose, intercalate)
import Control.Monad (forM_) import Data.Ord (comparing) import Data.Function (on) import Data.Monoid ((<>))
magic :: Int -> Int magic n =
let d = (2 * n) + 1 -- LUX table size startXY = (quot d 2, 0) -- Middle of top row in threadRows . concat . snd $ mapAccumR -- Numbering of higher-resolution coordinates (\a (xy, c) -> (a + 4, luxNums xy c a)) 1 -- Initial number (luxPath (luxPattern n) (siamPath (d - 1) [startXY]))
-- Size required -> square of L U X cells with two mixed rows luxPattern :: Int -> [String] luxPattern n =
let d = (2 * n) + 1 [ls, us] = replicate (quot d 2) <$> "LU" [lRow, xRow] = replicate d <$> "LX" in replicate n lRow <> [ls <> ('U' : ls)] <> [us <> ('L' : us)] <> replicate (n - 1) xRow
-- Highest 0-based index of grid -> Siamese path so far -> full Siamese path siamPath :: Int -> [(Int, Int)] -> [(Int, Int)] siamPath uBound xs@((x, y):path) =
if y == uBound && x == quot uBound 2 then xs else siamPath uBound (pathSucc (x, y) : xs) where pathSucc (x, y) = let alt (a, b) | a > uBound && b < 0 = (uBound, 1) | a > uBound = (0, b) | b < 0 = (a, uBound) | elem (a, b) path = (a - 1, b + 2) | otherwise = (a, b) in alt (x + 1, y - 1)
-- LUX table -> Siamese path -> LUX-labelled Siamese path luxPath :: [String] -> [(Int, Int)] -> [((Int, Int), Char)] luxPath rows = fmap (\(x, y) -> ((x, y), (rows !! y) !! x))
-- LUX table coordinate -> L|U|X -> initial number -> 4 numbered coordinates luxNums :: (Int, Int) -> Char -> Int -> [((Int, Int), Int)] luxNums xy lux n =
zipWith (\x d -> (x, n + d)) (hiRes xy) $ case lux of 'L' -> [3, 0, 1, 2] 'U' -> [0, 3, 1, 2] 'X' -> [0, 3, 2, 1] _ -> [0, 0, 0, 0]
-- LUX cell coordinate -> four coordinates at higher resolution hiRes :: (Int, Int) -> [(Int, Int)] hiRes (x, y) =
let [col, row] = (* 2) <$> [x, y] [col1, row1] = succ <$> [col, row] in [(col, row), (col1, row), (col, row1), (col1, row1)]
-- Numbered sequence of coordinates -> ordered rows threadRows :: [((Int, Int), Int)] -> Int threadRows cells =
let row = snd . fst col = fst . fst in (fmap snd . sortBy (comparing col) <$> groupBy (on (==) row) (sortBy (comparing row) cells))
-- TESTS ---------------------------------------------------------------------- checked :: Int -> (Int, Bool) checked square = (h, all (h ==) t)
where diagonals = fmap (flip (zipWith (!!)) [0 ..]) . ((:) <*> (return . reverse)) h:t = sum <$> square ++ -- rows transpose square ++ -- cols diagonals square -- diagonals
table :: String -> String -> [String] table delim rows =
let justifyRight c n s = drop (length s) (replicate n c <> s) in intercalate delim <$> transpose ((fmap =<< justifyRight ' ' . maximum . fmap length) <$> transpose rows)
main :: IO () main =
forM_ [1, 2, 3] $ \n -> do let test = magic n putStrLn $ unlines (table " " (fmap show <$> test)) print $ checked test putStrLn ""</lang>
- Output:
32 29 4 1 24 21 30 31 2 3 22 23 12 9 17 20 28 25 10 11 18 19 26 27 13 16 36 33 5 8 14 15 34 35 6 7 (111,True) 68 65 96 93 4 1 32 29 60 57 66 67 94 95 2 3 30 31 58 59 92 89 20 17 28 25 56 53 64 61 90 91 18 19 26 27 54 55 62 63 16 13 24 21 49 52 80 77 88 85 14 15 22 23 50 51 78 79 86 87 37 40 45 48 76 73 81 84 9 12 38 39 46 47 74 75 82 83 10 11 41 44 69 72 97 100 5 8 33 36 43 42 71 70 99 98 7 6 35 34 (505,True) 120 117 156 153 192 189 4 1 40 37 76 73 112 109 118 119 154 155 190 191 2 3 38 39 74 75 110 111 152 149 188 185 28 25 36 33 72 69 108 105 116 113 150 151 186 187 26 27 34 35 70 71 106 107 114 115 184 181 24 21 32 29 68 65 104 101 140 137 148 145 182 183 22 23 30 31 66 67 102 103 138 139 146 147 20 17 56 53 64 61 97 100 136 133 144 141 180 177 18 19 54 55 62 63 98 99 134 135 142 143 178 179 49 52 57 60 93 96 132 129 165 168 173 176 13 16 50 51 58 59 94 95 130 131 166 167 174 175 14 15 81 84 89 92 125 128 161 164 169 172 9 12 45 48 83 82 91 90 127 126 163 162 171 170 11 10 47 46 85 88 121 124 157 160 193 196 5 8 41 44 77 80 87 86 123 122 159 158 195 194 7 6 43 42 79 78 (1379,True)
Java
<lang java>public class MagicSquareSinglyEven {
public static void main(String[] args) { int n = 6; for (int[] row : magicSquareSinglyEven(n)) { for (int x : row) System.out.printf("%2s ", x); System.out.println(); } System.out.printf("\nMagic constant: %d ", (n * n + 1) * n / 2); }
public static int[][] magicSquareOdd(final int n) { if (n < 3 || n % 2 == 0) throw new IllegalArgumentException("base must be odd and > 2");
int value = 0; int gridSize = n * n; int c = n / 2, r = 0;
int[][] result = new int[n][n];
while (++value <= gridSize) { result[r][c] = value; if (r == 0) { if (c == n - 1) { r++; } else { r = n - 1; c++; } } else if (c == n - 1) { r--; c = 0; } else if (result[r - 1][c + 1] == 0) { r--; c++; } else { r++; } } return result; }
static int[][] magicSquareSinglyEven(final int n) { if (n < 6 || (n - 2) % 4 != 0) throw new IllegalArgumentException("base must be a positive " + "multiple of 4 plus 2");
int size = n * n; int halfN = n / 2; int subSquareSize = size / 4;
int[][] subSquare = magicSquareOdd(halfN); int[] quadrantFactors = {0, 2, 3, 1}; int[][] result = new int[n][n];
for (int r = 0; r < n; r++) { for (int c = 0; c < n; c++) { int quadrant = (r / halfN) * 2 + (c / halfN); result[r][c] = subSquare[r % halfN][c % halfN]; result[r][c] += quadrantFactors[quadrant] * subSquareSize; } }
int nColsLeft = halfN / 2; int nColsRight = nColsLeft - 1;
for (int r = 0; r < halfN; r++) for (int c = 0; c < n; c++) { if (c < nColsLeft || c >= n - nColsRight || (c == nColsLeft && r == nColsLeft)) {
if (c == 0 && r == nColsLeft) continue;
int tmp = result[r][c]; result[r][c] = result[r + halfN][c]; result[r + halfN][c] = tmp; } }
return result; }
}</lang>
35 1 6 26 19 24 3 32 7 21 23 25 31 9 2 22 27 20 8 28 33 17 10 15 30 5 34 12 14 16 4 36 29 13 18 11 Magic constant: 111
Kotlin
<lang scala>// version 1.0.6
fun magicSquareOdd(n: Int): Array<IntArray> {
if (n < 3 || n % 2 == 0) throw IllegalArgumentException("Base must be odd and > 2")
var value = 0 val gridSize = n * n var c = n / 2 var r = 0 val result = Array(n) { IntArray(n) } while (++value <= gridSize) { result[r][c] = value if (r == 0) { if (c == n - 1) r++ else { r = n - 1 c++ } } else if (c == n - 1) { r-- c = 0 } else if (result[r - 1][c + 1] == 0) { r-- c++ } else r++ } return result
}
fun magicSquareSinglyEven(n: Int): Array<IntArray> {
if (n < 6 || (n - 2) % 4 != 0) throw IllegalArgumentException("Base must be a positive multiple of 4 plus 2") val size = n * n val halfN = n / 2 val subSquareSize = size / 4 val subSquare = magicSquareOdd(halfN) val quadrantFactors = intArrayOf(0, 2, 3, 1) val result = Array(n) { IntArray(n) } for (r in 0 until n) for (c in 0 until n) { val quadrant = r / halfN * 2 + c / halfN result[r][c] = subSquare[r % halfN][c % halfN] result[r][c] += quadrantFactors[quadrant] * subSquareSize } val nColsLeft = halfN / 2 val nColsRight = nColsLeft - 1 for (r in 0 until halfN) for (c in 0 until n) if (c < nColsLeft || c >= n - nColsRight || (c == nColsLeft && r == nColsLeft)) { if (c == 0 && r == nColsLeft) continue val tmp = result[r][c] result[r][c] = result[r + halfN][c] result[r + halfN][c] = tmp } return result
}
fun main(args: Array<String>) {
val n = 6 for (ia in magicSquareSinglyEven(n)) { for (i in ia) print("%2d ".format(i)) println() } println("\nMagic constant ${(n * n + 1) * n / 2}")
}</lang>
- Output:
35 1 6 26 19 24 3 32 7 21 23 25 31 9 2 22 27 20 8 28 33 17 10 15 30 5 34 12 14 16 4 36 29 13 18 11 Magic constant 111
Lua
For all three kinds of Magic Squares(Odd, singly and doubly even)
See Magic_squares/Lua.
Perl 6
See Magic squares/Perl 6 for a general magic square generator.
- Output:
With a parameter of 6:
35 1 6 26 19 24 3 32 7 21 23 25 31 9 2 22 27 20 8 28 33 17 10 15 30 5 34 12 14 16 4 36 29 13 18 11 The magic number is 111
With a parameter of 10:
92 99 1 8 15 67 74 51 58 40 98 80 7 14 16 73 55 57 64 41 4 81 88 20 22 54 56 63 70 47 85 87 19 21 3 60 62 69 71 28 86 93 25 2 9 61 68 75 52 34 17 24 76 83 90 42 49 26 33 65 23 5 82 89 91 48 30 32 39 66 79 6 13 95 97 29 31 38 45 72 10 12 94 96 78 35 37 44 46 53 11 18 100 77 84 36 43 50 27 59 The magic number is 505
Ruby
<lang ruby>def odd_magic_square(n)
n.times.map{|i| n.times.map{|j| n*((i+j+1+n/2)%n) + ((i+2*j-5)%n) + 1} }
end
def single_even_magic_square(n)
raise ArgumentError, "must be even, but not divisible by 4." unless (n-2) % 4 == 0 raise ArgumentError, "2x2 magic square not possible." if n == 2
order = (n-2)/4 odd_square = odd_magic_square(n/2) to_add = (0..3).map{|f| f*n*n/4} quarts = to_add.map{|f| odd_square.dup.map{|row|row.map{|el| el+f}} }
sq = [] quarts[0].zip(quarts[2]){|d1,d2| sq << [d1,d2].flatten} quarts[3].zip(quarts[1]){|d1,d2| sq << [d1,d2].flatten}
sq = sq.transpose order.times{|i| sq[i].rotate!(n/2)} swap(sq[0][order], sq[0][-order-1]) swap(sq[order][order], sq[order][-order-1]) (order-1).times{|i| sq[-(i+1)].rotate!(n/2)} randomize(sq)
end
def swap(a,b)
a,b = b,a
end
def randomize(square)
square.shuffle.transpose.shuffle
end
def to_string(square)
n = square.size fmt = "%#{(n*n).to_s.size + 1}d" * n square.inject(""){|str,row| str << fmt % row << "\n"}
end
puts to_string(single_even_magic_square(6))</lang>
- Output:
23 7 5 21 30 25 18 29 36 13 4 11 14 34 32 12 3 16 19 6 1 26 35 24 27 2 9 22 31 20 10 33 28 17 8 15
LUX method
wp:Conway's LUX method for magic squares <lang ruby>class Magic_square
attr_reader :square LUX = { L: [[4, 1], [2, 3]], U: [[1, 4], [2, 3]], X: [[1, 4], [3, 2]] } def initialize(n) raise ArgumentError, "must be even, but not divisible by 4." unless (n-2) % 4 == 0 raise ArgumentError, "2x2 magic square not possible." if n == 2 @n = n oms = odd_magic_square(n/2) mat = make_lux_matrix(n/2) @square = synthesize(oms, mat) puts to_s end def odd_magic_square(n) # zero beginning, it is 4 multiples. n.times.map{|i| n.times.map{|j| (n*((i+j+1+n/2)%n) + ((i+2*j-5)%n)) * 4} } end def make_lux_matrix(n) center = n / 2 lux = [*[:L]*(center+1), :U, *[:X]*(n-center-2)] matrix = lux.map{|x| Array.new(n, x)} matrix[center][center] = :U matrix[center+1][center] = :L matrix end def synthesize(oms, mat) range = 0...@n/2 range.inject([]) do |matrix,i| row = [[], []] range.each do |j| x = oms[i][j] LUX[mat[i][j]].each_with_index{|lux,k| row[k] << lux.map{|y| x+y}} end matrix << row[0].flatten << row[1].flatten end end def to_s format = "%#{(@n*@n).to_s.size}d " * @n + "\n" @square.map{|row| format % row}.join end
end
sq = Magic_square.new(6).square</lang>
- Output:
32 29 4 1 24 21 30 31 2 3 22 23 12 9 17 20 28 25 10 11 18 19 26 27 13 16 36 33 5 8 14 15 34 35 6 7
zkl
<lang zkl>class MagicSquareSinglyEven{
fcn init(n){ var result=magicSquareSinglyEven(n) } fcn toString{ sink,n:=Sink(String),result.len(); // num collumns fmt:="%2s "; foreach row in (result) { sink.write(row.apply('wrap(n){ fmt.fmt(n) }).concat(),"\n") } sink.write("\nMagic constant: %d".fmt((n*n + 1)*n/2)); sink.close(); } fcn magicSquareOdd(n){ if (n<3 or n%2==0) throw(Exception.ValueError("base must be odd and > 2")); value,gridSize,c,r:=0, n*n, n/2, 0; result:=n.pump(List(),n.pump(List(),0).copy); // array[n,n] of zero while((value+=1)<=gridSize){
result[r][c]=value; if(r==0){ if(c==n-1) r+=1;
else{ r=n-1; c+=1; }
} else if(c==n-1){ r-=1; c=0; } else if(result[r-1][c+1]==0){ r-=1; c+=1; } else r+=1;
} result; } fcn magicSquareSinglyEven(n){ if (n<6 or (n-2)%4!=0)
throw(Exception.ValueError("base must be a positive multiple of 4 +2"));
size,halfN,subSquareSize:=n*n, n/2, size/4;
subSquare:=magicSquareOdd(halfN); quadrantFactors:=T(0, 2, 3, 1); result:=n.pump(List(),n.pump(List(),0).copy); // array[n,n] of zero
foreach r,c in (n,n){ quadrant:=(r/halfN)*2 + (c/halfN);
result[r][c]=subSquare[r%halfN][c%halfN]; result[r][c]+=quadrantFactors[quadrant]*subSquareSize;
} nColsLeft,nColsRight:=halfN/2, nColsLeft-1; foreach r,c in (halfN,n){ if ( c<nColsLeft or c>=(n-nColsRight) or (c==nColsLeft and r==nColsLeft) ){
if(c==0 and r==nColsLeft) continue; tmp:=result[r][c]; result[r][c]=result[r+halfN][c]; result[r+halfN][c]=tmp; }
} result }
}</lang> <lang zkl>MagicSquareSinglyEven(6).println();</lang>
- Output:
35 1 6 26 19 24 3 32 7 21 23 25 31 9 2 22 27 20 8 28 33 17 10 15 30 5 34 12 14 16 4 36 29 13 18 11 Magic constant: 111