Problem
Write a method to return a boolean if an input grid is magic square.
A magic square is a \$NxN\$ square grid (where N is the number of cells on each side) filled with distinct positive integers in the range \${1,2,...,n^{2}}\$ such that each cell contains a different integer and the sum of the integers in each row, column and diagonal is equal. The sum is called the magic constant or magic sum of the magic square.
Code
I've tried to solve the above problem. If you'd like to review the code and provide any change/improvement recommendations please do so, and I'd really appreciate that.
from typing import List
import numpy as np
def is_magic_square(grid: List[List[int]]) -> bool:
"""Returns a boolean if an input grid is magic square"""
try:
grid_length = len(grid)
magic_sum = float(grid_length * (grid_length ** 2 + 1) / 2)
diag_positive, diag_negative = [], []
diag_count_positive = 0
diag_count_negative = grid_length - 1
col_grid = np.zeros(shape=(grid_length, grid_length))
unique_elements = set()
for index_row, lists in enumerate(grid):
diag_negative.append(lists[diag_count_negative])
diag_count_negative -= 1
if len(grid[index_row]) != grid_length:
return False
if sum(lists) != magic_sum:
return False
for index_col in range(grid_length):
unique_elements.add(lists[index_col])
col_grid[index_col][index_row] = lists[index_col]
if index_col == grid_length and index_row == grid_length - 1 and len(unique_elements) != grid_length ** 2 - 1:
return False
if index_row == grid_length - 1:
sum_col = sum(col_grid)
temp_col = np.array([magic_sum] * grid_length)
if str(temp_col) != str(sum_col):
return False
if diag_count_positive == index_row:
diag_positive.append(lists[index_row])
diag_count_positive += 1
if diag_count_positive == grid_length and sum(diag_positive) != magic_sum:
return False
if index_row == grid_length - 1 and sum(diag_negative) != magic_sum:
return False
except:
return False
return True
if __name__ == '__main__':
# ---------------------------- TEST ---------------------------
DIVIDER_DASH_LINE = '-' * 50
GREEN_APPLE = '\U0001F34F'
RED_APPLE = '\U0001F34E'
magic_squares = [
[[4, 3, 8],
[9, 5, 1],
[2, 7, 6]],
[[9, 3, 22, 16, 15],
[2, 21, 20, 14, 8],
[25, 19, 13, 7, 1],
[18, 12, 6, 5, 24],
[11, 10, 4, 23, 17]],
[[60, 53, 44, 37, 4, 13, 20, 29],
[3, 14, 19, 30, 59, 54, 43, 38],
[58, 55, 42, 39, 2, 15, 18, 31],
[1, 16, 17, 32, 57, 56, 41, 40],
[61, 52, 45, 36, 5, 12, 21, 28],
[6, 11, 22, 27, 62, 51, 46, 35],
[63, 50, 47, 34, 7, 10, 23, 26],
[8, 9, 24, 25, 64, 49, 48, 33]],
[[35, 26, 17, 1, 62, 53, 44],
[46, 37, 21, 12, 3, 64, 55],
[57, 41, 32, 23, 14, 5, 66],
[61, 52, 43, 34, 25, 16, 7],
[2, 63, 54, 45, 36, 27, 11],
[13, 4, 65, 56, 47, 31, 22],
[24, 15, 6, 67, 51, 42, 33]],
[[1, 35, 4, 33, 32, 6],
[25, 11, 9, 28, 8, 30],
[24, 14, 18, 16, 17, 22],
[13, 23, 19, 21, 20, 15],
[12, 26, 27, 10, 29, 7],
[36, 2, 34, 3, 5, 31]],
[[16, 14, 7, 30, 23],
[24, 17, 10, 8, 31],
[32, 25, 18, 11, 4],
[5, 28, 26, 19, 12],
[13, 6, 29, 22, 20]],
[[1, 14, 4, 15],
[8, 11, 5, 10],
[13, 2, 16, 3],
[12, 7, 9, 6]],
[[8, 1, 6],
[3, 5, 7],
[4, 9, 2]]
]
for magic_square in magic_squares:
print(DIVIDER_DASH_LINE)
if is_magic_square(magic_square) is True:
print(f'{GREEN_APPLE} "{magic_square}" is a magic square.')
else:
print(f'{RED_APPLE} "{magic_square}" is not a magic square.')
Output
--------------------------------------------------
🍏 "[[4, 3, 8], [9, 5, 1], [2, 7, 6]]" is a magic square.
--------------------------------------------------
🍏 "[[9, 3, 22, 16, 15], [2, 21, 20, 14, 8], [25, 19, 13, 7, 1], [18, 12, 6, 5, 24], [11, 10, 4, 23, 17]]" is a magic square.
--------------------------------------------------
🍏 "[[60, 53, 44, 37, 4, 13, 20, 29], [3, 14, 19, 30, 59, 54, 43, 38], [58, 55, 42, 39, 2, 15, 18, 31], [1, 16, 17, 32, 57, 56, 41, 40], [61, 52, 45, 36, 5, 12, 21, 28], [6, 11, 22, 27, 62, 51, 46, 35], [63, 50, 47, 34, 7, 10, 23, 26], [8, 9, 24, 25, 64, 49, 48, 33]]" is a magic square.
--------------------------------------------------
🍎 "[[35, 26, 17, 1, 62, 53, 44], [46, 37, 21, 12, 3, 64, 55], [57, 41, 32, 23, 14, 5, 66], [61, 52, 43, 34, 25, 16, 7], [2, 63, 54, 45, 36, 27, 11], [13, 4, 65, 56, 47, 31, 22], [24, 15, 6, 67, 51, 42, 33]]" is not a magic square.
--------------------------------------------------
🍏 "[[1, 35, 4, 33, 32, 6], [25, 11, 9, 28, 8, 30], [24, 14, 18, 16, 17, 22], [13, 23, 19, 21, 20, 15], [12, 26, 27, 10, 29, 7], [36, 2, 34, 3, 5, 31]]" is a magic square.
--------------------------------------------------
🍎 "[[16, 14, 7, 30, 23], [24, 17, 10, 8, 31], [32, 25, 18, 11, 4], [5, 28, 26, 19, 12], [13, 6, 29, 22, 20]]" is not a magic square.
--------------------------------------------------
🍏 "[[1, 14, 4, 15], [8, 11, 5, 10], [13, 2, 16, 3], [12, 7, 9, 6]]" is a magic square.
--------------------------------------------------
🍏 "[[8, 1, 6], [3, 5, 7], [4, 9, 2]]" is a magic square.