魔方蟒

时间:2017-02-05 19:37:29

标签: python magic-square

我编写了一个程序,该程序读取文件中的一行并确定该行是否为Lo Shu Magic square。在这个魔术方格中,行的总和,列的总和以及对角线的总和必须等于15,并且每个数字1-9只能在正方形中出现一次。这就是我到目前为止所做的:

def main():
    for line in open("Magic Square Input.txt"):
        items = line.split(" ")
        items = [int(x) for x in items]
        result = [items[0:3], items[3:6], items[6:9]]
        isMagic(result)

def isMagic(result):
    checks1 = ''
    for x in result:
        for y in range(3):
            if sum (result[y][y] for y in range(3)) == 15:
                if sum(x[y] for x in result) == 15:
                    checks1 = checkDupe(result)
                else:
                    checks1 = 'Invalid'
            else:
                checks1 = 'Invalid'

    print(checks1)

def checkDupe(result):
    checks1 = ''
    for i in range(0,8):
        counter = 0
        for j in result:
            if (j == i):
                counter += 1
        if counter > 0:
            checks1 = 'Invalid'
        else:
            checks1 = 'Valid'
    return checks1
main()

我的文本文件的内容如下:

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

每行中的前三个数字代表正方形的顶行,接下来的三个代表中间行,后三个代表底行。我遇到的问题是前三个方格有效,后四个方格无效。但我的代码为我打印的是

Valid
Valid
Valid
Valid
Valid
Invalid
Valid

有人能告诉我在哪里搞砸了吗?我对python很新,我一直在盯着这几个小时试图弄清楚它。

6 个答案:

答案 0 :(得分:3)

如果您从平面列表开始,这个问题就更容易思考了:

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

然后找出您需要检查的索引。总共只有八个:

indexes = (
    (0, 1, 2), (3, 4, 5), (6, 7, 8), # rows
    (0, 3, 6), (1, 4, 7), (2, 5, 8), # cols
    (0, 4, 8), (2, 4, 6),            # diag
    )

通过该设置,检查功能变得非常简单:

def main():
    for line in open('Magic Square Input.txt'):
        square = [int(n) for n in line.split()]
        if len(set(square)) != len(square):
            print('Invalid: Duplicates')
        else:
            for idx in indexes:
                if sum(square[i] for i in idx) != 15:
                    print('Invalid: Sum')
                    break
            else:
                print('Valid')

答案 1 :(得分:1)

我的版本没有将项目拆分成行

data = '''4 3 8 9 5 1 2 7 6
8 3 4 1 5 9 6 7 2
6 1 8 7 5 3 2 9 4
6 9 8 7 5 3 2 1 4
6 1 8 7 5 3 2 1 4
6 1 3 2 9 4 8 7 5
5 5 5 5 5 5 5 5 5'''

def main():
    for line in data.split("\n"):
        # create list with all numbers
        items = list(map(int, line.split()))
        print(is_magic(items))

def is_magic(items):

    # --- dups ---

    #print('dups')
    #print(len(set(items)) == 9)
    #for x in range(1, 10):
    #    print(x, x in items)
    if len(set(items)) != 9:
        return 'Invalid'

    # --- rows ---

    #print('rows')
    for x in range(0, 9, 3):
        l = items[x:x+3]
        #print(l, sum(l) == 15)
        if sum(l) != 15:
            return 'Invalid'

    # --- cols ---

    #print('cols')
    for x in range(3):
        l = [items[x], items[x+3], items[x+6]]
        #print(l, sum(l) == 15)
        if sum(l) != 15:
            return 'Invalid'

    # --- diags ---

    #print('diags')
    l = [items[0], items[4], items[8]]
    #print(l, sum(l) == 15)
    if sum(l) != 15:
        return 'Invalid'

    l = [items[2], items[4], items[6]]
    #print(l, sum(l) == 15)
    if sum(l) != 15:
        return 'Invalid'

    # --- OK ---

    return 'Valid'

main()

