In 1976 I took a programming class. As my major programming project, I undertook the writing of a program to generate magic squares. In researching algorithms and in writing code for this project, I became somewhat frustrated, as I could find no straightforward way of creating some types of magic squares. This web page details my solution to the problem.
Definition of
a magic square:
Although there
are other types of squares called "magic", this program deals with the
"standard" definition as follows.
Magic squares
are arrays of numbers where the rows, columns and the diagonals add up
to the same number, (called the square's constant). Also, no number
is repeated. For example, a 3 by 3 square consists of all the numbers
from 1 to 15. This is one such square of size 3.
| 8 | 3 | 4 |
| 1 | 5 | 9 |
| 6 | 7 | 2 |
in this case, the rows add to 15
8+3+4=15
1+5+9=15
6+7+2=15
the columns add to 15
8+1+6=15
3+5+7=15
4+9+2=15
and the diagonals add to 15
8+5+2=15
6+5+4=15
There are 3 basic
types of squares.
"Odd", where
the number of rows and columns is an odd number (3,5,7,9,11 etc.)
"Double Even",
where the number of rows and columns is an even number
divisible by
4. (4,8,12,16,20 etc.)
"Single Even",
where the number of rows and columns is an even number
not divisible
by 4. (6,10,14,18,22 etc.)
1976 This program was originally written in a FORTRAN dialect called WATFIV, which is a structured programming version of FORTRAN. It was written as a quarter project for a computer science class at Iowa State University. At that time it was quite a bit less efficient and did not include this method for odd size squares, which I worked out later. The main point of the project was to write a program that could generate magic squares of all sizes, but my research failed to uncover a workable algorith for "Single Even" sizes. In testing different methods of making Double Even squares more easily, I developed a method for doing Single Even squares also. These methods may seem less straight-forward than some you may have seen, but when programming a computer, these methods lend themselves quite readily to array manipulation. The original program was written on punch cards and, due to student memory allocation constraints, could build a maximum square of 31 by 31 cells, using 2 byte integer math. Recently, I used an IBM 2003-215 mainframe to build a square of size 3002 by 3002. (several hours of processing time).
1985 I re-wrote in Apple Basic with performance improvements and a better method for doing "Odd" size squares.
1986 Re-written in REXX to run on an IBM mainframe computer. Size constraining code removed to allow attempt at any size square. (previously limited to small squares by the available computing power).
2000 Modified to run in a PC environment using Regina Rexx.
The program is
called "Magic.Rex".
The extension
"REX" needs to be associated with the program "REGINA.EXE" which is the
interpreter portion of the Regina Rexx package.
Click on the link
below see or save the source version of the program.
(Do a "file"
"save-as" and save to your desktop as "MAGIC.REX".
Download Bob Levad's magic squares program
As this program
is written in REXX. It is necessary to run it in the
REXX environment.
This is a quite powerful language that can also be
fairly easy to
learn. To obtain a freeware version of REXX (under 1 meg) that will
allow
this program
to run on a PC, download it from:
Mark Hessling's REXX download page
After extracting
the zip file, Open "magic.rex" with "regina.exe" and it will prompt
for the size
of square to build. If you click "always use this program", you will
be able to just double-click "magic.rex" to run it.
Historical references
The method shown here uses variations on techniques documented by Philippe de la Hire (1640-1718). The following links are to two biographical pieces.
The MacTutor History of Mathematics
Details of my magic square algorith
The details listed here follow closely with the attached program. Which shows more of the calculations involved in the matrix manipulations.
First we must
get the SIZE for the square.
Then we check
to see if a valid number was entered.
Once we have
the size, we set up the arrays and calculate the square's constant.
Size = (Number
of Rows or columns in the magic square)
Constant = (total
of the cells in each row, column and diagonal)
The constant
can be calculated by the formula: constant = (size * ((size * size) + 1))
/ 2
e.g. for size
= 3: constant = 15 = (3*((3*3)+1))/2.
We then initialize
the variables we will use in the program and set up our destination files.
Next we decide
what type of square we will be building.
(based on whether
the Size of the square is odd or even
and whether the
Size of the square is divisible by 4).
When the square
is of type "ODD" we fill our base square as follows:
Start in the
top left cell with the integer that is (size/2) rounded up.
Going right,
increment by 1 for each cell until you reach the value of "size" (7 in
this case). Drop back to one and continue till row 1 is filled. (4,5,6,7,1,2,3)
The next row
starts with the number 1 less than the last and is filled in the same manner.
(3,4,5,6,7,1,2).
Each row in turn
starts with the number 1 smaller than the one above, until, after the row
starting with "1", start with the number "size" (7 in this case).
(7,1,2,3,4,5,6)
Continue as before
until the square is filled.
This is how a
square of size "7" is filled.
| 4 | 5 | 6 | 7 | 1 | 2 | 3 |
| 3 | 4 | 5 | 6 | 7 | 1 | 2 |
| 2 | 3 | 4 | 5 | 6 | 7 | 1 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 7 | 1 | 2 | 3 | 4 | 5 | 6 |
| 6 | 7 | 1 | 2 | 3 | 4 | 5 |
| 5 | 6 | 7 | 1 | 2 | 3 | 4 |
When the square
is of type "Double" we can divide "SIZE" by 4.
This base square
is the easiest to fill. Also it was the key to figuring out how to
do a single even square. The book I had showed filling the base square
diagonals with the numbers from 1 to "size" and then filling in the remaining
cells with the numbers not used. I reasoned that the object was to get
all the different numbers on the diagonals, and that naturally followed
if you just filled the square in an alternating fashion and mirrored the
top half to the bottom half.
This is how the
base square of size "8" is initially filled.
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
When the square
is of type "Single" we can divide "SIZE" by 2 but not 4.
I first tried
the same method as for double even, my results were close, but not quite
magic. I then played with the method till I found the permutations
necessary to produce the desired results.
This is how a
square of size "6" is initially filled. Note that the duplicate row
is below center as opposed to on center for the double even.
| 1 | 2 | 3 | 4 | 5 | 6 |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | 3 | 4 | 5 | 6 |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | 3 | 4 | 5 | 6 |
We then swap the
cell values at ends of row 2. This is the resulting square.
| 1 | 2 | 3 | 4 | 5 | 6 |
| "1" | 5 | 4 | 3 | 2 | "6" |
| 1 | 2 | 3 | 4 | 5 | 6 |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | 3 | 4 | 5 | 6 |
Then we swap cells
at ends of the row just above the center of our square.
| 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 5 | 4 | 3 | 2 | 6 |
| "6" | 2 | 3 | 4 | 5 | "1" |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | 3 | 4 | 5 | 6 |
Next, we swap
the center cells of the row just below the center.
| 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 5 | 4 | 3 | 2 | 6 |
| 6 | 2 | 3 | 4 | 5 | 1 |
| 6 | 5 | "3" | "4" | 2 | 1 |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | 3 | 4 | 5 | 6 |
Last, we swap
the center cells of the bottom row.
| 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 5 | 4 | 3 | 2 | 6 |
| 6 | 2 | 3 | 4 | 5 | 1 |
| 6 | 5 | 3 | 4 | 2 | 1 |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | "4" | "3" | 5 | 6 |
After this point,
the 3 methods converge. There is no difference in the following steps
for any size square. In our 6 by 6 example, We take the resulting
square :
| 1 | 2 | 3 | 4 | 5 | 6 |
| 1 | 5 | 4 | 3 | 2 | 6 |
| 6 | 2 | 3 | 4 | 5 | 1 |
| 6 | 5 | 3 | 4 | 2 | 1 |
| 6 | 5 | 4 | 3 | 2 | 1 |
| 1 | 2 | 4 | 3 | 5 | 6 |
And generate
a new square with values that match the formula
(current cell
value * size ) - size
| 0 | 6 | 18 | 12 | 24 | 30 |
| 30 | 24 | 18 | 12 | 6 | 0 |
| 30 | 24 | 12 | 18 | 6 | 0 |
| 30 | 6 | 12 | 18 | 24 | 0 |
| 0 | 24 | 18 | 12 | 6 | 30 |
| 0 | 6 | 12 | 18 | 24 | 30 |
Then we transpose
the square as follows
| 0 | 30 | 30 | 30 | 0 | 0 |
| 6 | 24 | 24 | 6 | 24 | 6 |
| 18 | 18 | 12 | 12 | 18 | 12 |
| 12 | 12 | 18 | 18 | 12 | 18 |
| 24 | 6 | 6 | 24 | 6 | 24 |
| 30 | 0 | 0 | 0 | 30 | 30 |
Then add the base
square values to the corresponding transposed square values
which results
in a magic square.
(0+1=1)(2+30=32)(3+30=33)(4+30=34)(5+0=5)(6+0=6)
etc.
| 1 | 32 | 33 | 34 | 5 | 6 |
| 7 | 29 | 28 | 9 | 26 | 12 |
| 24 | 20 | 15 | 16 | 23 | 13 |
| 18 | 17 | 21 | 22 | 14 | 19 |
| 30 | 11 | 10 | 27 | 8 | 25 |
| 31 | 2 | 4 | 3 | 35 | 36 |
At this point,
we run through a series of tests to verify that what has been
created is really
a magic square. We test that each row and column and
the two diagonals
add up to the constant for the square and that each number
is used only
once.
E-mail address: blevad@wctatel.net
Copyright 1976-2000 by Robert Levad