Magic squares of doubly even order
A magic square of doubly even order has a size that is a multiple of four (e.g. 4, 8, 12).
This means that the subsquares also have an even size, which plays a role in the construction.
1 | 2 | 62 | 61 | 60 | 59 | 7 | 8 |
9 | 10 | 54 | 53 | 52 | 51 | 15 | 16 |
48 | 47 | 19 | 20 | 21 | 22 | 42 | 41 |
40 | 39 | 27 | 28 | 29 | 30 | 34 | 33 |
32 | 31 | 35 | 36 | 37 | 38 | 26 | 25 |
24 | 23 | 43 | 44 | 45 | 46 | 18 | 17 |
49 | 50 | 14 | 13 | 12 | 11 | 55 | 56 |
57 | 58 | 6 | 5 | 4 | 3 | 63 | 64 |
The task: create a magic square of 8 x 8.
- Cf.
- See also
FreeBASIC
<lang freebasic>' version 18-03-2016 ' compile with: fbc -s console ' doubly even magic square 4, 8, 12, 16...
Sub Err_msg(msg As String)
Print msg Beep : Sleep 5000, 1 : Exit Sub
End Sub
Sub de_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 < 4 Then Err_msg( "Error: n is to small") Exit Sub End If
If (n Mod 4) <> 0 Then Err_msg "Error: not possible to make doubly" + _ " 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 q = n \ 4 Dim As UInteger x, y, nr = 1 Dim As String frmt = String(Len(Str(n * n)) +1, "#")
' set up the square For y = 1 To n For x = q +1 To n - q sq(x,y) = 1 Next Next For x = 1 To n For y = q +1 To n - q sq(x, y) Xor= 1 Next Next
' fill the square q = n * n +1 For y = 1 To n For x = 1 To n If sq(x,y) = 0 Then sq(x,y) = q - nr Else sq(x,y) = nr End If nr += 1 Next Next
' check columms and rows For y = 1 To n nr = 0 : q = 0 For x = 1 To n nr += sq(x,y) q += sq(y,x) Next If nr <> magic_sum Or q <> magic_sum Then Err_msg "Error: value <> magic_sum" Exit Sub End If Next
' check diagonals nr = 0 : q = 0 For x = 1 To n nr += sq(x, x) q += sq(n - x +1, n - x +1) Next If nr <> magic_sum Or q <> 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 >=------
de_magicsq(8, "magic8de.txt") : Print
' empty keyboard buffer While Inkey <> "" : Var _key_ = Inkey : Wend Print : Print "hit any key to end program" Sleep End</lang>
- Output:
Single even magic square size: 8*8 The magic sum = 260 64 63 3 4 5 6 58 57 56 55 11 12 13 14 50 49 17 18 46 45 44 43 23 24 25 26 38 37 36 35 31 32 33 34 30 29 28 27 39 40 41 42 22 21 20 19 47 48 16 15 51 52 53 54 10 9 8 7 59 60 61 62 2 1
Java
<lang java>public class MagicSquareDoublyEven {
public static void main(String[] args) { int n = 8; for (int[] row : magicSquareDoublyEven(n)) { for (int x : row) System.out.printf("%2s ", x); System.out.println(); } System.out.printf("\nMagic constant: %d ", (n * n + 1) * n / 2); }
static int[][] magicSquareDoublyEven(final int n) { if (n < 4 || n % 4 != 0) throw new IllegalArgumentException("base must be a positive " + "multiple of 4");
// pattern of count-up vs count-down zones int bits = 0b1001011001101001; int size = n * n; int mult = n / 4; // how many multiples of 4
int[][] result = new int[n][n];
for (int r = 0, i = 0; r < n; r++) { for (int c = 0; c < n; c++, i++) { int bitsPos = c / mult + (r / mult) * 4; result[r][c] = (bits & (1 << bitsPos)) != 0 ? i + 1 : size - i; } } return result; }
}</lang>
1 2 62 61 60 59 7 8 9 10 54 53 52 51 15 16 48 47 19 20 21 22 42 41 40 39 27 28 29 30 34 33 32 31 35 36 37 38 26 25 24 23 43 44 45 46 18 17 49 50 14 13 12 11 55 56 57 58 6 5 4 3 63 64 Magic constant: 260
Perl 6
See Magic squares/Perl 6 for a general magic square generator. Note that it produces a magic square, not the magic square. The output is different each time.
- Output:
With a parameter of 8:
54 16 53 52 10 9 15 51 27 33 28 29 39 40 34 30 19 41 20 21 47 48 42 22 35 25 36 37 31 32 26 38 62 8 61 60 2 1 7 59 6 64 5 4 58 57 63 3 43 17 44 45 23 24 18 46 14 56 13 12 50 49 55 11 The magic number is 260
With a parameter of 12:
36 27 116 26 117 113 112 34 115 114 35 25 144 135 8 134 9 5 4 142 7 6 143 133 85 94 53 95 52 56 57 87 54 55 86 96 61 70 77 71 76 80 81 63 78 79 62 72 24 15 128 14 129 125 124 22 127 126 23 13 120 111 32 110 33 29 28 118 31 30 119 109 37 46 101 47 100 104 105 39 102 103 38 48 132 123 20 122 21 17 16 130 19 18 131 121 97 106 41 107 40 44 45 99 42 43 98 108 12 3 140 2 141 137 136 10 139 138 11 1 73 82 65 83 64 68 69 75 66 67 74 84 49 58 89 59 88 92 93 51 90 91 50 60 The magic number is 870
REXX
Marked numbers indicate that those (sequentially generated) numbers don't get swapped (and thusly, stay in place in the magic square). <lang rexx>/*REXX program constructs a magic square of doubly even sides (a size divisible by 4).*/ n=8; s=n%4; L=n%2-s+1; w=length(n**2) /*size; small sq; low middle; # width*/ @.=0; H=n%2+s /*array default; high middle. */ call gen /*generate a grid in numerical order. */ call diag /*mark numbers on both diagonals. */ call corn /* " " in small corner boxen. */ call midd /* " " in the middle " */ call swap /*swap positive numbers with highest #.*/ call show /*display the doubly even magic square.*/ call sum /* " " magic number for square. */ exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ o: parse arg ?; return n-?+1 /*calculate the "other" (right) column.*/ @: parse arg x,y; return abs(@.x.y) diag: do r=1 for n; @.r.r=-@(r,r); o=o(r); @.r.o=-@(r,o); end; return midd: do r=L to H; do c=L to H; @.r.c=-@(r,c); end; end; return gen: #=0; do r=1 for n; do c=1 for n; #=#+1; @.r.c=#; end; end; return show: #=0; do r=1 for n; $=; do c=1 for n; $=$ right(@(r,c),w); end; say $; end; return sum: #=0; do r=1 for n; #=#+@(r,1); end; say; say 'The magic number is: ' #; return max#: do a=n to 1 by -1; do b=n to 1 by -1; if @.a.b>0 then return; end; end /*──────────────────────────────────────────────────────────────────────────────────────*/ swap: do r=1 for n
do c=1 for n; if @.r.c<0 then iterate; call max# /*find max number.*/ parse value -@.a.b (-@.r.c) with @.r.c @.a.b /*swap two values.*/ end /*c*/ end /*r*/ return
/*──────────────────────────────────────────────────────────────────────────────────────*/ corn: do r=1 for n; if r>s & r<=n-s then iterate /*"corner boxen", size≡S*/
do c=1 for n; if c>s & c<=n-s then iterate; @.r.c=-@(r,c); end /*c*/ end /*r*/ return</lang>
output when using the default input:
1 2 62 61 60 59 7 8 9 10 54 53 52 51 15 16 48 47 19 20 21 22 42 41 40 39 27 28 29 30 34 33 32 31 35 36 37 38 26 25 24 23 43 44 45 46 18 17 49 50 14 13 12 11 55 56 57 58 6 5 4 3 63 64 The magic number is: 260
zkl
<lang zkl>class MagicSquareDoublyEven{
fcn init(n){ var result=magicSquareDoublyEven(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 magicSquareDoublyEven(n){ if (n<4 or n%4!=0 or n>16)
throw(Exception.ValueError("base must be a positive multiple of 4"));
bits,size,mult:=0b1001011001101001, n*n, n/4; result:=n.pump(List(),n.pump(List(),0).copy); // array[n,n] of zero
foreach i in (size){
bitsPos:=(i%n)/mult + (i/(n*mult)*4); value:=(bits.bitAnd((2).pow(bitsPos))) and i+1 or size-i; result[i/n][i%n]=value;
} result; }
} MagicSquareDoublyEven(8).println();</lang>
- Output:
1 2 62 61 60 59 7 8 9 10 54 53 52 51 15 16 48 47 19 20 21 22 42 41 40 39 27 28 29 30 34 33 32 31 35 36 37 38 26 25 24 23 43 44 45 46 18 17 49 50 14 13 12 11 55 56 57 58 6 5 4 3 63 64 Magic constant: 260