我需要在这个Sudoku python代码中进行解释

时间:2014-10-26 06:39:25

标签: python algorithm sudoku

我尝试用Python编写的这个数独求解器https://freepythontips.wordpress.com/2013/09/01/sudoku-solver-in-python/代码工作正常。这是完整的代码:

import sys

def same_row(i,j): return (i/9 == j/9)
def same_col(i,j): return (i-j) % 9 == 0
def same_block(i,j): return (i/27 == j/27 and i%9/3 == j%9/3)

def r(a):
  i = a.find('0')
  if i == -1:
    sys.exit(a)

  excluded_numbers = set()
  for j in range(81):
    if same_row(i,j) or same_col(i,j) or same_block(i,j):
        excluded_numbers.add(a[j])

  for m in '123456789':
    if m not in excluded_numbers:
        r(a[:i]+m+a[i+1:])

r('100070030830600000002900608600004907090000050307500004203009100000002043040080009')

我不理解这个循环:

for m in '123456789':
        if m not in excluded_numbers:
            r(a[:i]+m+a[i+1:])

请有人解释此代码的算法。感谢

编辑: 我问的是那个循环的逻辑,现在我理解了逻辑,我检查了Peter Novig的数独求解器。

2 个答案:

答案 0 :(得分:2)

在代码的开头,您将i设置为尚未填充的第一个字段的索引。接下来,您将excluded_numbers设置为此位置上不允许的所有数字,因为它们与i已存在于同一行,列或块中。

for循环中,你问一下,你循环遍历所有可能的数字,猜测位置i的数字为m。首先检查m是否不是禁止的数字之一,如果不是,则再次递归调用函数r,将空点替换为guess m。这是通过将所有字段连接到位置ia[:i]),猜测m以及位置i之后的所有字段(a[i+1:])来完成的。在位置i之前和之后获取部件由slicing完成到代表整个电路板的长字符串中。

函数r()作为一个整体通过找到第一个未填充的位置,用有效数字填充它然后再次递归调用自身来工作。如果在某个时刻,没有更多的数字填充在某个位置(因为你做出了错误的猜测),函数就会退出。当函数最终找到完整的解决方案(没有0)时,它会打印解决方案并退出。请注意,这不是解决数独的有效方法。一个更好的算法是explained by Peter Norvig,他是Google研究的负责人。

答案 1 :(得分:1)

def r(a):
  i = a.find('0')  #  find the next "missing" item
  if i == -1:  # if there is none, we have a winner - print it on exit
    sys.exit(a)

  excluded_numbers = set()  #  build a set of excluded numbers, the range is [0,9] (though '0' is not meaningful)
  for j in range(81):  #  we have 9 mini 3X3 boards which combined to one sudoku board
    if same_row(i,j) or same_col(i,j) or same_block(i,j):  #  if i and j are on the same row/column/block - we'll exclude the item on a[j] because i cannot contain the same number - according to sudoku rules
        excluded_numbers.add(a[j])

for m in '123456789':  #  for each one of the candidates m in [1,2,3,...9] (though it's being read as a string)
    if m not in excluded_numbers:  #  if m was not excluded in the previous step 
        r(a[:i]+m+a[i+1:])  #  replace the i-th item with m and continue (recursively)

在最后一行,我们有一个递归调用,试图使用未被排除的m中的每一个来“猜测”解决方案。假设该板至少有一个解决方案 - 至少有一个调用应达到条件if i == -1,并且第一个递归分支将到达那里将打印自己并退出(忽略其他可能的解决方案,“稍后”)所有其他可能性树上的一片叶子。)