I've got magic!

Out of the 362880 362880 ways of arranging the numbers

1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 1,2,3,4,5,6,7,8,9

in a 3 × 3 3 \times 3 matrix, how many configurations are there such that all lines (rows, columns and diagonals) add up to the same sum?


The answer is 8.

This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try refreshing the page, (b) enabling javascript if it is disabled on your browser and, finally, (c) loading the non-javascript version of this page . We're sorry about the hassle.

6 solutions

Brock Brown
Jul 22, 2015

There are 8 \boxed{8} different valid arrangements:

276 294 438 492 618 672 816 834 276\hspace{5mm}294\hspace{5mm}438\hspace{5mm}492\hspace{5mm}618\hspace{5mm}672\hspace{5mm}816\hspace{5mm}834 951 753 951 357 753 159 357 159 951\hspace{5mm}753\hspace{5mm}951\hspace{5mm}357\hspace{5mm}753\hspace{5mm}159\hspace{5mm}357\hspace{5mm}159 438 618 276 816 294 834 492 672 438\hspace{5mm}618\hspace{5mm}276\hspace{5mm}816\hspace{5mm}294\hspace{5mm}834\hspace{5mm}492\hspace{5mm}672

Python 3.3:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from itertools import permutations as combos
digits = range(1,10)
def goal(numbers):
    return row_sums_same(numbers) and\
        column_sums_same(numbers) and\
        diagonal_sums_same(numbers)
def row_sums_same(numbers):
    row_1 = sum(numbers[i] for i in range(3))
    row_2 = sum(numbers[i] for i in range(3, 6))
    row_3 = sum(numbers[i] for i in range(6, 9))
    return row_1 == row_2 and\
        row_2 == row_3
def column_sums_same(numbers):
    column_1 = sum(numbers[i] for i in range(0, 9, 3))
    column_2 = sum(numbers[i] for i in range(1, 9, 3))
    column_3 = sum(numbers[i] for i in range(2, 9, 3))
    return column_1 == column_2 and\
        column_2 == column_3
def diagonal_sums_same(numbers):
    diagonal_1 = numbers[0] + numbers[4] + numbers[8]
    diagonal_2 = numbers[2] + numbers[4] + numbers[6]
    return diagonal_1 == diagonal_2
def print_grid(numbers):
    print (''.join(str(numbers[i]) for i in range(3)))
    print (''.join(str(numbers[i]) for i in range(3,6)))
    print (''.join(str(numbers[i]) for i in range(6,9))+'\n')
count = 0
for grid in combos(digits):
    if goal(grid):
        count += 1
        print_grid(grid)
print ("Answer:", count)

Hasmik Garyaka
Jan 12, 2017

There is only 1 magic square and we can turn it on 90 degrees and reflect each by horizontal axe. So we get 8 different configuration with the same numbers.

It would help if you described what a magic square is in your answer

Joshua Daniel - 3 years, 5 months ago

Daniel,

https://en.wikipedia.org/wiki/Magic_square

김 재형 - 3 years, 2 months ago
A S
Oct 4, 2019

If all rows, columns, and diagonals add up to the same sum, that means the total sum of the 3x3 matrix must be divided equally among the rows, columns, and diagonals. Since the total sum of the matrix is always 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 45, each row, column, and diagonal must have a sum of 45 / 3 = 15.

There are a fixed number of ways for each number from 1 to 9 to contribute towards a total of 15 when added with two other numbers.

  • 1 can contribute in two ways: 1 + 5 + 9 and 1 + 6 + 8
  • 2 can contribute in three ways: 2 + 4 + 9, 2 + 5 + 8, and 2 + 6 + 7
  • 3 can contribute in two ways: 3 + 4 + 8 and 3 + 5 + 7
  • 4 can contribute in three ways: 4 + 5 + 6, 4 + 8 + 3, and 4 + 9 + 2
  • 5 can contribute in four ways: 5 + 6 + 4, 5 + 7 + 3, 5 + 8 + 2, and 5 + 9 + 1
  • 6 can contribute in three ways: 6 + 7 + 2, 6 + 8 + 1, and 6 + 4 + 5
  • 7 can contribute in two ways: 7 + 2 + 6 and 7 + 3 + 5
  • 8 can contribute in three ways: 8 + 1 + 6, 8 + 2 + 5, and 8 + 3 + 4
  • 9 can contribute in two ways: 9 + 1 + 5 and 9 + 2 + 4

We see that 5 can contribute towards the sum in four different ways. Hence, it must always be strategically placed at the center because this is the only way the middle row, the middle column, and the two diagonals can add up to 15. The reason why 5 is placed in the center is that the center is part of the two diagonals, the middle row, and the middle column. As seen above, 5 can be added up to 15 in FOUR unique ways, so each sum together will cover these FOUR paths along the two diagonals, the middle row, and the middle column.

We see that 2, 4, 6, and 8 can contribute towards the sum in three different ways. Hence, these numbers must always be strategically placed at one of the four corners so that one row, one column, and one diagonal can add up to 15. The reason why 2, 4, 6, and 8 are placed at the corners is that the corners are part of one diagonal, one row, and one column. As seen above, 2, 4, 6, and 8 can be added up to 15 in THREE unique ways, so each sum together will cover these THREE paths along the diagonal, the row, and the column.

