【问题标题】:Sudoku backtracking solver bug数独回溯求解器错误
【发布时间】:2021-03-14 10:33:50
【问题描述】:

好的,我已经为此苦苦思索了几个小时了..

我的目标是编写一个使用回溯方法的数独求解器,并使用 pygame 显示算法的进度。为此,我必须跟踪事件,我通过将它们附加到名为 registre 的列表中来做到这一点,如代码所示:

def solver(self):
    self.t1 = time.time()
    if self.t1-self.t0 > self.solve_time_max:
        sys.exit(1)
    for i in range(self.grid.shape[0]):
        for j in range(self.grid.shape[1]):
            if self.grid[i][j]==0:
                for n in range(1,10):        
                    self.registre.append([n,i,j])
                    if self.verify(n,i,j):
                        self.grid[i][j]=n
                        
                        self.solver()
                        if 0 not in self.grid:
                            break
                    self.registre.append([0,i,j])
                    self.grid[i][j]=0
                    
                return self.grid

我实际上成功了,并且大部分运行都很好。但有时,由于某种我无法识别的原因,会发生这种情况:

    print(une_grille.grid0)
    print(une_grille.grid)
    print(une_grille.registre[:20])
   [[0 8 0 7 0 0 0 0 2]
    [5 0 0 0 0 9 0 0 0]
    [0 0 0 0 0 0 0 0 0]
    [0 0 0 0 0 0 0 0 0]
    [0 1 0 0 6 0 0 0 0]
    [4 0 0 9 0 0 0 0 0]
    [0 0 9 0 8 0 0 0 4]
    [2 0 0 0 0 0 0 8 0]
    [0 0 0 0 0 0 0 0 0]]
   [[1 8 3 7 4 5 6 9 2]
    [5 2 4 6 1 9 3 7 8]
    [6 9 7 2 3 8 1 4 5]
    [3 5 2 8 7 1 4 6 9]
    [9 1 8 3 6 4 2 5 7]
    [4 7 6 9 5 2 8 1 3]
    [7 3 9 1 8 6 5 2 4]
    [2 4 1 5 9 3 7 8 6]
    [8 6 5 4 2 7 9 3 1]]
    [[1, 0, 0], [1, 0, 1], [0, 0, 1], [2, 0, 1], [0, 0, 1], [3, 0, 1], [1, 0, 
    2], [0, 0, 2], [2, 0, 2], [0, 0, 2], [3, 0, 2], [0, 0, 2], [4, 0, 2], [0, 
    0, 2], [5, 0, 2], [1, 0, 3], [0, 0, 3], [2, 0, 3], [0, 0, 3], [3, 0, 3]]

打印的只是初始化的网格、求解的网格和self.registre 中的前 20 个事件。对于这次运行,pygame 上的显示不起作用,一些数字重叠,而另一些则留空。我几乎可以肯定这不是显示问题,因为显示功能使用列表registre,并且它适用于大多数其他运行。我也不明白这些事件。

完整的脚本:

import numpy as np
import random as rd
import time
import sys

class Grid():

"""
une Docstring

"""
def __init__(self, nval=15, dim=(9,9), tries_max=1000, init_time_max=5e-3, solve_time_max = 1):
    self.nval = nval+1
    self.dim = dim 
    self.t0 = 0
    self.t1 = 0
    self.tries_max = tries_max
    self.k = 0
    self.init_time_max = init_time_max
    self.solve_time_max = solve_time_max
    self.registre = []
    
    self.grid =  self.create_grid()   
    self.smthg = 0
    
    
def create_grid(self):
    for tries in range(self.tries_max):
        self.k = 0
        if tries == self.tries_max -1:
            print(f"Tried {self.tries_max} times, I have failed")
            sys.exit(1)
        self.grid0 = np.zeros([self.dim[0],self.dim[1]], dtype=int)
        try:
            self.grid0 = self.initialize_board()
        except SystemExit:
            print(f"TRY #{tries}: Spent too much time initializing board. Re-trying.")
            continue
        self.grid = np.copy(self.grid0)
        try:
            self.t0 = time.time()
            self.grid = self.solver()
            if 0 not in self.grid:
                print(f"Found grid with solution after n = {tries+1} tries!")
                return self.grid
            else:
                print(f"TRY #{tries} converged to null solution")
                continue
        except SystemExit:
            print(f"TRY #{tries} too much time spent trying to solve current grid, continuing")
            continue
    print("Maximum tries reached")
    
def initialize_board(self):
    for i in range(self.nval):
        rx = rd.randint(0, self.grid0.shape[0]-1)
        ry = rd.randint(0, self.grid0.shape[1]-1)
        cx = int(rx/3)
        cy = int(ry/3)
        time0 = time.time()
        while(self.grid0[rx][ry]==0):
            if time.time()-time0 > self.init_time_max:
                sys.exit(1)
            r = rd.randint(1, 9)
            if((r in self.grid0[rx,:]) or (r in self.grid0[:,ry]) or (r in self.grid0[3*cx:3*cx+3,3*cy:3*cy+3])):
                continue
            else:
                self.grid0[rx][ry] = r
    return self.grid0
        





def solver(self):
    self.t1 = time.time()
    if self.t1-self.t0 > self.solve_time_max:
        sys.exit(1)
    for i in range(self.grid.shape[0]):
        for j in range(self.grid.shape[1]):
            if self.grid[i][j]==0:
                for n in range(1,10):        
                    self.registre.append([n,i,j])
                    if self.verify(n,i,j):
                        self.grid[i][j]=n
                        
                        self.solver()
                        if 0 not in self.grid:
                            break
                    self.registre.append([0,i,j])
                    self.grid[i][j]=0
                    
                return self.grid
    
def verify(self, number, x, y):
    cx = int(x/3)
    cy = int(y/3)
    if((number in self.grid[x,:]) or (number in self.grid[:,y]) or (number in self.grid[3*cx:3*cx+3,3*cy:3*cy+3])):
        return False
    return True
    

game = Grid(nval = 35)
print(game.grid)
print(game.grid0)
print(game.registre[:20])

问题的另一个实例:

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

如果您能帮我解决这个问题,我将不胜感激。

【问题讨论】:

  • 请不要将文字作为图片发布。
  • 是的,很抱歉,但是我还没有足够的声望,所以我不能直接发布图片。我至少会编辑并放置代码。
  • 请同时添加您得到的输出,并且产生该输出的代码(带有print)因为您提供的代码不会输出任何内容。
  • 好的,再次抱歉。
  • 我无法重现此输出。对于示例网格(在 [0,1] 处具有非零值),注册输出看起来不是这样。该注册表中的第二个条目与输入网格相矛盾,当我尝试使其运行时,该注册表以[[1, 0, 0], [1, 0, 2],... 开头。请提供信息以允许重现任何问题。只需提供我们可以运行的代码。现在您省略了基本代码...

标签: python debugging backtracking sudoku


【解决方案1】:

在您添加重复生成网格的代码后,很明显您不会创建Grid 的新实例,而是改变现有实例。在该过程中,您应该注意完全重置状态。您只能部分执行此操作,例如通过重置t0。但是您没有重置registre,因此当您打印前 20 个项目时,您实际上是在查看第一次尝试的日志,而不是成功的日志。

【讨论】:

  • 非常感谢!我现在可以看得很清楚了。
猜你喜欢
  • 2023-03-27
  • 2017-12-16
  • 1970-01-01
  • 2021-12-11
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多