2

我正在编写一个程序,该程序读取文件中的一行并确定该行是否构成 Lo Shu 魔方。在这个幻方中,行之和、列之和、对角线之和必须等于 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 还很陌生,我一直盯着这个几个小时试图理解它。

4

6 回答 6

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')
于 2017-02-05T21:10:27.940 回答
2

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

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()
于 2017-02-05T20:16:53.630 回答
2

    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")

输入

魔方(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

于 2018-09-04T16:04:05.207 回答
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()
于 2017-02-05T20:25:54.317 回答
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()

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

于 2017-02-05T20:48:06.097 回答
0

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

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

出于调试目的,我还添加了打印语句来检查不同列表的值

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 
于 2018-08-09T21:18:20.760 回答