【问题标题】:Empty crossword solver in PythonPython中的空填字游戏求解器
【发布时间】:2019-05-29 23:52:46
【问题描述】:

我得到了一个包含填字游戏蓝图的矩阵 - 当然是未填充的。我们的目标是填补整个谜题 - 这是 Checkio 的一项任务,我已经为此苦苦挣扎了很长一段时间。

根据我对复杂性的理解,对于这个问题没有完美的算法。不过,必须有最好的方法来做到这一点,对吧?我尝试了一些不同的方法,但随着填字游戏和/或字典中单词数量的增加,结果并不是那么好。

所以,我尝试过的一些事情:

  • 简单的暴力破解。根本不起作用,因为它一直在忽略 并覆盖交叉路口。
  • 暴力破解,同时保留所有相关数据 - 使用特定字典按预期工作,用 即使进行了字长优化,也适中。数字。
  • 盲区填充 - 我认为最好不要打扰相交的单词,而是集中注意力的想法 在字母上。喜欢以 As 开头并检查是否可以填写 具有这些限制的整个填字游戏。如果它对某些人不起作用 单词,增加一个字母,然后再试一次。 如您所料,结果很糟糕。
  • 递归探索 - 在更简单的蓝图上完美运行,但在更复杂的蓝图上表现平平。简单的有问题 简单地解决了循环,但我没有找到 路径分裂然后的情况的合理解决方案 稍后重新加入几个进一步的分裂(所以没有什么可以 解决第二个分支,但它不知道)。
  • 最小化交叉口 - 尚未对此进行测试,但看起来很有希望。这个想法是我找到最短的单词列表 包含所有交叉点......也不与每个交叉点相交 其他。然后我可以为每个单词使用一个生成器,然后 然后检查是否存在具有这些交叉点的​​依赖词。如果 他们没有,我只是从生成器中获取下一个单词。

这就是我目前所处的位置。我决定在这里问这个问题,因为它已经到了我认为花费的时间比应有的时间更多的时候,即使这样,我的最新想法甚至可能都不是正确的方法。

那么, 正确的做法是什么?

编辑: 输入是表示填字游戏的字符串列表和表示字典的字符串列表。输出是代表填好的填字游戏的字符串列表。

填字游戏示例:

['...XXXXXX', 
 '.XXX.X...', 
 '.....X.XX', 
 'XXXX.X...', 
 'XX...X.XX', 
 'XX.XXX.X.', 
 'X......X.', 
 'XX.X.XXX.', 
 'XXXX.....']

输出将是一个类似的列表,其中包含填充字母而不是点。

请注意,“词典”只是一本小型英语词典,而不是适合作为该谜题答案的单词列表。

【问题讨论】:

  • 谢谢你的描述,你能不能再添加一个拼图示例?此外,我不确定我是否完全明白了。你有一个填字游戏,你有一个填满这个谜题的单词列表,你是否在寻找应该放置它们的位置?还是我完全错了? ^^
  • "(...) 没有最佳解决方案 (...) 必须有最好的方法来做到这一点,对吧? “最优解”的定义。可能不存在的是“好的算法”,被理解为具有多项式最坏情况复杂度的算法。在任何情况下,您都没有正确描述您的问题(输入、预期输出、示例......)。
  • 谢谢你的例子,但我只是看不到上面的交集。抱歉,我仍然没有看到填字游戏。
  • 请稍等,我将对该输入进行可视化表示。
  • 为了减少耗时的过程,您可以尝试通过查看英文字母的重新分区来改进您选择单词的方式。哪些字母用得最多?最常见的第一个字母有哪些?最后一封信?通过改进单词选择,您将减少错误,然后更快地解决问题。

标签: python python-3.x algorithm crossword


【解决方案1】:

那么,正确的做法是什么?

我不知道它是否是最优的,但我会使用Floodfill 的原则。

数据结构:

填字游戏单词及其交叉点。按字典中对应词长的词数对它们进行排序。这很可能意味着您将从最长的单词之一开始。

按字长访问的字典。

如果字典很大,能够快速找到具有特定n:th 字母的特定长度的单词将是有益的,其中n 对应于交叉位置。

请注意,对于每个填字游戏单词,任何两个适合并且在所有交叉点中具有相同字母的单词都是等效的。因此,可以从字典中为每个填字游戏词选择一个子集。子集是等价类的集合。因此,对于每个填字游戏单词,您可以创建一个字典子集,其中最多包含 [字母表中字母的数量] 到 [交叉点的数量] 的幂。该子集将构成可能适合特定填字游戏的等价类。

算法:

  • 获取第一个/下一个未解决的填字游戏。分配它的第一个/下一个 合适的词。

  • 走第一个/下一个路口。将另一个填字游戏单词分配给第一个适合的单词。

  • 如果没有更多的十字路口可以继续前进,请返回您来自的十字路口并继续下一个十字路口。
  • 如果字典中没有合适的词,则回溯一个交叉点并搜索下一个合适的词。

【讨论】:

  • 如果字典有点太大的话会很长。
  • @Mathieu 会的。但请注意,字典可以缩小为等价类。如果您需要一个带有一个交集的n 字母单词,那么只有 26 个等价类,一个对应于交集中每个可能的字母。我会把它添加到解决方案中!
  • 我看到这种方法的问题是它的起点非常脆弱。例如,如果初始单词有 3 个单独的分支,并且您要逐个填充它们,当您到达第三个分支时,如果没有可用的单词符合条件,则必须更改该初始单词并重做所有内容。这实际上让我尝试了上面提到的递归探索——它的整个想法围绕着尽可能长时间地画一条直线,所以如果匹配中发生任何错误,你可以立即修复它——它不会影响之前的匹配。
  • @Lainesius 当你的方法失败时,你可能不得不回溯很长一段时间。如果您做出了最终失败的选择,那么您希望尽快失败。所以你应该从一个填字游戏开始,它有很多失败的方式和几个匹配的单词..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多