Finally, we see that 1, 3, 7, and 9 can contribute towards the sum in two different ways. Hence, these numbers must always be strategically placed on the edges i.e. the four remaining slots other than the corners and the center so that one row and one column can add up to 15. The reason why 1, 3, 7, and 9 are placed on the edges is that the edges are part of one row and one column. As seen above, 1, 3, 7, and 9 can be added up to 15 in TWO unique ways, so each sum together will cover these TWO paths along the row and the column.

Now that we have the setup, counting the number of configurations should be relatively simple.

  • 5 will always have to go to the center so there is only one way this can be done.

  • If we fix 2, 4, 6, or 8 to one of the corners, this automatically implies that the corner directly opposite is also fixed. For eg: if we pick 2 to go on one of the corners, the corner directly opposite to 2 will require an 8 so that the diagonal has 2 + 5 + 8 = 15.

  • There are four corners where 2 can be placed, which automatically means 8 must go to the corner opposite of wherever 2 is placed. For each of these four scenarios, this leaves us with two possible corners where we can place 4 or 6. Placing either one in either corner will automatically seal the placement of another in the opposite corner so that diagonal has 4 + 5 + 6 = 15.

  • Placing 5 in the center and 2, 4, 6, and 8 in the corners automatically means that the fate of the rest of the numbers - 1, 3, 7, and 9, is sealed already because they can only occupy a single position that will make the rows and columns sum to 15.


To summarize, if we proceed step-by-step in the most optimal manner,

  • There is always ONE corner to place the 5.
  • There are FOUR corners to place EITHER 2 and 8 OR 4 and 6, always directly across from each other so that they line up in a diagonal with 5.
  • There are TWO corners to place EITHER 2 and 8 OR 4 and 6, always directly across from each other so that they line up in a diagonal with 5.
  • At this point, the configuration is already complete as each of the remaining numbers have exactly ONE position they can occupy.

Therefore, the total number of configurations = 1 × 4 × 2 × 1 = 8 1 \times 4 \times 2 \times 1 = 8

Andreas Kleven
Aug 5, 2018
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from itertools import permutations
perms = permutations([1,2,3,4,5,6,7,8,9])
count = 0
for p in perms:
    """Rows"""
    sum = p[0] + p[1] + p[2]
    if p[3] + p[4] + p[5] != sum:
        continue
    if p[6] + p[7] + p[8] != sum:
        continue
    """Columns"""
    if p[0] + p[3] + p[6] != sum:
        continue
    if p[1] + p[4] + p[7] != sum:
        continue
    if p[2] + p[5] + p[8] != sum:
        continue
    """Diagonals"""
    if p[0] + p[4] + p[8] != sum:
        continue
    if p[2] + p[4] + p[6] != sum:
        continue
    count += 1
    print(p[:3])
    print(p[3:6])
    print(p[-3:])
    print("")
print("Done:", count) 

Derrick Sonnier
Oct 30, 2016

Given the computationally small space and algorithm's next permutation function, this is near-trivial in C++: #include <iostream> #include <algorithm> using namespace std; bool ismagicsquare(int []); int main () { int myints[] = {1,2,3,4,5,6,7,8,9}; int count = 0; do { if(ismagicsquare(myints)) count++; } while (next permutation(myints,myints+9) );

    cout << count << endl;
    return 0;
}

bool ismagicsquare(int list[]) {
    int sum = list[0] + list[1] + list[2];
    if(sum == (list[3] + list[4] + list[5]) && sum == (list[6] + list[7] + list[8]) && 
       sum == (list[0] + list[3] + list[6]) && sum == (list[1] + list[4] + list[7]) && sum == (list[2] + list[5] + list[8]) && 
       sum == (list[0] + list[4] + list[8]) && sum == (list[2] + list[4] + list[6]))
        return true;
    return false;            
}
Mark C
Apr 30, 2016

Doing permutations ourselves:

import copy

def SeekOrderings(ListSoFar,ItemsRemaining):
    for d in ItemsRemaining:
        NewList = copy.deepcopy(ListSoFar)
        NewList += [d]
        NewRemaining = copy.deepcopy(ItemsRemaining)
        NewRemaining.remove(d)
        if NewRemaining == []:
            Process(NewList)
        else:
            SeekOrderings(NewList,NewRemaining)

def Process(d):
    global ways
    success = 1
    for i in [0,1,2]:
        if not((d[i]+d[i+3]+d[i+6]==15) 
                and (d[3*i]+d[3*i+1]+d[3*i+2]==15)):
            success = 0
    if not ((d[0]+d[4]+d[8]==15) 
            and (d[2]+d[4]+d[6]==15)):
        success = 0
    ways += success

ways = 0
SeekOrderings([],[1,2,3,4,5,6,7,8,9])
print (ways)

0 pending reports

×

Problem Loading...

Note Loading...

Set Loading...