适当的数据结构代表数独谜题?

时间:2010-11-01 01:16:02

标签: python data-structures graph sudoku

用于表示数独谜题的智能数据结构是什么?即9X9平方,其中每个“单元格”包含数字或空白。

特别考虑因素包括:

  • 能够跨行,列和3X3“组
  • 进行比较
  • 易于实施(特别是在Python中)
  • 效率(不是最重要的)

我认为,在一个紧要关头,2D阵列可能会起作用,但这似乎不是一个优雅的解决方案。我只是想知道是否有更好的数据结构。

4 个答案:

答案 0 :(得分:10)

实际上,我构建了这样一个野兽,无论是解算器还是生成器,我都使用了2D数组。它运作良好。

您只需了解索引及其位置,并且不难掌握。

一行中单元格之间的相对关系不会因列而异,对于列中的单元格也是如此,甚至是小方块中的单元格。

有时候,一个不那么“优雅”的解决方案就好了。实际上,有时候,最好是: - )


对于它的价值,您可能对我用于求解器/生成器的算法感兴趣。

首先我编写了求解器部分,它首先将所有单元格设置为能够为任何值,然后按顺序应用所有规则以查看单个单元格是否可以被解决或以其他方式限制,例如:

  • 如果单元格是线索中的特定值,请将其设置为该值。
  • 如果一行(或列或迷你方格)中只剩下一个单元格,则可以将其设置为剩余值。
  • 如果某个单元格被标记为可能N且其行/列/小方块中存在N,请删除该可能性。
  • 如果行/列/迷你方块中有两个单元格并且它们具有相同的两种可能性(并且没有其他可能性),则该行/列/迷你方块中的所有其他单元格应该删除该可能性。 / LI>

依此类推,添加我用于解决真实谜题的每条规则。

对于发电机,我从:

开始
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

然后,在不同大小的循环(至少500)中,继续交换行和列,使其永远不会产生无效的拼图。换句话说,将行或列与它们所在的组交换(例如,第1,2和3行是一个组,第4,5和6列也是如此)。

这足以让细胞足够好,以产生一个像样的谜题。

然后,我开始选择随机单元格并将其设置为未知。一旦将一个单元格设置为未知,我就会将整个拼图传递给解算器。如果它是可以解决的,我会继续,否则我会重新启动细胞并继续。

这使我无法获得逻辑上无法解决的谜题。

一旦完成了大量的随机单元删除,我将尝试使用相同的方法按顺序删除所有剩余的单元格。剩下的就是解决难题所需的最少信息量。

而且,对于数独初学者来说,这不是一个痛苦,我会允许他们指定一个较低的难度级别,这将使一定数量的不必要的单元格重新进入。

不是一个糟糕的计划,可能会有更好的计划但是那个对我来说很好。

现在,如果我只能弄清楚这个Kakuro的东西,我会很高兴: - )

答案 1 :(得分:7)

阅读Peter Norvig的文章Solving Every Sudoku Puzzle。您不太可能找到更优雅的解决方案,您可能会在此过程中学习有关数据结构,Python和性能分析的一些新内容。

答案 2 :(得分:2)

其他人已经合理地建议简单地使用2D数组。

我注意到大多数语言实现中的2D数组(其中实现为“X数组的数组”的任何内容都会受到额外的访问时间开销的影响(一次访问顶级数组,一次访问子数组)。

我建议你抽象地将数据结构实现为2D数组(甚至可能继续使用2个索引),但是将数组实现为81个单元的单个块,通过i * 9 + j进行经典索引。通过避免第二次内存访问,这为您提供了概念清晰度和更高效的实现。

您应该能够隐藏采用2D索引的setter和getter背后的1D数组访问。如果您的语言具有该功能(如果Python适用,则为dunno),可以内联这些小方法以获得更高的速度。

答案 3 :(得分:0)

Python没有太多的数据结构。你最好的选择可能只是一个普通的2D数组或者使用类来构建你自己的。

您可以阅读有关python数据类型here的更多信息。