python - 我的数独模拟器的验证功能有什么问题吗?
问题描述
我最近正在使用 python 构建一个数独模拟器,我很困惑为什么我的验证函数不能按预期工作。我尝试使用另一种使用 3 个 for 循环的验证方法,它有效,所以我认为我的解决方法没有问题。基本上如果在同一行、列或对角线上有相同的数字,它将返回 False,否则返回 True
def validate1(grid, r, c, val):
var = 0
r_up = r-var
r_down = r+var
c_right = c+var
c_left = c-var
while(r_up>=0 or r_down<=8 or c_right<=8 or c_left>=0):
if(r_up>=0):
if(grid[r_up][c]==val):
return False
if(r_down<=8):
#print("down" + str(grid[r_down][c]))
if(grid[r_down][c]==val):
return False
if(c_right<=8):
if(grid[r][c_right]==val):
return False
if(c_left>=0):
if(grid[r][c_left]==val):
return False
if(r_up>=0 and c_right<=8):
if(grid[r_up][c_right]==val):
return False
if(r_up>=0 and c_left>=0):
if(grid[r_up][c_left]==val):
return False
if(r_down<=8 and c_right<=8):
if(grid[r_down][c_right]==val):
return False
if(r_down<=8 and c_left>=0):
if(grid[r_down][c_left]==val):
return False
var = var + 1
r_up = r-var
r_down = r+var
c_right = c+var
c_left = c-var
return True
解决方案
我建议不要试图找出问题所在,而是让函数更简单(并且更 Pythonic):
def validate1(grid,r,c,val):
if val in grid[r] : return False
if val in (row[c] for row in grid): return False
if any(val in row[c//3*3:][:3] for row in grid[r//3*3:][:3]): return False
return True
但是,像这样检查冲突并不是最快的方法。你可以做的是维护27组已使用的号码,对应于板上的专属组。每个位置映射到这些组中的 3 个(行、列、块),因此您可以快速将放置的数字添加到它们,并使用集合成员快速检查是否存在冲突的数字。这可以通过将数字与其组索引相结合来进一步改进,从而允许您使用一组 243 个 groupID-number 对来管理冲突。有了这个,您可以编写一个非常紧凑的数独求解器,带有回溯功能,可以蛮力解决问题:
def shortSudokuSolve(board):
size = len(board)
block = int(size**0.5)
board = [n for row in board for n in row ]
span = { (n,p): { (g,n) for g in (n>0)*[p//size, size+p%size, 2*size+p%size//block+p//size//block*block] }
for p in range(size*size) for n in range(size+1) }
empties = [i for i,n in enumerate(board) if n==0 ]
used = {gn for p,n in enumerate(board) for gn in span[n,p] if n}
empty = 0
while empty>=0 and empty<len(empties):
pos = empties[empty]
used -= span[board[pos],pos]
board[pos] = next((n for n in range(board[pos]+1,size+1) if not span[n,pos]&used),0)
used |= span[board[pos],pos]
empty += 1 if board[pos] else -1
return [board[r:r+size] for r in range(0,size*size,size)]
推荐阅读
- keras - Keras中的自定义损失函数结合了多个输出
- jquery - 检查数据表中是否存在值
- javascript - JS 请求不显示传单的 API 密钥
- java - 我想在数组中找到字符串的索引
- javascript - Javascript检测是否可以设置音量
- javascript - 将数组中的所有数字填充到随机 div 中
- flutter - Flutter Futures:等待侦听器至少完成一次
- python - 显示登录用户的数据列表
- swiftui - SwiftUI 状态变量非对称转换
- c++ - 无法理解 C++ 参考手册中的示例中使用的这种类型 `void(C::* volatile)(int) const`