代码之家  ›  专栏  ›  技术社区  ›  Yuval Adam

为“驱动你的坚果”拼图生成所有独特的组合

  •  4
  • Yuval Adam  · 技术社区  · 14 年前

    不久前,我编写了一个简单的python程序,用于暴力破解drive-ya nuts难题的单一解决方案。

    alt text http://www.tabbykat.com/Drive%20ya%20Nuts%20Travel%20Sol%20c.jpg

    拼图由7个六边形组成,每个六边形上的数字为1-6,所有的棋子必须对齐,以便每个数字与下一个棋子上的相同数字相邻。

    谜题有 ~1.4G 非独特的可能性:你有 7! 按顺序排序的选项(例如, center=0 , top=1 ,按顺时针顺序继续…)。在你把这些零件分类后,你可以用6种方式旋转每一个零件(每个零件都是六边形),这样你就可以得到 6**7 7个部分的给定排列的可能旋转。总数: 7!*(6**7)=~1.4G 可能性。下面的python代码生成了这些可能的解决方案:

    def rotations(p):
        for i in range(len(p)):
            yield p[i:] + p[:i]
    
    def permutations(l):
        if len(l)<=1:
            yield l
        else:
            for perm in permutations(l[1:]):
                for i in range(len(perm)+1):
                    yield perm[:i] + l[0:1] + perm[i:]
    
    def constructs(l):
        for p in permutations(l):
            for c in product(*(rotations(x) for x in p)):
                yield c
    

    但是,请注意,这个难题只有 ~0.2G 独特的 可能的解决方案,因为您必须将总的可能性数除以6,因为每个可能的解决方案等于其他5个解决方案(只需将整个难题旋转1/6圈)。

    有更好的方法产生 只有独特的可能性 为了这个拼图?

    3 回复  |  直到 13 年前
        1
  •  5
  •   Daniel Stutzbach Edward Leno    14 年前

    要获得唯一有效的解决方案,可以在中心固定工件的方向。例如,您可以假设中心的工件上的“1”始终指向“上”。

    如果您还没有这样做,您可以通过在放置每个工件后检查有效的解决方案来提高程序的效率。一旦您以无效的方式放置了两个片段,就不需要枚举所有其他无效的组合。

        2
  •  3
  •   Thomas    14 年前

    如果中间没有碎片,这就很容易了。只需考虑以下情况: 0 在顶部。

    但我们可以把这个想法扩展到实际情况。你只能考虑以下情况 i 在中间,并且碎片 (i+1) % 7 在顶部。

        3
  •  1
  •   dmuir    14 年前

    我认为搜索空间很小,尽管编程可能会很尴尬。

    我们有七种选择作为中心。那么我们有6种选择 上面的部分,但它的方向是固定的,因为它的底边必须与中心部分的顶边匹配,同样地,当我们选择一个部分进入槽中时,方向是固定的。

    剩下的部分选择较少。假设 例如,我们选择了中间部分和顶部部分,如图所示;然后 右上角件必须具有(顺时针)连续边缘(5,3),以匹配 位置,而且只有三件物品有这样的边缘(事实上,我们已经 选择其中一个作为中心部件)。

    可以先用一个列表构建一个表 每个边缘对的件数,然后为中间和顶部的42个选项中的每一个选择 顺时针进行,仅在具有所需边对的工件中进行选择(以匹配中心工件和先前放置的工件),如果没有这样的工件,则进行回溯。

    我估计最常见的一对边是(1,6),它出现在4片上,另外两对边((6,5)和(5,3))出现在3片上,有9对边出现在2片上,14 发生在1件和4件上,根本不发生。 所以对我们必须做出的选择数量的一个非常悲观的估计是 7*6*4*3*3*2或3024。