如何在不反复试验的情况下从逻辑上解决这个难题
Posted
技术标签:
【中文标题】如何在不反复试验的情况下从逻辑上解决这个难题【英文标题】:How to solve this puzzle logically without trial and error 【发布时间】:2012-03-20 05:10:18 【问题描述】:我在 Ubuntu 中遇到了 slant 谜题。 我想从逻辑上解决难题,而不是通过反复试验等方式。
规则很简单:
-
我们必须用右或左倾斜填充所有框。
与数字接触的斜线的数量必须等于该数字。
板上不允许有环路。即斜面不得形成环。
谜题:
自动解决答案:
我从哪里开始?
【问题讨论】:
@EAGER_STUDENT:我认为你的意思是this game?不能看一下源码看看他们是怎么解决的吗? @James:他们在源代码中所做的似乎很清楚:他们首先构建解决方案,因此他们不需要算法来解决它。 @EAGER_STUDENT:为什么回溯不合逻辑? @EAGER_STUDENT:数独可以在一定程度上完成设置,有时没有足够的信息可以继续进行,我认为需要一些回溯。然而,不喜欢某事并不会使它不合逻辑。大声笑 @EAGER_STUDENT,这个游戏也被称为“Gokigen Naname”,这个词更适合谷歌搜索。 【参考方案1】:我将使用斜杠 (/) 和反斜杠 (\) 代替左右倾斜。
让我们取一个角为 (x1)(11) 的正方形,其中 x 不等于 1。左上角有一个这样的正方形。假设那个正方形上的斜线是斜线,它连接两个 1。那些 1 已“用完”,所有接触它们的方格都必须有不接触数字的线。但这导致了不可能的情况,因为我们的正方形的左边和下面都会有一个斜线,这意味着剩下的 1 接触两个斜线。结论:如果您有一个带有三个 1 的正方形,那么该正方形中的线必须触及不是 1 的角。此规则可能不适用于边缘和角落,但如果角落中有 1,则必须绘制与该角落接触的线。
数字 1 和 3 是对称的,使用类似的逻辑,我们得到另一条规则:如果您有一个包含三个 3 的正方形,那么该正方形中的线必须接触这三个 3 中的两个。
有更一般的规则,但它们不适用于角落。有问题的正方形周围必须有正方形。让我们取一个两个相反的 1 (x1)(1y) 的正方形,其中 x 和 y 是任何东西,包括无数。离左下角有一个这样的两个正方形。假设那个正方形上的斜线是斜线,它连接两个 1。那些 1 已“用完”,所有接触它们的方格都必须有不接触数字的线。但这会导致围绕 1 循环。结论:如果您有一个带有两个相反 1 的方格,那么该方格中的线不得接触这两个 1 。此规则可能不适用于棋盘边缘。
数字 1 和 3 是对称的,但之前的规则采用“无环”规则,并且没有对称的“侧线无环”规则,因此没有两个相反的 3 的规则。
既然您知道哪条线与 1 接触,您就可以得出结论,没有其他线可以接触到它。我们可以将此推理概括为以下填充规则:如果一个数字 x 与 x 条线相接触,那么所有其他相邻方格都有不接触该数字的线。并且对称地:如果一个数字 x 是 (4-x) 个正方形的角,其中的线与该数字不相交,那么所有其他相邻的正方形必须有与该数字相交的线。
搜索“Gokigen Naname”这个词,我发现了更多规则。一个大约是两个相邻的 1 (11),但 Mweerden 已经覆盖了它。
这些规则不足以解决董事会。可能还有其他规则。但最终算法可能不得不做出猜测。
【讨论】:
我不相信在任何好的谜题中算法都必须做出猜测(基于合理数量的经验,游戏来自 Simon Tatham 的便携式谜题集合的版本 - chiark.greenend.org.uk/~sgtatham/puzzles/java/slant.html),但除此之外我同意。它的全部内容是找到为您提供信息的模式,然后将其添加进去,然后找到更多模式。如果您正在猜测,那么您还没有足够的模式。 :) 模式的数量可能如此之多,以至于猜测比拥有千兆字节的大型数据库要好。 你是对的,有时候只测试一条失败的路径可能是最好的,但我的直觉/经验表明情况并非如此。自从我上次玩以来已经太久了,所以我不记得我脑子里所有的规则都可以使用并放在这里。如果我不工作,我会开始玩来提醒自己。 ;-) 这个谜题在模式/猜测方面类似于数独。如果您存储了所有可能的子板,您就可以拥有一个无需猜测的模式数据库。由于这是不可行的,因此您存储了一个较小的模式数据库,并偶尔进行猜测。如果猜测导致不可能的情况,请返回并以不同的方式猜测。【参考方案2】:“逻辑上”是一个非常广泛的术语。正如 Orbling 在 cmets 中提到的,回溯可以被认为是合乎逻辑的。人们也可以将“逻辑上”理解为如何通过将其转换为逻辑公式来解决它。从我收集的 cmets 中,您正在尝试实现一个求解器,可能类似于常见的数独求解器。
实现求解器的一种简单方法(类似于数独中的求解器)是找到某些模式。对于你提到的程序产生的谜题,我可以有理由自信地说,这应该足以解决它们而无需猜测和回溯。
一些明显模式的例子是<11>
和>33<
。特别是 2 有一些很好的“传递”属性。例如:<12...23 -> <12...23<
(带有 2...2 任意数量的 2s)。在各种示例上尝试您的求解器,当它卡住时,我相信您已经找到了一个可以教给您另一种模式的示例。
【讨论】:
以上是关于如何在不反复试验的情况下从逻辑上解决这个难题的主要内容,如果未能解决你的问题,请参考以下文章