Magic squares of odd order: Difference between revisions
(Add Seed7 example) |
|||
Line 829: | Line 829: | ||
putStrLn $ display $ magicNumber x |
putStrLn $ display $ magicNumber x |
||
</lang> |
</lang> |
||
=={{header|Mathematica}}== |
|||
Rotate rows and columns of the initial matrix with rows filled in order 1 2 3 .... N^2 |
|||
Method from http://www.jsoftware.com/papers/eem/magicsq.htm |
|||
<lang Mathematica> |
|||
rp[v_, pos_] := RotateRight[v, (Length[v] + 1)/2 - pos]; |
|||
rho[m_] := MapIndexed[rp, m]; |
|||
magic[n_] := |
|||
rho[Transpose[rho[Table[i*n + j, {i, 0, n - 1}, {j, 1, n}]]]]; |
|||
square = magic[11] // Grid |
|||
Print["Magic number is ", Total[square[[1, 1]]]] |
|||
</lang> |
|||
Output (alignment lost in translation to text): |
|||
{68, 80, 92, 104, 116, 7, 19, 31, 43, 55, 56}, |
|||
{81, 93, 105, 117, 8, 20, 32, 44, 45, 57, 69}, |
|||
{94, 106, 118, 9, 21, 33, 34, 46, 58, 70, 82}, |
|||
{107, 119, 10, 22, 23, 35, 47, 59, 71, 83, 95}, |
|||
{120, 11, 12, 24, 36, 48, 60, 72, 84, 96, 108}, |
|||
{1, 13, 25, 37, 49, 61, 73, 85, 97, 109, 121}, |
|||
{14, 26, 38, 50, 62, 74, 86, 98, 110, 111, 2}, |
|||
{27, 39, 51, 63, 75, 87, 99, 100, 112, 3, 15}, |
|||
{40, 52, 64, 76, 88, 89, 101, 113, 4, 16, 28}, |
|||
{53, 65, 77, 78, 90, 102, 114, 5, 17, 29, 41}, |
|||
{66, 67, 79, 91, 103, 115, 6, 18, 30, 42, 54} |
|||
Magic number is 671 |
|||
Output from code that checks the results |
|||
Rows |
|||
{671,671,671,671,671,671,671,671,671,671,671} |
|||
Columns |
|||
{671,671,671,671,671,671,671,671,671,671,671} |
|||
Diagonals |
|||
671 |
|||
671 |
|||
=={{header|Maxima}}== |
=={{header|Maxima}}== |
Revision as of 01:56, 3 July 2014
You are encouraged to solve this task according to the task description, using any language you may know.
A magic square is an 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 1st 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 , generate a magic square with the integers and show the results. Optionally, show the magic number.
You should demonstrate the generator by showing at least a magic square for .
- Also see
- MathWorld™ entry: Magic_square
Ada
<lang Ada>with Ada.Text_IO, Ada.Command_Line;
procedure Magic_Square is
N: constant Positive := Positive'Value(Ada.Command_Line.Argument(1)); subtype Constants is Natural range 1 .. N*N; package CIO is new Ada.Text_IO.Integer_IO(Constants); Undef: constant Natural := 0;
subtype Index is Natural range 0 .. N-1; function Inc(I: Index) return Index is (if I = N-1 then 0 else I+1); function Dec(I: Index) return Index is (if I = 0 then N-1 else I-1); A: array(Index, Index) of Natural := (others => (others => Undef)); -- initially undefined; at the end holding the magic square X: Index := 0; Y: Index := N/2; -- start position for the algorithm
begin
for I in Constants loop -- write 1, 2, ..., N*N into the magic array A(X, Y) := I; -- write I into the magic array if A(Dec(X), Inc(Y)) = Undef then
X := Dec(X); Y := Inc(Y); -- go right-up
else
X := Inc(X); -- go down
end if; end loop; for Row in Index loop -- output the magic array for Collumn in Index loop
CIO.Put(A(Row, Collumn), Width => (if N*N < 10 then 2 elsif N*N < 100 then 3 else 4));
end loop; Ada.Text_IO.New_Line; end loop;
end Magic_Square;</lang>
- Output:
>./magic_square 3 8 1 6 3 5 7 4 9 2 >./magic_square 11 68 81 94 107 120 1 14 27 40 53 66 80 93 106 119 11 13 26 39 52 65 67 92 105 118 10 12 25 38 51 64 77 79 104 117 9 22 24 37 50 63 76 78 91 116 8 21 23 36 49 62 75 88 90 103 7 20 33 35 48 61 74 87 89 102 115 19 32 34 47 60 73 86 99 101 114 6 31 44 46 59 72 85 98 100 113 5 18 43 45 58 71 84 97 110 112 4 17 30 55 57 70 83 96 109 111 3 16 29 42 56 69 82 95 108 121 2 15 28 41 54
AutoHotkey
<lang autohotkey> msgbox % OddMagicSquare(5) msgbox % OddMagicSquare(7) return
OddMagicSquare(oddN){ sq := oddN**2 obj := {} loop % oddN obj[A_Index] := {} ; dis is row mid := Round((oddN+1)/2) sum := Round(sq*(sq+1)/2/oddN) obj[1][mid] := 1 cR := 1 , cC := mid loop % sq-1 { done := 0 , a := A_index+1 while !done { nR := cR-1 , nC := cC+1 if !nR nR := oddN if (nC>oddN) nC := 1 if obj[nR][nC] ;filled cR += 1 else cR := nR , cC := nC if !obj[cR][cC] obj[cR][cC] := a , done := 1 } }
str := "Magic Constant for " oddN "x" oddN " is " sum "`n" for k,v in obj { for k2,v2 in v str .= " " v2 str .= "`n" } return str } </lang>
Output:
Magic Constant for 5x5 is 65 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 Magic Constant for 7x7 is 175 30 39 48 1 10 19 28 38 47 7 9 18 27 29 46 6 8 17 26 35 37 5 14 16 25 34 36 45 13 15 24 33 42 44 4 21 23 32 41 43 3 12 22 31 40 49 2 11 20
AWK
<lang AWK>
- syntax: GAWK -f MAGIC_SQUARES_OF_ODD_ORDER.AWK
BEGIN {
build(5) build(3,1) # verify sum build(7) exit(0)
} function build(n,check, arr,i,width,x,y) {
if (n !~ /^[0-9]*[13579]$/ || n < 3) { printf("error: %s is invalid\n",n) return } printf("\nmagic constant for %dx%d is %d\n",n,n,(n*n+1)*n/2) x = 0 y = int(n/2) for (i=1; i<=(n*n); i++) { arr[x,y] = i if (arr[(x+n-1)%n,(y+n+1)%n]) { x = (x+n+1) % n } else { x = (x+n-1) % n y = (y+n+1) % n } } width = length(n*n) for (x=0; x<n; x++) { for (y=0; y<n; y++) { printf("%*s ",width,arr[x,y]) } printf("\n") } if (check) { verify(arr,n) }
} function verify(arr,n, total,x,y) { # verify sum of each row, column and diagonal
print("\nverify")
- horizontal
for (x=0; x<n; x++) { total = 0 for (y=0; y<n; y++) { printf("%d ",arr[x,y]) total += arr[x,y] } printf("\t: %d row %d\n",total,x+1) }
- vertical
for (y=0; y<n; y++) { total = 0 for (x=0; x<n; x++) { printf("%d ",arr[x,y]) total += arr[x,y] } printf("\t: %d column %d\n",total,y+1) }
- left diagonal
total = 0 for (x=y=0; x<n; x++ y++) { printf("%d ",arr[x,y]) total += arr[x,y] } printf("\t: %d diagonal top left to bottom right\n",total)
- right diagonal
x = n - 1 total = 0 for (y=0; y<n; y++ x--) { printf("%d ",arr[x,y]) total += arr[x,y] } printf("\t: %d diagonal bottom left to top right\n",total)
} </lang>
output:
magic constant for 5x5 is 65 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 magic constant for 3x3 is 15 8 1 6 3 5 7 4 9 2 verify 8 1 6 : 15 row 1 3 5 7 : 15 row 2 4 9 2 : 15 row 3 8 3 4 : 15 column 1 1 5 9 : 15 column 2 6 7 2 : 15 column 3 8 5 2 : 15 diagonal top left to bottom right 4 5 6 : 15 diagonal bottom left to top right magic constant for 7x7 is 175 30 39 48 1 10 19 28 38 47 7 9 18 27 29 46 6 8 17 26 35 37 5 14 16 25 34 36 45 13 15 24 33 42 44 4 21 23 32 41 43 3 12 22 31 40 49 2 11 20
bc
<lang bc>define magic_constant(n) {
return(((n * n + 1) / 2) * n)
}
define print_magic_square(n) {
auto i, x, col, row, len, old_scale
old_scale = scale scale = 0 len = length(n * n)
print "Magic constant for n=", n, ": ", magic_constant(n), "\n" for (row = 1; row <= n; row++) { for (col = 1; col <= n; col++) { x = n * ((row + col - 1 + (n / 2)) % n) + \ ((row + 2 * col - 2) % n) + 1 for (i = 0; i < len - length(x); i++) { print " " } print x if (col != n) print " " } print "\n" }
scale = old_scale
}
temp = print_magic_square(5)</lang>
- Output:
Magic constant for n=5: 65 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9
C
<lang c>#include <stdio.h>
- include <stdlib.h>
int main(int argc, char **argv) {
- define M(x) ((x + n - 1) % n)
int i, j, k, n, *m; char fmt[16];
if (argc < 2 || (n = atoi(argv[1])) <= 0 || !(n&1)) fprintf(stderr, "forcing size %d\n", n = 5);
m = calloc(n*n, sizeof(*m));
i = 0, j = n/2; for (k = 1; k <= n*n; k++) { m[i*n + j] = k; if (m[M(i)*n + M(j)]) i = (i+1) % n; else i = M(i), j = M(j); }
for (i = 2, j = 1; j <= n*n; ++i, j *= 10); sprintf(fmt, "%%%dd", i);
for (i = 0; i < n; i++) { for (j = 0; j < n; j++) printf(fmt, m[i*n + j]); putchar('\n'); }
return 0;
}</lang>
- Output:
% ./a.out forcing size 5 15 8 1 24 17 16 14 7 5 23 22 20 13 6 4 3 21 19 12 10 9 2 25 18 11
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++; sz = d; sqr = new int[sz * sz]; memset( sqr, 0, sz * sz * sizeof( int ) ); fillSqr(); }
void display() { cout << "Odd 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 fillSqr() {
int sx = sz / 2, sy = 0, c = 0; while( c < sz * sz ) { if( !sqr[sx + sy * sz] ) { sqr[sx + sy * sz]= c + 1; inc( sx ); dec( sy ); c++; } else { dec( sx ); inc( sy ); inc( sy ); } }
}
int magicNumber() { return ( ( ( sz * sz + 1 ) / 2 ) * sz ); }
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( 5 ); s.display(); return system( "pause" );
} </lang>
- Output:
Odd Magic Square: 5 x 5 It's Magic Sum is: 65 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 Odd Magic Square: 7 x 7 It's Magic Sum is: 175 30 39 48 1 10 19 28 38 47 7 9 18 27 29 46 6 8 17 26 35 37 5 14 16 25 34 36 45 13 15 24 33 42 44 4 21 23 32 41 43 3 12 22 31 40 49 2 11 20
Common Lisp
<lang lisp>(defun magic-square (n)
(loop for i from 1 to n collect (loop for j from 1 to n collect (+ (* n (mod (+ i j (floor n 2) -1) n)) (mod (+ i (* 2 j) -2) n) 1))))
(defun magic-constant (n)
(* n (/ (1+ (* n n)) 2)))
(defun output (n)
(format T "Magic constant for n=~a: ~a~%" n (magic-constant n)) (let* ((size (length (write-to-string (* n n)))) (format-str (format NIL "~~{~~{~~~ad~~^ ~~}~~%~~}~~%" size))) (format T format-str (magic-square n))))</lang>
- Output:
> (output 5) Magic constant for n=5: 65 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9
D
<lang d>void main(in string[] args) {
import std.stdio, std.conv, std.range, std.algorithm,std.exception;
immutable n = args.length == 2 ? args[1].to!uint : 5; enforce(n > 0 && n % 2 == 1, "Only odd n > 1"); immutable len = text(n ^^ 2).length.text;
foreach (immutable r; 1 .. n + 1) writefln("%-(%" ~ len ~ "d %)", iota(1, n + 1) .map!(c => n * ((r + c - 1 + n / 2) % n) + ((r + 2 * c - 2) % n)));
writeln("\nMagic constant: ", (n * n + 1) * n / 2);
}</lang>
- Output:
16 23 0 7 14 22 4 6 13 15 3 5 12 19 21 9 11 18 20 2 10 17 24 1 8 Magic constant: 65
Alternative Version
<lang d>import std.stdio, std.conv, std.string, std.range, std.algorithm;
uint[][] magicSquare(immutable uint n) pure nothrow in {
assert(n > 0 && n % 2 == 1);
} out(mat) {
// mat is square of the right size. assert(mat.length == n); assert(mat.all!(row => row.length == n));
immutable magic = mat[0].sum;
// The sum of all rows is the same magic number. assert(mat.all!(row => row.sum == magic));
// The sum of all columns is the same magic number. //assert(mat.transposed.all!(col => col.sum == magic)); assert(mat.dup.transposed.all!(col => col.sum == magic));
// The sum of the main diagonals is the same magic number. //assert(mat.enumerate.map!(ir => ir[1][ir[0]]).sum == magic); assert(n.iota.zip(mat).map!(ir => ir[1][ir[0]]).sum == magic); //assert(mat.enumerate.map!(ir => ir[1][$-1-ir[0]]).sum == magic); assert(n.iota.zip(mat).map!(ir => ir[1][$-1-ir[0]]).sum == magic);
} body {
enum M = (in uint x) pure nothrow => (x + n - 1) % n; auto m = new uint[][](n, n);
uint i = 0; uint j = n / 2; foreach (immutable uint k; 1 .. n ^^ 2 + 1) { m[i][j] = k; if (m[M(i)][M(j)]) { i = (i + 1) % n; } else { i = M(i); j = M(j); } }
return m;
}
void showSquare(in uint[][] m) in {
assert(m.all!(row => row.length == m[0].length));
} body {
immutable maxLen = text(m.length ^^ 2).length.text; writefln("%(%(%" ~ maxLen ~ "d %)\n%)", m); writeln("\nMagic constant: ", m[0].sum);
}
int main(in string[] args) {
if (args.length == 1) { 5.magicSquare.showSquare; return 0; } else if (args.length == 2) { immutable n = args[1].to!uint; if (n > 0 && n % 2 == 1) { n.magicSquare.showSquare; return 0; } }
stderr.writefln("Requires n odd and larger than 0."); return 1;
}</lang>
- Output:
15 8 1 24 17 16 14 7 5 23 22 20 13 6 4 3 21 19 12 10 9 2 25 18 11 Magic constant: 65
Icon and Unicon
This is a Unicon-specific solution because of the use of the [: ... :] construct. <lang unicon>procedure main(A)
n := integer(!A) | 3 write("Magic number: ",n*(n*n+1)/2) sq := buildSquare(n) showSquare(sq)
end
procedure buildSquare(n)
sq := [: |list(n)\n :] r := 0 c := n/2 every i := !(n*n) do { /sq[r+1,c+1] := i nr := (n+r-1)%n nc := (c+1)%n if /sq[nr+1,nc+1] then (r := nr,c := nc) else r := (r+1)%n } return sq
end
procedure showSquare(sq)
n := *sq s := *(n*n)+2 every r := !sq do every writes(right(!r,s)|"\n")
end</lang>
Sample output:
->ms 5 Magic number: 65 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 ->
J
Based on http://www.jsoftware.com/papers/eem/magicsq.htm
<lang J>ms=: i:@<.@-: |."0 1&|:^:2 >:@i.@,~</lang>
In other words, generate a square of counting integers, like this: <lang J> >:@i.@,~ 3 1 2 3 4 5 6 7 8 9</lang>
Then generate a list of integers centering on 0 up to half of that value, like this: <lang J> i:@<.@-: 3 _1 0 1</lang>
Finally, rotate each corresponding row and column of the table by the corresponding value in the list. We can use the same instructions to rotate both rows and columns if we transpose the matrix before rotating (and perform this transpose+rotate twice).
Example use:
<lang J> ms 5
9 15 16 22 3
20 21 2 8 14
1 7 13 19 25
12 18 24 5 6 23 4 10 11 17
~.+/ms 5
65
~.+/ms 101
515201</lang>
Java
<lang java>public class MagicSquare {
public static void main(String[] args) { int n = 5; for (int[] row : magicSquareOdd(n)) { for (int x : row) System.out.format("%2s ", x); System.out.println(); } System.out.printf("\nMagic constant: %d ", (n * n + 1) * n / 2); }
public static int[][] magicSquareOdd(final int base) { if (base % 2 == 0 || base < 3) throw new IllegalArgumentException("base must be odd and > 2");
int[][] grid = new int[base][base]; int r = 0, number = 0; int size = base * base;
int c = base / 2; while (number++ < size) { grid[r][c] = number; if (r == 0) { if (c == base - 1) { r++; } else { r = base - 1; c++; } } else { if (c == base - 1) { r--; c = 0; } else { if (grid[r - 1][c + 1] == 0) { r--; c++; } else { r++; } } } } return grid; }
}</lang>
Output:
17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 Magic constant: 65
Go
<lang go>package main
import (
"fmt" "log"
)
func ms(n int) (int, []int) {
M := func(x int) int { return (x + n - 1) % n } if n <= 0 || n&1 == 0 { n = 5 log.Println("forcing size", n) } m := make([]int, n*n) i, j := 0, n/2 for k := 1; k <= n*n; k++ { m[i*n+j] = k if m[M(i)*n+M(j)] != 0 { i = (i + 1) % n } else { i, j = M(i), M(j) } } return n, m
}
func main() {
n, m := ms(5) i := 2 for j := 1; j <= n*n; j *= 10 { i++ } f := fmt.Sprintf("%%%dd", i) for i := 0; i < n; i++ { for j := 0; j < n; j++ { fmt.Printf(f, m[i*n+j]) } fmt.Println() }
}</lang>
- Output:
15 8 1 24 17 16 14 7 5 23 22 20 13 6 4 3 21 19 12 10 9 2 25 18 11
Haskell
<lang haskell> -- as a translation from imperative code, this is probably not a "good" implementation import Data.List
type Var = (Int, Int, Int, Int) -- sx sy sz c
magicSum :: Int -> Int magicSum x = ((x * x + 1) `div` 2) * x
wrapInc :: Int -> Int -> Int wrapInc max x
| x + 1 == max = 0 | otherwise = x + 1
wrapDec :: Int -> Int -> Int wrapDec max x
| x == 0 = max - 1 | otherwise = x - 1
isZero :: Int -> Int -> Int -> Bool isZero m x y = m !! x !! y == 0
setAt :: (Int,Int) -> Int -> Int -> Int setAt (x, y) val table
| (upper, current : lower) <- splitAt x table, (left, this : right) <- splitAt y current = upper ++ (left ++ val : right) : lower | otherwise = error "Outside"
create :: Int -> Int create x = replicate x $ replicate x 0
cells :: Int -> Int cells m = x*x where x = length m
fill :: Var -> Int -> Int fill (sx, sy, sz, c) m
| c < cells m = if isZero m sx sy then fill ((wrapInc sz sx), (wrapDec sz sy), sz, c + 1) (setAt (sx, sy) (c + 1) m) else fill ((wrapDec sz sx), (wrapInc sz(wrapInc sz sy)), sz, c) m | otherwise = m
magicNumber :: Int -> Int magicNumber d = transpose $ fill (d `div` 2, 0, d, 0) (create d)
display :: Int -> String display (x:xs)
| null xs = vdisplay x | otherwise = vdisplay x ++ ('\n' : display xs)
vdisplay :: [Int] -> String vdisplay (x:xs)
| null xs = show x | otherwise = show x ++ " " ++ vdisplay xs
magicSquare x = do
putStr "Magic Square of " putStr $ show x putStr " = " putStrLn $ show $ magicSum x putStrLn $ display $ magicNumber x
</lang>
Mathematica
Rotate rows and columns of the initial matrix with rows filled in order 1 2 3 .... N^2
Method from http://www.jsoftware.com/papers/eem/magicsq.htm
<lang Mathematica> rp[v_, pos_] := RotateRight[v, (Length[v] + 1)/2 - pos]; rho[m_] := MapIndexed[rp, m]; magic[n_] :=
rho[Transpose[rho[Table[i*n + j, {i, 0, n - 1}, {j, 1, n}]]]];
square = magic[11] // Grid Print["Magic number is ", Total[square1, 1]] </lang> Output (alignment lost in translation to text):
{68, 80, 92, 104, 116, 7, 19, 31, 43, 55, 56}, {81, 93, 105, 117, 8, 20, 32, 44, 45, 57, 69}, {94, 106, 118, 9, 21, 33, 34, 46, 58, 70, 82}, {107, 119, 10, 22, 23, 35, 47, 59, 71, 83, 95}, {120, 11, 12, 24, 36, 48, 60, 72, 84, 96, 108}, {1, 13, 25, 37, 49, 61, 73, 85, 97, 109, 121}, {14, 26, 38, 50, 62, 74, 86, 98, 110, 111, 2}, {27, 39, 51, 63, 75, 87, 99, 100, 112, 3, 15}, {40, 52, 64, 76, 88, 89, 101, 113, 4, 16, 28}, {53, 65, 77, 78, 90, 102, 114, 5, 17, 29, 41}, {66, 67, 79, 91, 103, 115, 6, 18, 30, 42, 54}
Magic number is 671
Output from code that checks the results Rows
{671,671,671,671,671,671,671,671,671,671,671}
Columns
{671,671,671,671,671,671,671,671,671,671,671}
Diagonals
671
671
Maxima
<lang Maxima>wrap1(i):= if i>%n% then 1 else if i<1 then %n% else i; wrap(P):=maplist('wrap1, P);
uprigth(P):= wrap(P + [-1, 1]); down(P):= wrap(P + [1, 0]);
magic(n):=block([%n%: n,
M: zeromatrix (n, n), P: [1, (n + 1)/2], m: 1, Pc], do ( M[P[1],P[2]]: m, m: m + 1, if m>n^2 then return(M), Pc: uprigth(P), if M[Pc[1],Pc[2]]=0 then P: Pc else while(M[P[1],P[2]]#0) do P: down(P)));</lang>
Usage: <lang output>(%i6) magic(3);
[ 8 1 6 ] [ ]
(%o6) [ 3 5 7 ]
[ ] [ 4 9 2 ]
(%i7) magic(5);
[ 17 24 1 8 15 ] [ ] [ 23 5 7 14 16 ] [ ]
(%o7) [ 4 6 13 20 22 ]
[ ] [ 10 12 19 21 3 ] [ ] [ 11 18 25 2 9 ]
(%i8) magic(7);
[ 30 39 48 1 10 19 28 ] [ ] [ 38 47 7 9 18 27 29 ] [ ] [ 46 6 8 17 26 35 37 ] [ ]
(%o8) [ 5 14 16 25 34 36 45 ]
[ ] [ 13 15 24 33 42 44 4 ] [ ] [ 21 23 32 41 43 3 12 ] [ ] [ 22 31 40 49 2 11 20 ]
/* magic number for n=7 */ (%i9) lsum(q, q, first(magic(7))); (%o9) 175</lang>
Perl 6
<lang perl6>sub MAIN (Int $n = 5) {
note "Sorry, must be a positive odd integer." and exit if $n %% 2 or $n < 0;
my $x = $n/2; my $y = 0; my $i = 1; my @sq;
@sq[($i % $n ?? $y-- !! $y++) % $n][($i % $n ?? $x++ !! $x) % $n] = $i++ for ^($n * $n);
my $f = "%{$i.chars}d"; say .fmt($f, ' ') for @sq;
say "\nThe magic number is ", [+] @sq[0].list;
}</lang>
- Output:
Default, No parameter:
17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 The magic number is 65
With a parameter of 19
192 213 234 255 276 297 318 339 360 1 22 43 64 85 106 127 148 169 190 212 233 254 275 296 317 338 359 19 21 42 63 84 105 126 147 168 189 191 232 253 274 295 316 337 358 18 20 41 62 83 104 125 146 167 188 209 211 252 273 294 315 336 357 17 38 40 61 82 103 124 145 166 187 208 210 231 272 293 314 335 356 16 37 39 60 81 102 123 144 165 186 207 228 230 251 292 313 334 355 15 36 57 59 80 101 122 143 164 185 206 227 229 250 271 312 333 354 14 35 56 58 79 100 121 142 163 184 205 226 247 249 270 291 332 353 13 34 55 76 78 99 120 141 162 183 204 225 246 248 269 290 311 352 12 33 54 75 77 98 119 140 161 182 203 224 245 266 268 289 310 331 11 32 53 74 95 97 118 139 160 181 202 223 244 265 267 288 309 330 351 31 52 73 94 96 117 138 159 180 201 222 243 264 285 287 308 329 350 10 51 72 93 114 116 137 158 179 200 221 242 263 284 286 307 328 349 9 30 71 92 113 115 136 157 178 199 220 241 262 283 304 306 327 348 8 29 50 91 112 133 135 156 177 198 219 240 261 282 303 305 326 347 7 28 49 70 111 132 134 155 176 197 218 239 260 281 302 323 325 346 6 27 48 69 90 131 152 154 175 196 217 238 259 280 301 322 324 345 5 26 47 68 89 110 151 153 174 195 216 237 258 279 300 321 342 344 4 25 46 67 88 109 130 171 173 194 215 236 257 278 299 320 341 343 3 24 45 66 87 108 129 150 172 193 214 235 256 277 298 319 340 361 2 23 44 65 86 107 128 149 170 The magic number is 3439
PL/I
<lang PL/I>magic: procedure options (main); /* 18 April 2014 */
declare n fixed binary;
put skip list ('What is the order of the magic square?'); get list (n); if n < 3 | iand(n, 1) = 0 then do; put skip list ('The value is out of range'); stop; end; put skip list ('The order is ' || trim(n));
begin; declare m(n, n) fixed, (i, j, k) fixed binary;
on subrg snap put data (i, j, k); m = 0; i = 1; j = (n+1)/2;
do k = 1 to n*n; if m(i,j) = 0 then m(i,j) = k; else do; i = i + 2; j = j + 1; if i > n then i = mod(i,n); if j > n then j = 1; m(i,j) = k; end; i = i - 1; j = j - 1; if i < 1 then i = n; if j < 1 then j = n; end;
do i = 1 to n; put skip edit (m(i, *)) (f(4)); end;
put skip list ('The magic number is' || sum(m(1,*))); end;
end magic;</lang> Outputs:
What is the order of the magic square? The order is 5 15 8 1 24 17 16 14 7 5 23 22 20 13 6 4 3 21 19 12 10 9 2 25 18 11 The magic number is 65 What is the order of the magic square? The order is 7 28 19 10 1 48 39 30 29 27 18 9 7 47 38 37 35 26 17 8 6 46 45 36 34 25 16 14 5 4 44 42 33 24 15 13 12 3 43 41 32 23 21 20 11 2 49 40 31 22 The magic number is 175
Python
<lang python>>>> def magic(n):
for row in range(1, n + 1): print(' '.join('%*i' % (len(str(n**2)), cell) for cell in (n * ((row + col - 1 + n // 2) % n) + ((row + 2 * col - 2) % n) + 1 for col in range(1, n + 1)))) print('\nAll sum to magic number %i' % ((n * n + 1) * n // 2))
>>> for n in (5, 3, 7):
print('\nOrder %i\n=======' % n)
magic(n)
Order 5
=
17 24 1 8 15 23 5 7 14 16
4 6 13 20 22
10 12 19 21 3 11 18 25 2 9
All sum to magic number 65
Order 3
=
8 1 6 3 5 7 4 9 2
All sum to magic number 15
Order 7
=
30 39 48 1 10 19 28 38 47 7 9 18 27 29 46 6 8 17 26 35 37
5 14 16 25 34 36 45
13 15 24 33 42 44 4 21 23 32 41 43 3 12 22 31 40 49 2 11 20
All sum to magic number 175 >>> </lang>
Racket
<lang racket>#lang racket
- Using "helpful formulae" in
(define (squares n) n)
(define (last-no n) (sqr n))
(define (middle-no n) (/ (add1 (sqr n)) 2))
(define (M n) (* n (middle-no n)))
(define ((Ith-row-Jth-col n) I J)
(+ (* (modulo (+ I J -1 (exact-floor (/ n 2))) n) n) (modulo (+ I (* 2 J) -2) n) 1))
(define (magic-square n)
(define IrJc (Ith-row-Jth-col n)) (for/list ((I (in-range 1 (add1 n)))) (for/list ((J (in-range 1 (add1 n)))) (IrJc I J))))
(define (fmt-list-of-lists l-o-l width)
(string-join (for/list ((row l-o-l)) (string-join (map (λ (x) (~a #:align 'right #:width width x)) row) " ")) "\n"))
(define (show-magic-square n)
(format "MAGIC SQUARE ORDER:~a~%~a~%MAGIC NUMBER:~a~%" n (fmt-list-of-lists (magic-square n) (+ (order-of-magnitude (last-no n)) 1)) (M n)))
(displayln (show-magic-square 3)) (displayln (show-magic-square 5)) (displayln (show-magic-square 9))</lang>
- Output:
MAGIC SQUARE ORDER:3 8 1 6 3 5 7 4 9 2 Magic Number:15 MAGIC SQUARE ORDER:5 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 Magic Number:65 MAGIC SQUARE ORDER:9 47 58 69 80 1 12 23 34 45 57 68 79 9 11 22 33 44 46 67 78 8 10 21 32 43 54 56 77 7 18 20 31 42 53 55 66 6 17 19 30 41 52 63 65 76 16 27 29 40 51 62 64 75 5 26 28 39 50 61 72 74 4 15 36 38 49 60 71 73 3 14 25 37 48 59 70 81 2 13 24 35 Magic Number:369
REXX
<lang rexx>/*REXX program generates and displays true magic squares (for odd N). */ parse arg N .; if N== then N=5 /*matrix size ¬given? Use default*/ w=length(N*N); r=2; c=(n+1)%2-1 /*define initial row and column. */ @.=. /* [↓] uses the Siamese method.*/
do j=1 for n*n; br=r==N & c==N; r=r-1; c=c+1 /*BR=bottom right*/ if r<1 & c>N then do; r=r+2; c=c-1; end /*R under, C over*/ if r<1 then r=n; if r>n then r=1; if c>n then c=1 /*overflow*/ if @.r.c\==. then do; r=r+2; c=c-1; if br then do; r=N; c=c+1; end;end @.r.c=j /*assign #───►square matrix cell.*/ end /*j*/ /* [↑] can handle even N matrix.*/ /* [↓] displays (aligned) matrix*/ do r=1 for N; _= /*display 1 matrix row at a time.*/ do c=1 for N; _=_ right(@.r.c, w); end /*c*/ /*build row*/ say substr(_,2) /*row has an extra leading blank.*/ end /*c*/ /* [↑] also right-justified #s.*/
say /*might as well show a blank line*/ if N//2 then say 'The magic number (or magic constant is): ' N*(n*n+1)%2
/*stick a fork in it, we're done.*/</lang>
output using the default input of 5:
17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 The magic number (or magic constant is): 65
output using the default input of 3:
8 1 6 3 5 7 4 9 2 The magic number (or magic constant is): 15
output using the input of: 19:
192 213 234 255 276 297 318 339 360 1 22 43 64 85 106 127 148 169 190 212 233 254 275 296 317 338 359 19 21 42 63 84 105 126 147 168 189 191 232 253 274 295 316 337 358 18 20 41 62 83 104 125 146 167 188 209 211 252 273 294 315 336 357 17 38 40 61 82 103 124 145 166 187 208 210 231 272 293 314 335 356 16 37 39 60 81 102 123 144 165 186 207 228 230 251 292 313 334 355 15 36 57 59 80 101 122 143 164 185 206 227 229 250 271 312 333 354 14 35 56 58 79 100 121 142 163 184 205 226 247 249 270 291 332 353 13 34 55 76 78 99 120 141 162 183 204 225 246 248 269 290 311 352 12 33 54 75 77 98 119 140 161 182 203 224 245 266 268 289 310 331 11 32 53 74 95 97 118 139 160 181 202 223 244 265 267 288 309 330 351 31 52 73 94 96 117 138 159 180 201 222 243 264 285 287 308 329 350 10 51 72 93 114 116 137 158 179 200 221 242 263 284 286 307 328 349 9 30 71 92 113 115 136 157 178 199 220 241 262 283 304 306 327 348 8 29 50 91 112 133 135 156 177 198 219 240 261 282 303 305 326 347 7 28 49 70 111 132 134 155 176 197 218 239 260 281 302 323 325 346 6 27 48 69 90 131 152 154 175 196 217 238 259 280 301 322 324 345 5 26 47 68 89 110 151 153 174 195 216 237 258 279 300 321 342 344 4 25 46 67 88 109 130 171 173 194 215 236 257 278 299 320 341 343 3 24 45 66 87 108 129 150 172 193 214 235 256 277 298 319 340 361 2 23 44 65 86 107 128 149 170 The magic number (or magic constant is): 3439
Ruby
<lang ruby>def odd_magic_square(n)
raise ArgumentError "Need odd positive number" if n.even? || n <= 0 n.times.map{|i| n.times.map{|j| n*((i+j+1+n/2)%n) + ((i+2*j-5)%n) + 1} }
end
[3, 5, 9].each do |n|
puts "\nSize #{n}, magic sum #{(n*n+1)/2*n}" fmt = "%#{(n*n).to_s.size + 1}d" * n odd_magic_square(n).each{|row| puts fmt % row}
end </lang>
- Output:
Size 3, magic sum 15 8 1 6 3 5 7 4 9 2 Size 5, magic sum 65 16 23 5 7 14 22 4 6 13 20 3 10 12 19 21 9 11 18 25 2 15 17 24 1 8 Size 9, magic sum 369 50 61 72 74 4 15 26 28 39 60 71 73 3 14 25 36 38 49 70 81 2 13 24 35 37 48 59 80 1 12 23 34 45 47 58 69 9 11 22 33 44 46 57 68 79 10 21 32 43 54 56 67 78 8 20 31 42 53 55 66 77 7 18 30 41 52 63 65 76 6 17 19 40 51 62 64 75 5 16 27 29
Seed7
<lang seed7>$ include "seed7_05.s7i";
const func integer: succ (in integer: num, in integer: max) is
return succ(num mod max);
const func integer: pred (in integer: num, in integer: max) is
return succ((num - 2) mod max);
const proc: main is func
local var integer: size is 3; var array array integer: magic is 0 times 0 times 0; var integer: row is 1; var integer: column is 1; var integer: number is 0; begin if length(argv(PROGRAM)) >= 1 then size := integer parse (argv(PROGRAM)[1]); end if; magic := size times size times 0; column := succ(size div 2); for number range 1 to size ** 2 do magic[row][column] := number; if magic[pred(row, size)][succ(column, size)] = 0 then row := pred(row, size); column := succ(column, size); else row := succ(row, size); end if; end for; for key row range magic do for key column range magic[row] do write(magic[row][column] lpad 4); end for; writeln; end for; end func;</lang>
- Output:
> s7 magicSquaresOfOddOrder 7 SEED7 INTERPRETER Version 5.0.5203 Copyright (c) 1990-2014 Thomas Mertes 30 39 48 1 10 19 28 38 47 7 9 18 27 29 46 6 8 17 26 35 37 5 14 16 25 34 36 45 13 15 24 33 42 44 4 21 23 32 41 43 3 12 22 31 40 49 2 11 20
Tcl
<lang tcl>proc magicSquare {order} {
if {!($order & 1) || $order < 0} {
error "order must be odd and positive"
} set s [lrepeat $order [lrepeat $order 0]] set x [expr {$order / 2}] set y 0 for {set i 1} {$i <= $order**2} {incr i} {
lset s $y $x $i set x [expr {($x + 1) % $order}] set y [expr {($y - 1) % $order}] if {[lindex $s $y $x]} { set x [expr {($x - 1) % $order}] set y [expr {($y + 2) % $order}] }
} return $s
}</lang> Demonstrating:
<lang tcl>package require Tcl 8.6
set square [magicSquare 5] puts [join [lmap row $square {join [lmap n $row {format "%2s" $n}]}] "\n"] puts "magic number = [tcl::mathop::+ {*}[lindex $square 0]]"</lang>
- Output:
17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 magic number = 65
zkl
<lang zkl>fcn rmod(n,m){ n=n%m; if (n<0) n+=m; n } // Ruby: -5%3-->1 fcn odd_magic_square(n){ //-->list of n*n numbers, row order
if (n.isEven or n <= 0) throw(Exception.ValueError("Need odd positive number")); [[(i,j); n; n; '{ n*((i+j+1+n/2):rmod(_,n)) + ((i+2*j-5):rmod(_,n)) + 1 }]]
}
T(3, 5, 9).pump(Void,fcn(n){
"\nSize %d, magic sum %d".fmt(n,(n*n+1)/2*n).println(); fmt := "%%%dd".fmt((n*n).toString().len() + 1) * n; odd_magic_square(n).pump(Console.println,T(T,Void.Read,n-1),fmt.fmt);
});</lang>
- Output:
Size 3, magic sum 15 8 1 6 3 5 7 4 9 2 Size 5, magic sum 65 16 23 5 7 14 22 4 6 13 20 3 10 12 19 21 9 11 18 25 2 15 17 24 1 8 Size 9, magic sum 369 50 61 72 74 4 15 26 28 39 60 71 73 3 14 25 36 38 49 70 81 2 13 24 35 37 48 59 80 1 12 23 34 45 47 58 69 9 11 22 33 44 46 57 68 79 10 21 32 43 54 56 67 78 8 20 31 42 53 55 66 77 7 18 30 41 52 63 65 76 6 17 19 40 51 62 64 75 5 16 27 29