我试图编写一个算法来解决任何数独.然而,我原来的方法是有缺陷的,因为我没有意识到一个结构良好的数独应该只有一个解决方案.
因此,结果算法没有针对数独求解进行优化,并且更为通用:它递归地生成当前数独布局的每个可能允许的结果/布局.因此,该算法在理论上可以找到空白数独的每个解决方案(但我/我们/人类可能不会看到输出).
我的第一个问题是:对于这种类型的搜索算法,什么是最佳方法 – 如何改进我的算法?总体战略是:
>在分支点尝试所有可能的解决方案
>如果无法解决单元格,则终止分支
>如果达到解决方案,则终止分支
结构和方法改编自为解决SICP(https://mitpress.mit.edu/sicp/full-text/book/book-Z-H-15.html)中的八皇后问题而提出的时间解耦解决方案,似乎这是一种反向跟踪算法(将“时间”状态推入机器中),在我的情况下这是真的吗?
我的第二个问题是,在处理递归算法时,如何使用Ruby> = 2.x Lazy功能生成可枚举?
期望的结果是做一些像solve(sudoku).first(x)这样的东西来检索第一个x解决方案.即解决方案存储为流/序列.我遇到的困难是递归生成嵌套的枚举,我正在努力寻找一种方法来传递整个树的强制方法.
我已在下面列出了密钥代码,但完整的方法套件可以在这里找到:https://gist.github.com/djtango/fe9322748cf8a055fc0e
def solve(sudoku) guess(simplify_sudoku(sudoku)) end def guess(sudoku,row = 0,column = 0) return sudoku.flatten if end_of_grid?(row,column) return guess(sudoku,row + 1,0) if end_of_column?(column) return guess(sudoku,row,column + 1) if filled?(sudoku,column) return nil if insoluble?(sudoku,column) permissible_values(sudoku,column).map do |value| guess(update_sudoku(sudoku,value,column),column + 1) end end def simplify_sudoku(sudoku) return sudoku if no_easy_solutions?(sudoku) simplify_sudoku(fill_in(sudoku)) end def fill_in(sudoku) new_sudoku = copy_sudoku(sudoku) new_sudoku.map.with_index do |row,row_index| row.map.with_index do |column,column_index| solution = permissible_values(new_sudoku,row_index,column_index) easy_and_not_filled?(solution,new_sudoku,column_index) ? [solution.first] : column end end end
在尝试实现延迟评估时,引入惰性方法的最自然点是猜测方法,如下所示:
permissible_values(sudoku,column + 1) end
但是在实现这个时,结果是:
solve(blank_sdk) => #<Enumerator::Lazy: #<Enumerator::Lazy: [1,2,3,4,5,6,7,8,9]>:map> solve(blank_sdk).first(10) => [#<Enumerator::Lazy: #<Enumerator::Lazy: [2,9]>:map>,#<Enumerator::Lazy: #<Enumerator::Lazy: [1,8]>:map>] solve(blank_sdk).first(1000000000000) => [#<Enumerator::Lazy: #<Enumerator::Lazy: [2,8]>:map>]
解决方法
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。