答案 2 :(得分:1)

我不得不做一些重大更改,但看起来你的checkDupe方法无法正常工作。您还只检查了一个对角线而不是两个。另外,请注意,使用checks1变量不是保存答案是否有效,如果出现任何错误,它只会返回'无效',这通常会使代码更清晰,并且可以简化问题。如果永远不会返回“无效”,则该方法最后会返回“有效”。

   def main():
    for line in open("Magic Square Input.txt"):
        items = line.split(" ")
        items = [int(x) for x in items]
        result = [items[0:3], items[3:6], items[6:9]]
        print isMagic(result)

def isMagic(result):
    # check duplicates
    if(checkDupe(result) == 'Invalid'):
        return 'Invalid'
    # diagonals
    if sum (result[y][y] for y in range(3)) != 15:
        return 'Invalid'
    # other digonals
    if sum (result[2 - y][2 - y] for y in range(3)) != 15:
        return 'Invalid'
    # rows and columns
    for i in range(3):
        if sum(result[i][y] for y in range(3)) != 15:
            return 'Invalid'
        if sum(result[x][i] for x in range(3)) != 15:
            return 'Invalid'
    return 'Valid'

def checkDupe(result):
    for x in range(1,9):
        if(not x in (result[0]+result[1]+result[2])):
            return 'Invalid'
        return 'Valid'
main()

答案 3 :(得分:1)

为了帮助你,我应该开始说你的代码很难阅读。由于您是Python的新手,很快您会发现Python的一个主要优点是它的语法清晰,这使得很容易弄清楚代码片段在做什么。话虽这么说,我解决你的问题,使用与你相同的逻辑,但使代码更具可读性,并使用一些Python技巧使解决方案更短,更清洁。

def main():

    """Open the file, parse the input and check if it is a magic cube"""

    with open("Magic Square Input.txt") as f:

        for line in f.readlines():

            numbers = line.split(" ")
            cube = [int(x) for x in numbers]            
            is_magic(cube)


def is_magic(cube):

    """Check if cube is magic.
    There are two conditions that must be satisfied:
    1 - There must not be any repetitions of the numbers
    2 - All vertical/horizontal/diagonal sums must be 15
    """

    if not dupe(cube) and check_sum(cube):        
        print ('Valid')

    else:        
        print ('Invalid')


def dupe(cube):

    """Check if there are repetitions in the cube."""

    if len(cube) == len(set(cube)):        
        return False
    return True



def check_sum(cube):

    """Check if all vertical/horizontal/diagonal sums are 15"""

    if vertical_check(cube) and horizontal_check(cube) and diagonal_check(cube):        
        return True


def vertical_check(cube):

    if sum(cube[0:9:3]) == sum(cube[1:9:3]) == sum(cube[2:9:3]) == 15:      
        return True    
    return False


def horizontal_check(cube):

    if sum(cube[0:3]) == sum(cube[3:6]) == sum(cube[6:9]) == 15:      
        return True    
    return False


def diagonal_check(cube):

    if sum(cube[0:9:4]) == sum(cube[2:7:2]) == 15:      
        return True    
    return False

main()

我希望您能从代码中的注释中理解解决方案。如果不是这种情况,请再次在此处发布。

