简体   繁体   English

代表数独难题的正确数据结构?

[英]Proper data structure to represent a Sudoku puzzle?

What would be a smart data structure to use to represent a Sudoku puzzle? 用来表示数独难题的智能数据结构是什么? Ie a 9X9 square where each "cell" contains either a number or a blank. 即9X9正方形,其中每个“单元格”都包含数字或空格。

Special considerations include: 特殊注意事项包括:

  • Ability to compare across row, column, and in 3X3 "group 能够在行,列和“ 3X3”组中进行比较
  • Ease of implementation (specifically in Python) 易于实现(特别是在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. 我只是想知道是否有更好的数据结构。

Actually, I built such a beast, both a solver and a generator, and I used a 2D array. 实际上,我建造了这样的野兽,既是求解器又是生成器,并且我使用了2D阵列。 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: 首先,我编写了求解器部分,该部分首先将所有像元设置为可以是任意值,然后依次应用所有规则,以查看单个像元是否可以求解或受到其他限制,例如:

  • if the cell was a specific value in the clues, set it to that value. 如果单元格是线索中的特定值,请将其设置为该值。
  • if there's only one cell left in a row (or column or mini-square), you can set it to the remaining value. 如果一行(或列或迷你正方形)中只剩下一个单元格,则可以将其设置为剩余值。
  • if a cell is marked as being possibly N and N exists in its row/column/mini-square elsewhere, remove that possibility. 如果某个单元格被标记为可能为N并且在其行/列/迷你正方形中的其他地方存在N ,请删除该可能性。
  • if there are two cells in the row/column/mini-square and they have the same two possibilities (and no other possibilities), all other cells in that row/column/mini-square should have that possibility removed. 如果行/列/迷你正方形中有两个单元格,并且它们具有相同的两种可能性(并且没有其他可能性),则应删除该行/列/迷你正方形中的所有其他单元格。

And so on, adding each rule that I use in solving the real puzzles. 依此类推,添加我用来解决真正难题的每条规则。

For the generator, I started with: 对于生成器,我首先开始:

123 456 789
456 789 123
789 123 456

234 567 891
567 891 234
891 234 567

345 678 912
678 912 345
912 345 678

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. 然后,在大小不同(至少500个)的循环中,进行交换行和列的方式将永远不会产生无效的困惑。 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). 换句话说,将行或列与其所在的组交换(例如,第1、2和3行是一个组,第4、5和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. 而且,因此对Sudoku初学者而言,这不是一件痛苦的事情,我将允许他们指定较低的难度级别,从而将一定数量的不必要单元放回原处。

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 :-) 现在,如果我只能弄清楚这个角郎的东西,我会死得很开心:-)

Read Peter Norvig 's essay Solving Every Sudoku Puzzle . 阅读Peter Norvig的文章“ 解决每个数独难题” 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. 您不太可能找到更优雅的解决方案,并且可能会在此过程中学习有关数据结构,Python和性能分析的新知识。

Others have reasonably suggested simply using a 2D array. 其他人则合理地建议仅使用2D阵列。

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). 我注意到大多数语言实现中的2D数组(将其实现为“ X的数组”的任何东西都将遭受额外的访问时间开销(一次访问顶层数组,第二次访问子数组)。

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. 我建议您抽象地将数据结构实现为2D数组(也许甚至继续使用2个索引),但是将数组实现为81个单元格的单个块,经典地由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. 您应该能够将采用2D索引的setter和getter隐藏在1D数组访问后面。 If your language has the capability (dunno if this is true for Python), such small methods can be inlined for additional speed. 如果您的语言具有此功能(如果对Python来说是正确的话,请使用nono),则可以内联此类小型方法以提高速度。

Python doesn't have much in the way of data structures. Python没有太多的数据结构方式。 Your best bet is probably just a regular 2D array or to build your own using classes. 最好的选择可能只是常规2D数组,或者使用类来构建自己的2D数组。

You can read more about python data types here . 您可以在此处阅读有关python数据类型的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM