Magic squares of singly even order
You are encouraged to solve this task according to the task description, using any language you may know.
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).
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 qualified Data.Map.Strict as M import Data.List (transpose, intercalate) import Data.Maybe (fromJust, isJust) import Control.Monad (forM_) import Data.Monoid ((<>))
magic :: Int -> Int magic n = mapAsTable ((4 * n) + 2) (hiResMap n)
-- Order of square -> sequence numbers keyed by cartesian coordinates hiResMap :: Int -> M.Map (Int, Int) Int hiResMap n =
let mapLux = luxMap n mapSiam = siamMap n in M.fromList $ foldMap (\(xy, n) -> luxNums xy (fromJust (M.lookup xy mapLux)) ((4 * (n - 1)) + 1)) (M.toList mapSiam)
-- 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]
-- Size of square -> integers keyed by coordinates -> rows of integers mapAsTable :: Int -> M.Map (Int, Int) Int -> Int mapAsTable nCols xyMap =
let axis = [0 .. nCols - 1] in fmap (fromJust . flip M.lookup xyMap) <$> (axis >>= \x -> [axis >>= \y -> [(x, y)]])
-- Dimension of LUX table -> LUX symbols keyed by coordinates luxMap :: Int -> M.Map (Int, Int) Char luxMap n =
(M.fromList . concat) $ zipWith (\y xs -> (zipWith (\x c -> ((x, y), c)) [0 ..] xs)) [0 ..] (luxPattern n)
-- LUX dimension -> 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 zero-based index of grid -> Siamese indices keyed by coordinates siamMap :: Int -> M.Map (Int, Int) Int siamMap n =
let uBound = (2 * n) sPath uBound sMap (x, y) n = let newMap = M.insert (x, y) n sMap in if y == uBound && x == quot uBound 2 then newMap else sPath uBound newMap (nextSiam uBound sMap (x, y)) (n + 1) in sPath uBound (M.fromList []) (quot uBound 2, 0) 1
-- Highest index of square -> Siam xys so far -> xy -> next xy coordinate nextSiam :: Int -> M.Map (Int, Int) Int -> (Int, Int) -> (Int, Int) nextSiam uBound sMap (x, y) =
let alt (a, b) | a > uBound && b < 0 = (uBound, 1) | a > uBound = (0, b) | b < 0 = (a, uBound) | isJust (M.lookup (a, b) sMap) = (a - 1, b + 2) | otherwise = (a, b) in alt (x + 1, y - 1)
-- 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)]
-- 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 30 12 10 13 14 29 31 9 11 16 15 4 2 17 18 36 34 1 3 20 19 33 35 24 22 28 26 5 6 21 23 25 27 8 7 (111,True) 68 66 92 90 16 14 37 38 41 43 65 67 89 91 13 15 40 39 44 42 96 94 20 18 24 22 45 46 69 71 93 95 17 19 21 23 48 47 72 70 4 2 28 26 49 50 76 74 97 99 1 3 25 27 52 51 73 75 100 98 32 30 56 54 80 78 81 82 5 7 29 31 53 55 77 79 84 83 8 6 60 58 64 62 88 86 9 10 33 35 57 59 61 63 85 87 12 11 36 34 (505,True) 120 118 152 150 184 182 20 18 49 50 81 83 85 87 117 119 149 151 181 183 17 19 52 51 84 82 88 86 156 154 188 186 24 22 56 54 57 58 89 91 121 123 153 155 185 187 21 23 53 55 60 59 92 90 124 122 192 190 28 26 32 30 64 62 93 94 125 127 157 159 189 191 25 27 29 31 61 63 96 95 128 126 160 158 4 2 36 34 68 66 97 98 132 130 161 163 193 195 1 3 33 35 65 67 100 99 129 131 164 162 196 194 40 38 72 70 104 102 136 134 165 166 169 171 5 7 37 39 69 71 101 103 133 135 168 167 172 170 8 6 76 74 108 106 140 138 144 142 173 174 9 11 41 43 73 75 105 107 137 139 141 143 176 175 12 10 44 42 112 110 116 114 148 146 180 178 13 14 45 47 77 79 109 111 113 115 145 147 177 179 16 15 48 46 80 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