Calculating a magic square

Asked

Viewed 2,733 times

5

I’m trying to make a magic square:

  • A magic square is one divided into rows and columns, with a number in each position and in which the sum of the rows, columns and diagonals is the same.
  • Example (3x3 - 1 to 9):

    8   3   4 
    
    1   5   9 
    
    6   7   2
    

I tried using a 3x3 matrix and a vector with 9 indices.

import random
                #j(coluna)
matriz = [[1, 2, 3],#i(linha)
          [4, 5, 6],
          [7, 8, 9]]
res = False
#DEFINIR UMA FUNÇÃO PARA CALCULAR AS SOMAS DE TODOS OS LADOS
def magicsquare():
    if matriz[0][0] + matriz[1][0] + matriz[2][0] == matriz[0][1] + matriz[1][1] + matriz[2][1] == matriz[0][2] + matriz[1][2] + matriz[2][2] == matriz[0][0] + matriz[0][1] + matriz[0][2] == matriz[1][0] + matriz[1][1] + matriz[1][2] == matriz[2][0] + matriz[2][1] + matriz[2][2] == matriz[0][0] + matriz[1][1] + matriz[2][2] == matriz[0][2] + matriz[1][1] + matriz[2][0]:
        return res == True
    else:
        return res == False

#DEFINIR UM LOOP PARA GERAR Nº ALEAT. ATÉ ENCONTRAR OS QUE SATIZFAZEM
#AS CONDIÇÕES DE UM QUADRADO MÁGICO
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9]
while res == False:
    for i in range(2):
        for j in range(2):
            z = random.choice(seq)
            matriz[i][j] = z
            x = seq.index(z)
            seq[x] = []
    magicsquare()
print (matriz)
#---------------------------------------------------------------------------------------------------------------------------------------------------------------
res = False
def magicsquare():
    if vetor[0] + vetor[1] + vetor[2] == vetor[3] + vetor[4] + vetor[5] == vetor[6] + vetor[7] + vetor[8] == vetor[0] + vetor[3] + vetor[6] == vetor[1] + vetor[4] + vetor[7] == vetor[2] + vetor[5] + vetor[8] == vetor[0] + vetor[4] + vetor[8] == vetor[2] + vetor[4] + vetor[6]:
        return res == True
    else:
        return res == False
#        0  1  2  3  4  5  6  7  8
vetor = [1, 2, 3, 4, 5, 6, 7, 8, 9]
seq = [1, 2, 3, 4, 5, 6, 7, 8, 9]
if res == False:
    for i in range(8):
        w = random.choice(seq)
        #Repor o valor w(1 a 9) no index i(0 a 8). Sem usar valores e indexes repetidos
        vetor.insert(i, w)
        #Eliminar os valores já utilizados
        x = seq.index(w)
        seq[x] =[]
    magicsquare()
print (vetor)

The result is always: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Can someone help me build a magic square?

Using Python 3.5.0

  • Having this code, how does it work? How would I simulate the creation of a magic square? Also, this code has some problem?

  • Are you sure the code you are using is the same code you posted here? I tested the first part of the code above and got TypeError: unsupported operand type(s) for +: 'int' and 'list'. Besides, I see you’re never assigning the res, only by comparing it with other variables, so that while res == False: will enter an infinite loop.

1 answer

6


I will answer based on your first attempt, with matrix, because the logic is simpler

First, your logic for verifying whether or not a matrix satisfies the condition of the magic square is correct. The problem with this function is that it’s returning the inverse result, and doing it obscurely. I suggest - especially if you are a beginner in programming - avoid assigning a value and using it at the same time, as this is a potential source of errors.

Also, there is an extra detail: you expect the function magicsquare affect the variable res defined outside it. To ensure this, it is best to declare it as global, so that the function does not create a new copy of it (I don’t know exactly what the rule is, but I had this problem here).

def magicsquare():
    global res
    if matriz[0][0] + matriz[1][0] + matriz[2][0] == matriz[0][1] + matriz[1][1] + matriz[2][1] == matriz[0][2] + matriz[1][2] + matriz[2][2] == matriz[0][0] + matriz[0][1] + matriz[0][2] == matriz[1][0] + matriz[1][1] + matriz[1][2] == matriz[2][0] + matriz[2][1] + matriz[2][2] == matriz[0][0] + matriz[1][1] + matriz[2][2] == matriz[0][2] + matriz[1][1] + matriz[2][0]:
        res = True  # Primeiro atribui...
    else:
        res = False # Primeiro atribui...
    return res # ...depois usa

Second, you are trying to "erase" the values already drawn from the set seq, so that they are not drawn again. The problem is that you are doing this by simply assigning a new value to it:

seq[x] = []

This not only does not prevent it from being drawn again but also introduces a new possibility: to have [] as an element of your magic square! And the worst is this: if the first attempt is not valid, it will never hit again, because the value has been erased and has not been restored.

A correct way to do this would be to actually remove the element from the set (so that it cannot be drawn again) and - at the beginning of the new loop - restore its set to the initial state so that it can try again:

while res == False:
    seq = [1, 2, 3, 4, 5, 6, 7, 8, 9] # Dentro do while, não fora
    for i in range(3): # 3, não 2 (0,1,2)
        for j in range(3):
            z = random.choice(seq)
            matriz[i][j] = z
            x = seq.index(z)
            seq = seq[:x] + seq[x+1:] # Remove o elemento x do conjunto
    magicsquare()

Example working on ideone

Browser other questions tagged

You are not signed in. Login or sign up in order to post.