check if it's a magic square with python

Input consists of several cases, each with the order n of a square, followed by n rows, each with n natural numbers between 1 and n². Like:

3
6 1 8
7 5 3
2 9 4

1
1
(...)

extra conditions:

should print ("yes") if its a magic square and ("no") if don't

so my code solves all correct inputs except the ones that have some number repeated, and I don't know how to solve that problem

my code

a = read(int)
while a is not None:
    check1 = True
    t = 0 
    s = 0
    listaA = [] 
    ## create matrix of lists like A([b[],b[],b[]])
    for j in range(a):
        b = []
        for k in range(a):
            c = read(int)
            if c in listaB:
                (a-1) - k
            listaB.append(c)
            b.append(c)
        listaA.append(b)
    if a == 1:
        check1 = False
        print("yes")
    else:
        x = sum(listaA[0])
    i=0
    while i<a and check1 == True:
    #for i in range(a):
        # suma la primera fila 
        suma=sum(listaA[i])
        if x != suma:
            print('no')
            break
        ## check columns 
        y = 0
        for j in range(a):
            y += listaA[j][i]
        if y != x:
            print('no')
            break
        i+=1
    ## check diagonals
    if i==a: 
        for i in range(a):
            t += (listaA[i][i])
            s += listaA[i][(a-1)-i]
        if s != x or t != x:
            print('no')

        else:
            print('yes')
    a = read(int)

some idea ???

Upvotes: 1

Views: 3482

Answers (1)

blhsing
blhsing

Reputation: 106455

You can use a set comparison to check if all the numbers between 1 and n² appear once, and use sum with generator expressions like this to test if all rows, columns and the two major diagonals sum the same:

def is_magic(m):
    n = len(m)
    s = (n ** 2 + 1) * n // 2
    return (
        set(range(1, n ** 2 + 1)) == set(i for r in m for i in r) and
        all(sum(r) == s for r in (*m, *zip(*m))) and
        sum(m[i][i] for i in range(n)) == sum(m[i][-i - 1] for i in range(n)) == s
    )

so that:

is_magic(
    [
        [6, 1, 8],
        [7, 5, 3],
        [2, 9, 4]
    ]
)

returns:

True

Upvotes: 2

Related Questions