有人可以建议如何使用计算机程序解决Log Pile木制拼图吗?
点击此处查看拼图:http://www.puzzlethis.co.uk/products/madcow/the_log_pile.htm
图片仅显示部分内容。全套10件配置如下,其中1表示一个栓钉,-1表示一个孔,0表示既不是钉子也不是孔。
-1,1,0,-1,0
1,0,1,0,0
1,-1,1,0,0
-1,-1,0,0,-1
-1,1,0,1,0
0,1,0,0,1
1,0,1,0,-1
0,-1,0,1,0
0,0,1,1,-1
1,0,-1,0,0
这些碎片可以互锁成两层,每层5层,顶层与底层成90度,如上图所示。
我已经使用Java自己创建了这个问题的解决方案,但我觉得这是一个笨拙的解决方案,我有兴趣看到一些更复杂的解决方案。随意建议一般方法或以您选择的语言提供工作计划。
我的方法是使用上面的数字符号来创建“Logs”数组。然后我使用组合/置换生成器来尝试所有可能的Logs排列,直到找到所有交叉点等于零的解(即Peg to Hole,Hole to Peg或Blank to Blank)。我使用了一些加速来检测给定排列的第一个失败的交叉点,然后继续下一个排列。
我希望你觉得这和我一样有趣。
谢谢, 克雷格。
答案 0 :(得分:5)
此问题似乎是Boolean satisfiability problem的一种形式。如果是这样,最着名的方法就是蛮力。
但是有一些对称性,问题的一些属性可以让你减少你需要尝试的解决方案的数量。例如 -
答案 1 :(得分:1)
Prolog很受此类问题的欢迎。我在Prolog中设置了一些simpler puzzle problems相对不错的解决方案。
使用函数和回溯在Haskell中解决这些问题有非常优雅的方法。我的一个朋友解决了一个非常棘手的物理难题 - Puzzling Pets - 仅仅200多行Haskell,包括所有碎片和所有东西的描述。学习相关技巧的好方法是阅读John Hughes的论文Why Functional Programming Matters,安装Haskell Platform,然后尝试一下。
答案 2 :(得分:1)
根据Jay Elston的建议,我将使用以下伪代码实现它:
Read in the pieces
Annotate each piece with its number of pegs and holes
Generate all possible base layers (10 over 5 = 252, selecting 5 from the set),
so that sum(above, pegs) == sum(below, holes) and sum(below, pegs) == sum(above, holes)
For each base layer, (5! = 120 of them, permuting the 'below' pieces)
compute 'rotated pieces' for the base layer
if one-to-one match between top layer and rotated base-layer pieces,
report successful solution
对于给定的基础层,“旋转的部分”将是您需要覆盖它的理想部分。通过计算这些碎片并将它们与顶层碎片匹配,您可以使用O(N log N)排序来匹配旋转的碎片与真正的顶层,而不是匹配所有N!可能的顶层安排。另外,在第一次不匹配时,你可以提前纾困。
编写高效算法的关键是尽早修剪您的搜索,并利用任何对称性。例如,如果您认为拼图是对称的,则可以将运行时间缩短一半,因此您可以任意地将一个块分配给底层:然后您将只有9个超过4个基础层进行探索。
答案 3 :(得分:0)
我在javascript中有一个(麻烦!)解决方案,但是发布它有困难。使用的基本算法是: 从总共10个日志中查找5个日志的所有迭代,并且每组5个日志创建每次迭代,并且日志被反转。 对于这些状态中的每一个,我们将知道需要将哪种日志模式置于顶部。因此,我们确定是否能够将剩余的5个日志放在最上面。
这导致了解决方案的这种表示:
(Bottom, right-> left)
[0,0,1,-1,1],[-1,-1,0,0,-1],[0,0,1,0,1],[-1,1,0,-1,0],[1,0,-1,0,0]
(Top, up->down)
[0,1,0,1,-1],[0,1,0,-1,0],[-1,0,-1,0,1],[1,0,0,1,0],[-1,1,-1,0,0]
0 - flat
1 - dowel
-1 - hole