Summing Matrices

Solving a mathematical problem

As long as I can remember, I've always liked numbers. The ways they behave and relate has always captured my interest. While I was in college, there were always fun mathematical problems to solve running around the corridors and I was one, amongst a bunch of people, who got entertained by trying to solve them. At some point, this simple problem showed up:

Fill a 3 by 3 square with the numbers from 1 to 9 so that the sum of the numbers on each row, column and both diagonals are the same.

After a little trial and error, the solution is easy to achieve:

4 9 2
3 5 7
8 1 6

And the sum of the numbers on each row, column and both diagonals is 15.

And, as usual, solving just the problem at hand isn't enough. I embarked in the task of trying to solve the same problem for a 5 by 5 square. After a little bit more trial and error than the first time, the solution presented itself:

11 24 7 20 3
4 12 25 8 16
17 5 13 21 9
10 18 1 14 22
23 6 19 2 15

Where the sum of the numbers on each row, column and both diagonals is 65.

At this point, I thought it must be likely that all odd-sided squares have a similar solution and, consequently, there must be a generic way to solve this problem for all. Following that conviction, I started looking for patterns and some stand out to the "naked eye", more or less rotations of the solution.

4 9 2
3 5 7
8 1 6
11 24 7 20 3
4 12 25 8 16
17 5 13 21 9
10 18 1 14 22
23 6 19 2 15

Having this starting point, I took the task of solving the 7 by 7 square.

22 47 16 41 10 35 4
5 23 48 17 42 11 29
30 6 24 49 18 36 12
13 31 7 25 43 19 37
38 14 32 1 26 44 20
21 39 8 33 2 27 45
46 15 40 9 34 3 28

Where the sum of the numbers on each row, column and both diagonals is 175.

Some more scrutiny and some more patterns became evident, like the sequences of numbers in diagonals parallel to the middle top-left to bottom-right diagonal:

22 47 16 41 10 35 4
5 23 48 17 42 11 29
30 6 24 49 18 36 12
13 31 7 25 43 19 37
38 14 32 1 26 44 20
21 39 8 33 2 27 45
46 15 40 9 34 3 28

Or the gap of the size of the side, in this case 7, on the diagonals of the opposite direction:

22 47 16 41 10 35 4
5 23 48 17 42 11 29
30 6 24 49 18 36 12
13 31 7 25 43 19 37
38 14 32 1 26 44 20
21 39 8 33 2 27 45
46 15 40 9 34 3 28

These got me trying out things like continuing these sequences outside the square itself and, eventually, I got here:

1
8 2
15 9 3
22 47 16 41 10 35 4
29 5 23 48 17 42 11 29 5
36 30 6 24 49 18 36 12 6
43 37 13 31 7 25 43 19 37 13 7
44 38 14 32 1 26 44 20 14
45 21 39 8 33 2 27 45 21
46 15 40 9 34 3 28
47 41 35
48 42
49

And, removing the clutter:

1
8 2
15 9 3
22 16 10 4
29 23 17 11 5
36 30 24 18 12 6
43 37 31 25 19 13 7
44 38 32 26 20 14
45 39 33 27 21
46 40 34 28
47 41 35
48 42
49

It doesn't take long from here to realize the numbers outside the square go into it moving the side value, in this case 7, into it:

1
8 2
15 9 3
22 16 10 4
29 23 17 11 5
36 30 24 18 12 6
43 37 31 25 43 19 13 7
44 38 32 1 26 20 14
45 21 39 33 27 21
46 40 34 28
47 41 35
48 42
49

And that's all there is to it.

I think, the largest side value I tested on paper, in my college days, was 19. Mostly, because it's not easy to find squared paper with such a big matrix. But I'm pretty confident this method works for every odd-sided square.

As a computer program

Since then, I've started working as a software developer and I always had the goal of, one day, implementing this method as a computer program. And, as I like to explore various programming languages, I try to code this give the language a go. The code lives here. Or in each language:

The purpose is to follow the same approach, e.g., same components, on every language but respecting the "normal" usage of each language and its features. The program consists of the following files that represent separate modules (or packages), and their contents:

> .xx is a placeholder for the file extension

> casing might change, according to language customs