Java 我怎样才能用计算机程序解决木桩难题?

Java 我怎样才能用计算机程序解决木桩难题?,java,algorithm,puzzle,Java,Algorithm,Puzzle,有人能建议如何使用计算机程序解决木桩难题吗 请参见此处以可视化该谜题: 这张照片只展示了其中的一部分。全套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度角,如上述链接所示 我已经用

有人能建议如何使用计算机程序解决木桩难题吗

请参见此处以可视化该谜题:

这张照片只展示了其中的一部分。全套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为这个问题创建了一个解决方案,但我觉得这是一个笨拙的解决方案,我有兴趣看到一些更复杂的解决方案。您可以随意建议一种通用方法,也可以用您选择的语言提供一个工作程序

我的方法是使用上面的数字符号来创建一个“日志”数组。然后,我使用组合/排列生成器尝试所有可能的原木排列,直到找到一个解决方案,其中所有交点都等于零(即桩到孔、孔到桩或空白到空白)。我使用了一些加速来检测给定排列的第一个失败交叉口,并继续下一个排列

我希望你觉得这和我一样有趣

谢谢,
Craig.

Prolog对于此类问题很受欢迎。我已经在Prolog中设置了一些相对不错的解决方案


在Haskell中有非常优雅的方法来解决这类问题,使用函数和回溯。我的一个朋友解决了一个非常令人烦恼的物理难题——用哈斯克尔的200多行文字,包括所有片段和一切的描述。学习相关技术的一个好方法是阅读约翰·休斯的论文,安装,然后试一下你的手。

这个问题似乎是。如果是的话,最著名的方法就是暴力

但是有一些对称性和问题的一些特性可以让你减少需要尝试的解决方案的数量。比如说--

  • 如果你把日志分成两部分 顶部和底部的5件式子集# 顶部的销钉需要与# 底部有洞,底部有#洞 顶部需要与中的#销钉匹配 底部和顶部需要的#平底鞋 匹配底部的#单位。如果 那么,这些钉子和孔是匹配的 平底鞋也会相配,所以你应该 不需要检查公寓
  • 你有10*9*8*7*6种方式 可以将日志分成两部分 5件式子集。(一旦你 为子集选择了前5个日志 顶部,剩余的日志在子集中 底部
  • 当您测试一个5件子集时,有5*8*6*4*2种方式可以排列一层日志。也就是说,在选择日志1后,剩下4条日志。对于第二条日志, 你可以从四个中挑选,有四个 它可以通过两种方式进行定向 关于第一个日志
  • 一旦你有了一个基本层,你可以试着从另一层一次适应每一个日志,直到你发现一个不适合。在这一点上,你放弃了当前的基本层日志安排,并尝试下一个

根据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个基本层可供探索。

(凌乱!)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  

谢谢诺曼,我来试试。我已经有一段时间没有做任何开场白了,但哈斯克尔听起来很有趣。很好的拼图。我喜欢那些在拿起时分开的。:->拼图很有趣:-)感谢您与我们分享这个谜题!感谢Jay的建议。我昨天确实回复了,但我的回复似乎没有正确发布。我将在接下来的几天晚上查看这个问题,并将发布消息让您了解我的进展情况。做得好tucuxi,感谢您花时间将Jay的建议转化为伪代码对我来说,这应该有助于我对它进行编码。我希望今晚或明天晚上尝试一下,并将公布结果。谢谢。这是一个有趣的问题-让我们看看结果如何。看起来与许多来自