表示数独谜题的正确数据结构?
用于表示数独谜题的智能数据结构是什么?即一个 9X9 的正方形,其中每个“单元格”包含一个数字或一个空格。
特殊考虑因素包括:
- 能够跨行、列和 3X3“组进行比较
- 易于实现(特别是在 Python 中)
- 效率(不是最重要的)
我想在紧要关头,二维数组可能会起作用,但这似乎不太优雅我只是想知道是否有更好的数据结构。
What would be a smart data structure to use to represent a Sudoku puzzle? I.e. a 9X9 square where each "cell" contains either a number or a blank.
Special considerations include:
- Ability to compare across row, column, and in 3X3 "group
- Ease of implementation (specifically in Python)
- Efficiency (not paramount)
I suppose in a pinch, a 2D array might work but that seems to be a less than elegant solution. I just would like to know if there's a better data structure.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
实际上,我构建了这样一个野兽,既是求解器又是生成器,并且我使用了 2D 数组。效果很好。
您只需要了解索引以及它们在哪里,掌握起来并不难。
行中的单元格之间的相对关系不会根据列而改变,列中的单元格甚至小方块中的单元格也是如此。
有时,不太“优雅”的解决方案就可以了。事实上,有时,这是更好的:-)
就其价值而言,您可能对我用于求解器/生成器的算法感兴趣。
首先,我编写了求解器部分,它首先将所有单元格设置为可以是任何值,然后按顺序应用所有规则来查看单个单元格是否可以被求解或以其他方式受到限制,例如:
N
并且N
存在于其行/列/小方块中的其他位置,则消除这种可能性。依此类推,添加我在解决真正的难题时使用的每条规则。
对于生成器,我从:开始
,然后在不同大小(至少 500)的循环中,继续以永远不会产生无效谜题的方式交换行和列。换句话说,将行或列与它们所在的组交换(例如,第 1、2 和 3 行是一个组,第 4、5 和 6 列也是一个组)。
这足以对细胞进行重组,从而产生一个像样的谜题。
然后,我开始选择随机单元格并将它们设置为未知。一旦单元格被设置为未知,我就会将整个谜题传递给求解器。如果可以解决,我会继续,否则我会重新设置单元格并继续。
这防止了我遇到逻辑上无法解决的难题。
一旦完成大量随机单元删除,我将尝试使用相同的方法按顺序删除所有剩余的单元。剩下的就是解决这个难题所需的最少信息量。
而且,所以这对数独初学者来说并不是一件痛苦的事,我允许他们指定一个较低的难度级别,这将把一定数量的不必要的单元放回去。这
不是一个坏方案,可能有更好的方案,但有一个有效对我来说很好。
现在,如果我能弄清楚这些 Kakuro 的东西,我就可以幸福地死去:-)
Actually, I built such a beast, both a solver and a generator, and I used a 2D array. It worked fine.
You just had to understand the indexes and where they were and that wasn't too difficult to master.
The relative relationships between cells in a row doesn't change depending on the column, same goes for cells in a column, or even cells in a mini-square.
Sometimes, a less "elegant" solution is just fine. Indeed, sometimes, it's preferable :-)
For what it's worth, you may be interested in the algorithms that I used for the solver/generator.
First I wrote the solver part which would first set all cells as being able to be any value then apply all the rules in sequence to see if a individual cell could be solved or otherwise limited, things like:
N
andN
exists in its row/column/mini-square elsewhere, remove that possibility.And so on, adding each rule that I use in solving the real puzzles.
For the generator, I started with:
and then, in a loop of varying size (at least 500), proceeded to swap rows and columns in such a way that it would never produce an invalid puzzle. In other words, swap rows or columns with the group they're in (for example, rows 1, 2 and 3 are a group, so are columns 4, 5 and 6).
This shuffled up the cells well enough to produce a decent puzzle.
Then, I started choosing random cells and setting them as unknown. Once a cell was set as unknown, I would pass the whole puzzle into the solver. If it was solvable, I would continue, otherwise I would re-instate the cell and carry on.
This prevented me getting a puzzle that was logically unsolvable.
Once a large number of random cell removals had been done, I would try to remove all the remaining cells in order using the same method. What was left then was the minimum amount of information required to solve the puzzle.
And, so it wasn't a pain to Sudoku beginners, I would allow them to specify a lower difficulty level which would put a certain number of the unnecessary cells back in.
Not a bad scheme, there may be better ones but that one worked fine for me.
Now, if I could only figure out this Kakuro stuff, I could die happy :-)
阅读 Peter Norvig 的文章解决每个数独难题。您不太可能找到更优雅的解决方案,并且您可能会在此过程中学到一些有关数据结构、Python 和性能分析的新知识。
Read Peter Norvig's essay Solving Every Sudoku Puzzle. You're unlikely to find a more elegant solution and you'll probably learn some new things about data structures, Python, and performance analysis in the process.
其他人合理地建议简单地使用二维数组。
我注意到大多数语言实现中的二维数组(任何被实现为“X 数组的数组”的数组都会遭受额外的访问时间开销(一次访问顶级数组,第二次访问子数组)。
我建议您将数据结构抽象地实现为 2D 数组(甚至可能继续使用 2 个索引),但将数组实现为 81 个单元的单个块,传统上由 i*9+j 索引这使您概念清晰,并且实现更有效。 ,通过避免第二次内存访问,
您应该能够将 1D 数组访问隐藏在采用 2D 索引的 setter 和 getter 后面,如果您的语言具有此功能(不知道 Python 是否如此),则可以内联这样的小方法。额外的速度。
Others have reasonably suggested simply using a 2D array.
I note that a 2D array in most language implementations (anything in which that is implemented as "array of array of X" suffers from additional access time overhead (one access to the top level array, a second to the subarray).
I suggest you implement the data structure abstractly as a 2D array (perhaps even continuing to use 2 indexes), but implement the array as single block of 81 cells, indexed classically by i*9+j. This gives you conceptual clarity, and somewhat more efficient implementation, by avoiding that second memory access.
You should be able to hide the 1D array access behind setters and getters that take 2D indexes. If your language has the capability (dunno if this is true for Python), such small methods can be inlined for additional speed.
Python 没有太多的数据结构。您最好的选择可能只是一个常规的二维数组或构建您自己的使用类。
您可以在此处阅读有关 python 数据类型的更多信息。
Python doesn't have much in the way of data structures. Your best bet is probably just a regular 2D array or to build your own using classes.
You can read more about python data types here.