答案 4 :(得分:1)


    def magic_square(n):
        num=(n*((n*n)+1))/2
        print('\nThe Magic Number Is:-',num,'\n')
        f=[]
        for i in range(0,n):
            a=[]
            for j in range(0,n):
                a.append(0)
            f.append(a)
        (x,i,p,q)=(n*n,1,int(n/2),n-1)
        while x!=0:
            if x==0:
                (f[p][q],i,p,q,x)=(i,i+1,p-1,q+1,x-1)
                continue
            else:
                if p==-1 and q==n:
                    p=0
                    q=n-2
                    if f[p][q]==0:
                        (f[p][q],i,p,q,x)=(i,i+1,p-1,q+1,x-1)
                        continue
                    else:
                        p=p+1
                        q=q-2
                        f[p][q]=i
                        i=i+1
                        p=p-1
                        q=q+1
                        x=x-1
                        continue
                if p==-1:
                    p=n-1
                    if f[p][q]==0:
                        (f[p][q],i,p,q,x)=(i,i+1,p-1,q+1,x-1)
                        continue
                    else:
                        p=p+1
                        q=q-2
                        f[p][q]=i
                        i=i+1
                        p=p-1
                        q=q+1
                        x=x-1
                        continue
                if q==n:
                    q=0
                    if f[p][q]==0:
                        (f[p][q],i,p,q,x)=(i,i+1,p-1,q+1,x-1)
                        continue
                    else:
                        p=p+1
                        q=q-2
                        f[p][q]=i
                        i=i+1
                        p=p-1
                        q=q+1
                        x=x-1
                        continue
                else:
                    if f[p][q]==0:
                        (f[p][q],i,p,q,x)=(i,i+1,p-1,q+1,x-1)
                        continue
                    else:
                        p=p+1
                        q=q-2
                        f[p][q]=i
                        i=i+1
                        p=p-1
                        q=q+1
                        x=x-1
                        continue
        for i in range(len(f)):
            for j in range(len(f[i])):
                print(f[i][j] ,end = "   ")
            print("\n")

输入

magic_square(5)

输出

魔幻数字是:-65.0

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

答案 5 :(得分:0)

在这里,我创建了示例方法来解决此问题。在这种方法中,我们将维护以下列表

  • lstAvailableNumbers:可用号码列表(在您的情况下为1-9)
  • lstTraversedNumbers:遍历的数字列表(一旦遍历一个项目,它将移至此列表)
  • 重复编号列表(所有重复编号将添加到此列表中)
  • 重复编号索引(它将存储重复编号的索引,以便可以用来替换不存在的编号
  • 它还返回更换成本

出于调试目的,我还添加了print语句以检查其他列表的值

def createMagicSquare(s):
    lstAvailableNumbers = list()
    lstAvailableNumbers=[1,2,3,4,5,6,7,8,9]   
    lstTraversedNumbers=set()
    lstDuplicateNumbers=list()
    dictDuplicateNumberIndex = dict()
    lstMissingNumbers=set()
    cost=0
    for item in range(len(s)):
        for colItem in range(len(s[item])):
            num= s[item][colItem]
            #print('Print traversed number - ' )
            #print(num)
            #print(lstTraversedNumbers)

            if(num in lstAvailableNumbers):
                #print('Inside if condition for  num in lstAvailableNumbers ' )
                lstAvailableNumbers.remove(num)
                #print(num)

                if(num in lstTraversedNumbers):
                    #print('Inside if condition for  num in lstTraversedNumbers ' )
                    #print(num)                    
                    lstDuplicateNumbers.append(num)
                    lstIndexPosition =[]
                    lstIndexPosition.append(item)
                    lstIndexPosition.append(colItem)                        
                    dictDuplicateNumberIndex[num]=lstIndexPosition
                lstTraversedNumbers.add(num)
                #print(lstTraversedNumbers)
            else:
                lstDuplicateNumbers.append(num)
                lstIndexPosition =[]
                lstIndexPosition.append(item)
                lstIndexPosition.append(colItem)                        
                dictDuplicateNumberIndex[num]=lstIndexPosition

    i=0
    #print("Available Numbers -")
    #print(lstAvailableNumbers)
    #print("Traversed Numbers -")
    #print(lstTraversedNumbers)
    #print("Duplicate Numbers -")
    #print(lstDuplicateNumbers)
    #print("Duplicate Number index -")
    #print(dictDuplicateNumberIndex)

    for item in lstAvailableNumbers:        
        itemToReplace= lstDuplicateNumbers[i]
        value= dictDuplicateNumberIndex[itemToReplace]
        s[value[0]][value[1]] = item
        i+=1
        cost += abs(itemToReplace - item)
        #print(cost)    
    return cost