简体   繁体   English

以下递归数独求解 function 是如何工作的?

[英]How does the following recursive Sudoku solving function work?

I recently watched this video showing a recursive function to solve sudoku and this seems irrational, since at the end we always change the value back to zero in the end.我最近看了这个视频,展示了一个递归 function 来解决数独问题,这似乎不合理,因为最后我们总是将值改回零。

How come the function worked in the video but doesnt work for me?为什么 function 在视频中有效但对我无效? Should the grid remain the same for both of us since at the end we use grid[y][x] = 0 which resets the grid discarding all changes made?由于最后我们使用grid[y][x] = 0重置网格并丢弃所做的所有更改,因此我们俩的网格是否应该保持不变?

The idea of this code is to iterate over each number cell and each number (1-9) and check if it is possible to put the number in that cell.这段代码的想法是遍历每个数字单元格和每个数字 (1-9) 并检查是否可以将数字放入该单元格中。 if we reach a dead end we backtrack.如果我们走到了死胡同,我们就会原路返回。

Here's the code I manually copied:这是我手动复制的代码:

import numpy as np
global grid
grid = [[5,3,0,0,7,0,0,0,0],
        [6,0,0,1,9,5,0,0,0],
        [0,9,8,0,0,0,0,6,0],
        [8,0,0,0,6,0,0,0,3],
        [4,0,0,8,0,3,0,0,1],
        [7,0,0,0,2,0,0,0,6],
        [0,6,0,0,0,0,2,8,0],
        [0,0,0,4,1,9,0,0,5],
        [0,0,0,0,8,0,0,7,9]]

def possible(y,x,n):
    global grid
    for i in range(0, 9):
        if grid[y][i] == n:
            return False
    for i in range(0, 9):
        if grid[i][x] == n:
            return False
    x0 = (x//3)*3
    y0 = (y//3)*3
    for i in range(0, 3):
        for j in range(0, 3):
            if grid[y0+i][x0+j] == n:
                return False
    return True

def solve():
    global grid
    for y in range(9):
        for x in range(9):
            if grid[y][x] == 0:
                for n in range(1, 10):
                    if possible(y,x,n):
                        grid[y][x] = n
                        solve()
                        grid[y][x] = 0
                return


print(np.matrix(grid))
print("")
solve()
print(np.matrix(grid))

The problem is that the solve function does indeed reset the grid back to its initial state after has finished executing, but it also solves the sudoku.问题是solve function 确实在完成执行后将网格重置回其初始 state,但它也解决了数独问题。

In the video, note that the grid is printed inside the solve function, not after it:在视频中,请注意网格是在solve function 内部打印的,而不是在它之后:

def solve():
    global grid
    for y in range(9):
        for x in range(9):
            if grid[y][x] == 0:
                for n in range(1, 10):
                    if possible(y,x,n):
                        grid[y][x] = n
                        solve()
                        grid[y][x] = 0
                return
    print(np.matrix(grid))

print(np.matrix(grid))
print("")
solve()

This works because it loops through every cell and only recurses if the cell does not yet have a value filled in, and then after it has tried every value, it returns.这是有效的,因为它循环遍历每个单元格,并且仅在该单元格尚未填充值时递归,然后在尝试了每个值之后,它返回。 The only way it will complete the for y in range(9): loop is if it never finds a cell that is not 0, ie if the sudoku is solved, so by printing the matrix after the loop completes it will ensure that it prints the solved sudoku.完成for y in range(9):循环的唯一方法是,如果它永远找不到不为 0 的单元格,即如果数独已解决,因此通过在循环完成后打印矩阵,它将确保它打印已解决的数独。

Your algorithm is working fine but you don't do anything with the grid when you find a solution.您的算法运行良好,但是当您找到解决方案时,您不会对网格做任何事情。 Once a solution is discovered, the backtracking zeroes out all of the cells it's filled in as it unwinds the call stack.一旦找到解决方案,回溯将在展开调用堆栈时将其填充的所有单元格归零。 By the time you get back to the main scope and print the result, it's back to its original state.当您回到主 scope 并打印结果时,它又回到了原来的 state。

Your algorithm ends when you've iterated all of the rows and columns in a call to solve and find that there are no zeroes left to fill in. After your loops end, print (or better yet, return) the result and you'll see the completed puzzle.当您迭代调用中的所有行和列以solve并发现没有零可填充时,您的算法结束。循环结束后,打印(或者更好的是,返回)结果,您将查看已完成的拼图。

Also, better to pass grid as a parameter to solve rather than use the global keyword.此外,最好将grid作为参数传递,而不是使用global关键字。 Sharing state like this makes it far too easy to introduce bugs.像这样共享 state 很容易引入错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM