数独求解算法
我想用 python 编写代码来解决数独难题。你们知道用于此目的的好算法吗?我在网上的某个地方读到了一种算法,该算法通过用所有可能的数字填充整个盒子,然后将已知值插入相应的盒子来解决这个问题。从已知值的行和列中,已知值被删除。如果你们知道更好的话比这个算法请帮我写一个。我也很困惑我应该如何从用户那里读取已知值。通过控制台一一输入数值确实很困难。除了使用 gui 之外,还有什么简单的方法吗?
I want to write a code in python to solve a sudoku puzzle. Do you guys have any idea about a good algorithm for this purpose. I read somewhere in net about a algorithm which solves it by filling the whole box with all possible numbers, then inserts known values into the corresponding boxes.From the row and coloumn of known values the known value is removed.If you guys know any better algorithm than this please help me to write one. Also I am confused that how i should read the known values from the user. It is really hard to enter the values one by one through console. Any easy way for this other than using gui?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
这是我用 python 编写的数独解算器。它使用简单的回溯算法来解决难题。
为了简单起见,没有进行输入验证或奇特的输出。这是解决问题的最低限度代码。
算法
解决方案
需要 9X9 网格,部分填充数字。值为 0 的单元格表示该单元格未填充。
代码
测试代码
上面是非常基本的回溯算法,在很多地方都有解释。但我遇到的最有趣、最自然的数独解决策略是这个 来自此处
Here is my sudoku solver in python. It uses simple backtracking algorithm to solve the puzzle.
For simplicity no input validations or fancy output is done. It's the bare minimum code which solves the problem.
Algorithm
Solution
It takes 9X9 grid partially filled with numbers. A cell with value 0 indicates that it is not filled.
Code
Testing the code
The above one is very basic backtracking algorithm which is explained at many places. But the most interesting and natural of the sudoku solving strategies I came across is this one from here
我还用 Python 编写了一个数独求解器。这也是一个回溯算法,但我也想分享我的实现。
回溯可以足够快,因为它在限制范围内移动并且明智地选择单元格。您可能还想查看我在此线程中关于优化算法的回答。但这里我将重点关注算法和代码本身。
该算法的要点是开始迭代网格并决定要做什么 - 填充单元格,或尝试同一单元格的另一个数字,或清空一个单元格并移回前一个单元格,等等。值得注意的是没有确定的方法可以知道解决这个难题需要多少步骤或迭代。因此,您实际上有两个选择 - 使用 while 循环或使用递归。它们都可以继续迭代,直到找到解决方案或直到证明缺乏解决方案。递归的优点是能够进行分支,一般支持更复杂的逻辑和算法,但缺点是实现起来比较困难,调试起来也比较棘手。对于回溯的实现,我使用了 while 循环,因为不需要分支,该算法以单线程线性方式进行搜索。
逻辑如下:
While True:(主要迭代)
While True:(回溯迭代)
是没有解决办法。
继续下一次回溯迭代。
回溯并返回到主要迭代。
该算法的一些特点:
它以相同的顺序记录访问过的单元格,以便随时回溯
它都会记录每个单元格的选择记录,这样它就不会在同一个单元格中尝试相同的数字两次
单元格的可用选择始终在数独约束内(行、列和 3x3 象限)
此特定实现有几种不同的方法来根据输入参数选择下一个单元格和下一个数字(优化线程中的更多信息)
如果给定一个空白网格,那么它将生成一个有效的数独谜题(与优化参数“C”一起使用,以便每次生成随机网格时间)
如果给定一个已解决的网格,它会识别它并打印一条消息
完整的代码是:
根据本文使用世界上最难的数独进行示例调用 http://www.telegraph.co.uk/news/science /science-news/9359579/Worlds-hardest-sudoku-can-you-crack-it.html
示例输出为:
I also wrote a Sudoku solver in Python. It is a backtracking algorithm too, but I wanted to share my implementation as well.
Backtracking can be fast enough given that it is moving within the constraints and is choosing cells wisely. You might also want to check out my answer in this thread about optimizing the algorithm. But here I will focus on the algorithm and code itself.
The gist of the algorithm is to start iterating the grid and making decisions what to do - populate a cell, or try another digit for the same cell, or blank out a cell and move back to the previous cell, etc. It's important to note that there is no deterministic way to know how many steps or iterations you will need to solve the puzzle. Therefore, you really have two options - to use a while loop or to use recursion. Both of them can continue iterating until a solution is found or until a lack of solution is proven. The advantage of the recursion is that it is capable of branching out and generally supports more complex logics and algorithms, but the disadvantage is that it is more difficult to implement and often tricky to debug. For my implementation of the backtracking I have used a while loop because no branching is needed, the algorithm searches in a single-threaded linear fashion.
The logic goes like this:
While True: (main iterations)
While True: (backtrack iterations)
is no solution.
continue to the next backtrack iteration.
backtracking and return to the main iterations.
Some features of the algorithm:
it keeps a record of the visited cells in the same order so that it can backtrack at any time
it keeps a record of choices for each cell so that it doesn't try the same digit for the same cell twice
the available choices for a cell are always within the Sudoku constraints (row, column and 3x3 quadrant)
this particular implementation has a few different methods of choosing the next cell and the next digit depending on input parameters (more info in the optimization thread)
if given a blank grid, then it will generate a valid Sudoku puzzle (use with optimization parameter "C" in order to generate random grid every time)
if given a solved grid it will recognize it and print a message
The full code is:
Example call using the world's hardest Sudoku as per this article http://www.telegraph.co.uk/news/science/science-news/9359579/Worlds-hardest-sudoku-can-you-crack-it.html
And example output is:
这是基于 hari 答案的更快的解决方案。基本区别在于,我们为未分配值的单元格保留一组可能的值。因此,当我们尝试新值时,我们只尝试有效值,并且还会传播此选择对数独其余部分的含义。在传播步骤中,我们从每个单元格的有效值集中删除已出现在行、列或同一块中的值。如果集合中只剩下一个数字,我们就知道该位置(单元格)必须具有该值。
此方法称为前向检查和前瞻 (http://ktiml. mff.cuni.cz/~bartak/constraints/propagation.html)。
下面的实现需要一次迭代(调用solve),而hari的实现需要487次。当然我的代码有点长。传播方法也不是最佳的。
Here is a much faster solution based on hari's answer. The basic difference is that we keep a set of possible values for cells that don't have a value assigned. So when we try a new value, we only try valid values and we also propagate what this choice means for the rest of the sudoku. In the propagation step, we remove from the set of valid values for each cell the values that already appear in the row, column, or the same block. If only one number is left in the set, we know that the position (cell) has to have that value.
This method is known as forward checking and look ahead (http://ktiml.mff.cuni.cz/~bartak/constraints/propagation.html).
The implementation below needs one iteration (calls of solve) while hari's implementation needs 487. Of course my code is a bit longer. The propagate method is also not optimal.
我写了一个简单的程序来解决简单的问题。它从一个文件中获取输入,该文件只是一个带有空格和数字的矩阵。解决这个问题的数据结构只是一个 9 x 9 的位掩码矩阵。位掩码将指定在某个位置上哪些数字仍然可能。填充文件中的数字将减少每个已知位置旁边的所有行/列中的数字。完成后,您将继续迭代矩阵并减少可能的数字。如果每个位置只剩下一个选项,那么您就完成了。但有些数独需要更多的工作。对于这些,你可以使用蛮力:尝试所有剩余的可能组合,直到找到一个有效的组合。
I wrote a simple program that solved the easy ones. It took its input from a file which was just a matrix with spaces and numbers. The datastructure to solve it was just a 9 by 9 matrix of a bit mask. The bit mask would specify which numbers were still possible on a certain position. Filling in the numbers from the file would reduce the numbers in all rows/columns next to each known location. When that is done you keep iterating over the matrix and reducing possible numbers. If each location has only one option left you're done. But there are some sudokus that need more work. For these ones you can just use brute force: try all remaining possible combinations until you find one that works.
我知道我迟到了,但这是我的版本:
它使用回溯。但这不是我编码的,它是Tech With Tim's。该列表包含世界上最难的数独,通过实现计时功能,时间为:
但对于一个简单的数独谜题,如:
结果是:
我可以说相当快。
I know I'm late, but this is my version:
It uses backtracking. But is not coded by me, it's Tech With Tim's. That list contains the world hardest sudoku, and by implementing the timing function, the time is:
But with a simple sudoku puzzle like:
The result is :
Pretty fast I can say.
使用回溯实现相同算法的简短尝试:
a short attempt to achieve same algorithm using backtracking:
解决数独难题有四个步骤:
并尝试建立一个可能的矩阵。
2.检查双对,如果存在,则从该行/列/框中的所有单元格中删除这两个值,无论该对存在于何处
如果任何单元格具有单一可能性,则分配该单元格
再次运行步骤 1
再次运行步骤 1
假设第一个可能的值并分配。然后运行步骤 1-3
如果仍未解决,则对下一个可能的值执行此操作并以递归方式运行它。
假设第一个可能的值并分配。然后运行步骤 1-3
如果仍未解决,则对下一个可能的值执行此操作并以递归方式运行。
There are four steps to solve a sudoku puzzle:
and try to develop a possible matrix.
2.Check for double pair, if it exists then remove these two values from all the cells in that row/column/box, wherever the pair exists
If any cell is having single possiblity then assign that
run step 1 again
run step 1 again
Assume the first possible value and assign. Then run step 1–3
If still not solved then do it for next possible value and run it in recursion.
Assume the first possible value and assign. Then run step 1–3
If still not solved then do it for next possible value and run it in recursion.
不会写完整的代码,但我很久以前就做了一个数独求解器。我发现它并不总能解决问题(人们在拥有报纸时所做的事情是不完整的!),但现在我想我知道该怎么做。
Not gonna write full code, but I did a sudoku solver a long time ago. I found that it didn't always solve it (the thing people do when they have a newspaper is incomplete!), but now think I know how to do it.
使用 google ortools - 以下将生成一个虚拟数独数组或解决一个候选数。该代码可能比所需的更详细,任何反馈都值得赞赏。
这个想法是解决一个约束编程问题,该问题涉及
此外,当尝试解决现有的数独,我们对已经分配值的变量添加额外的约束。
解决以下数独
Using google ortools - the following will either generate a dummy sudoku array or will solve a candidate. The code is probably more verbose than required, any feedback is appreciated.
The idea is to solve a constraint-programming problem that involves
In addition, when trying to solve existing sudoku, we add additional constraints on variables that already have assigned value.
Solve the following sudoku
您好,我在博客中写过关于用 Python 从头开始编写数独求解器的文章,并且目前正在编写关于用 Julia(另一种高级但更快的语言)编写约束编程求解器的整个系列
您可以从文件中读取数独问题,这似乎比 gui 或 cli 方式更容易、更方便。它使用的总体思想是约束规划。我使用所有不同/唯一的约束,但我自己编码,而不是使用约束编程求解器。
如果有人感兴趣:
Hi I've blogged about writing a sudoku solver from scratch in Python and currently writing a whole series about writing a constraint programming solver in Julia (another high level but faster language)
You can read the sudoku problem from a file which seems to be easier more handy than a gui or cli way. The general idea it uses is constraint programming. I use the all different / unique constraint but I coded it myself instead of using a constraint programming solver.
If someone is interested:
这是我前段时间用 Tensorflow 和 mnist 以及自动求解器做的一个项目。不过,求解器算法没有很好的记录:)
https://github.com/Sohrab82/Sudoku-Solver< /a>
This is a project I did some time ago with Tensorflow and mnist and automatic solver. The solver algorithm is not well documented though :)
https://github.com/Sohrab82/Sudoku-Solver