Creating a Magic Square Using Python

Creating a Magic Square Using Python

ECX 30 Days of Code and Design

Day 15

Magic Square

Task

A magic square is a 3 by 3 grid (could be 4 by 4 or more), such that:

  1. It consists of unique numbers (i.e., no two same numbers appear in the square)
  2. The sum of each row, column, and diagonal all add up to the same number

Write a function that accepts a two-dimensional list as input and determine whether the list is a Magic Square or not. Test the function in a program.

My Approach

This is the full code. I will explain it throughout of this article.

# Dictionary for the board
board = {1: ' ', 2: ' ', 3: ' ',
         4: ' ', 5: ' ', 6: ' ',
         7: ' ', 8: ' ', 9: ' '}

board_items = [[2, 7, 6], [9, 5, 1], [4, 3, 8]]         # This forms a magic square
board_items_1 = [[1, 5, 9], [6, 7, 2], [8, 3, 4]]       # This forms a semi magic square
# A semi magic square has it columns and rows having the same sum, but the diagonal having a different sum


# Function to arrange the board
def magic_square_board(boards):
    """This prints out the board."""

    print('-------')
    print('|' + boards[1] + '|' + boards[2] + '|' + boards[3] + '|')
    print('-------')
    print('|' + boards[4] + '|' + boards[5] + '|' + boards[6] + '|')
    print('-------')
    print('|' + boards[7] + '|' + boards[8] + '|' + boards[9] + '|')
    print('-------')


# Function to fill the board and check if the numbers form a magic square
def magic_square(boards_items, boards):
    """This checks for if a magic number is formed from a list containing integers"""

    counts = 1                      # Used to enter board items
    total_row_sum = []              # Used to ums the rows of the board

    # Entering list items into the board and calculating the sum of rows
    for nested_lists in boards_items:
        total = 0
        for list_items in nested_lists:

            boards[counts] = str(list_items)

            total = total + list_items

            counts = counts + 1

        # Summation of rows
        total_row_sum.append(total)

    # Print the updated board
    magic_square_board(boards)

    # Summation of columns
    first_col = int(boards[1]) + int(boards[4]) + int(boards[7])
    second_col = int(boards[2]) + int(boards[5]) + int(boards[8])
    third_col = int(boards[3]) + int(boards[6]) + int(boards[9])

    # Summation of diagonals
    back_slash_diagonal = int(boards[1]) + int(boards[5]) + int(boards[9])
    forward_slash_diagonal = int(boards[3]) + int(boards[5]) + int(boards[7])

    # Check if sum of individual rows have the same value
    if total_row_sum[0] == total_row_sum[1] == total_row_sum[2]:
        all_row = total_row_sum[1]
    else:
        all_row = -1

    # Check if the sum of individual columns has the same value
    if first_col == second_col == third_col:
        all_col = first_col
    else:
        all_col = -2

    # Check if the sum of individual rows has the same value
    if forward_slash_diagonal == back_slash_diagonal:
        all_diagonals = forward_slash_diagonal
    else:
        all_diagonals = -3

    # Final check if summation of individual rows, columns, and diagonal have the same value
    if all_row == all_col == all_diagonals:
        print('The numbers form a magic square\n')
    else:
        print('The numbers do not form a magic square\n')


# Function call
magic_square(board_items, board)
magic_square(board_items_1, board)

First, we create a dictionary, board, for the magic square board which we would use to fill in the list items. Next, we create a nested list which we would use to fill the board. One of the lists forms a magic square, while the other does not.

board = {1: ' ', 2: ' ', 3: ' ',
         4: ' ', 5: ' ', 6: ' ',
         7: ' ', 8: ' ', 9: ' '}

board_items = [[2, 7, 6], [9, 5, 1], [4, 3, 8]]        
board_items_1 = [[1, 5, 9], [6, 7, 2], [8, 3, 4]]

Next, we define a function, magic_square_board(), which we will use to order and print out the board.

def magic_square_board(boards):
    """This prints out the board."""

    print('-------')
    print('|' + boards[1] + '|' + boards[2] + '|' + boards[3] + '|')
    print('-------')
    print('|' + boards[4] + '|' + boards[5] + '|' + boards[6] + '|')
    print('-------')
    print('|' + boards[7] + '|' + boards[8] + '|' + boards[9] + '|')
    print('-------')
-------
| | | |
-------
| | | |
-------
| | | |
-------
Empty board

We would create another function, magic_square(), which we would use to fill the board with the list items and check if a magic number exists. We create a counter, counter, which we would use for the keys of the dictionary for inputting the values of the nested list. We would also create an empty list in which we would store the sum of each row as we input the values in the board.

def magic_square(boards_items, boards):
    """This checks for if a magic number is formed from a list containing integers"""

    counts = 1            
    total_row_sum = []

Next, we input the values from the nested lists into the board. for nested_lists in boards_items implies for each list in the nested list. Next, we have ‘for each item in individual lists’ which we will use to input the items into the dictionary. Because we are entering the values per row, we are able to sum individual rows which will be saved in the row_sum list we initially created.

for nested_lists in boards_items:
    total = 0
    for list_items in nested_lists:

        boards[counts] = str(list_items)

        total = total + list_items

        counts = counts + 1

    total_row_sum.append(total)

Next, we get the sum of the individual columns and diagonals which we store in a variable.

    first_col = int(boards[1]) + int(boards[4]) + int(boards[7])
    second_col = int(boards[2]) + int(boards[5]) + int(boards[8])
    third_col = int(boards[3]) + int(boards[6]) + int(boards[9])

    back_slash_diagonal = int(boards[1]) + int(boards[5]) + int(boards[9])
    forward_slash_diagonal = int(boards[3]) + int(boards[5]) + int(boards[7])

We then check if all rows are equal, if all columns are equal, and if all diagonal are equal before we check if they are all equal. If they are all equal, we print ‘The numbers form a magic square’, else ‘The numbers do not form a magic square.’

    if total_row_sum[0] == total_row_sum[1] == total_row_sum[2]:
        all_row = total_row_sum[1]
    else:
        all_row = -1

    if first_col == second_col == third_col:
        all_col = first_col
    else:
        all_col = -2

    if forward_slash_diagonal == back_slash_diagonal:
        all_diagonals = forward_slash_diagonal
    else:
        all_diagonals = -3

    if all_row == all_col == all_diagonals:
        print('The numbers form a magic square\n')
    else:
        print('The numbers do not form a magic square\n')

Finally, we call the functions with the lists passed in as arguments

magic_square(board_items, board)
magic_square(board_items_1, board)

Output

-------
|2|7|6|
-------
|9|5|1|
-------
|4|3|8|
-------
The numbers form a magic square

-------
|1|5|9|
-------
|6|7|2|
-------
|8|3|4|
-------
The numbers do not form a magic square

Run code on Replit