【问题标题】:Python Sudoku Backtracking Solved! But Not Returning AnswerPython数独回溯已解决!但不返回答案
【发布时间】:2020-06-13 12:52:04
【问题描述】:

我已经正确地制作了一个数独回溯求解器。但现在我需要得到解决方案,但由于某种原因,我不断得到原来的数独网格。数独问题有一个独特的解决方案。

answer = []
count = 0
def solution(sudoku):
    global answer
    global count
    for y in range(9):
        for x in range(9):
            if sudoku[y][x] == 0: # Found an empty grid
                for n in range(1, 10):
                    if isPossible(x, y, n, sudoku):
                        sudoku[y][x] = n
                        solution(sudoku) # Recursion here
                        sudoku[y][x] = 0 # If no solution then reset the grid and go back
                solved = False
                return sudoku
    print("hi look at me")
    if count == 0:
        answer = list(sudoku)
        print(answer)
        count += 1
    return sudoku

hi = solution(board)
print(answer)
print(hi)

在此解决方案中, answer = list(sudoku) 将解决方案放置到我的全局变量中,还请注意,我使用 list() 来确保当数独参数更改时全局答案不会更改。我已确保这只发生一次。我知道这种回溯将导致原始数独板,因为一旦解决了解决方案,该算法将设置 sudoku[y][x] = 0,有效地将解决方案归零。但是唯一的解决方案已经存储在答案中,当我尝试在函数之外打印答案时,我得到了原始未解决的数独板。 那么为什么函数中的“答案”得到了正确的解决方案,但是一旦函数之外的“答案”给了我原来的板? answer = list(sudoku) 只出现一次, list() 给了我一个新的列表对象,所以即使数独改变答案也永远不会改变,那么改变之后怎么办?经过数小时的调试,我真的被卡住了。如何将解决方案放入函数之外的内容中?

完整代码以防万一

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

def isPossible(x, y, n, sudoku):
    if n in sudoku[y]: # Check if in row
        return False
    for i in range(0, 9):
        if n == sudoku[i][x]: # Check if in column
            return False
    y //= 3
    x //= 3
    for i in range(y*3, y*3 + 3): # Check if in squares
        for j in range(x*3, x*3 + 3):
            if n == sudoku[i][j]:
                return False
    return True

answer = []
count = 0
def solution(sudoku):
    global answer
    global count
    for y in range(9):
        for x in range(9):
            if sudoku[y][x] == 0: # Found an empty grid
                for n in range(1, 10):
                    if isPossible(x, y, n, sudoku):
                        sudoku[y][x] = n
                        solution(sudoku) # Recursion here
                        sudoku[y][x] = 0 # If no solution then reset the grid and go back
                return sudoku
    print("hi look at me")
    if count == 0:
        answer = list(sudoku)
        print(answer)
        count += 1
    return sudoku

hi = solution(board)
print(answer)
print(hi)

【问题讨论】:

    标签: python sudoku


    【解决方案1】:

    你的问题是你有一个嵌套的列表结构,list(sudoku) 只做一个浅拷贝。内部列表仍然是与以后代码修改的对象相同的对象。如果你想要一个深拷贝,你可能想要使用copy 模块的deepcopy 函数:

    answer = copy.deepcopy(sudoku)
    

    虽然这应该可以解决您在成功解决方案上到处乱写的回溯问题,但这并不会改变这样一个事实,即您的解决方案将在您已经找到一个解决方案后继续尝试找到更多解决方案。为避免这种情况,您可能需要更改代码,以便在成功与否时返回信号值。如果您只返回一个已解决的板,或者如果您没有找到一个None,您可以使用它在找到解决方案时立即结束搜索。作为奖励,您不再需要使用任何全局变量。

    这应该是这样的:

    def solution(sudoku):                          # no more global variables needed
        for y in range(9):
            for x in range(9):
                if sudoku[y][x] == 0:
                    for n in range(1, 10):
                        if isPossible(x, y, n, sudoku):
                            sudoku[y][x] = n
                            result = solution(sudoku)
                            if result is not None: # check if the recursion was successful or not
                                return result      # and stop searching if it was!
                            sudoku[y][x] = 0
                    return None                    # signal failure
        return sudoku                              # signal success by returning the board
    

    【讨论】:

      【解决方案2】:

      问题是你只是制作了一个简单的板子副本,所以它会随着更新而不断变化。

      浅拷贝:

      answer = list(sudoku)
      

      一种选择是改用deepcopy

      answer = deepcopy(sudoku)
      

      在您的代码中将 list 替换为 deepcopy 后,全局保留答案。

      未来的问题可能是:

      1. 由于不鼓励简单代码使用全局变量,如何在不使用全局变量的情况下重写此代码?
      2. 这段代码真的是回溯还是穷举?

      【讨论】:

        猜你喜欢
        • 2021-04-15
        • 2021-10-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-30
        • 1970-01-01
        相关资源
        最近更新 更多