【问题标题】:Check if a set of puzzle pieces is forms a valid puzzle检查一组拼图是否构成有效拼图
【发布时间】:2022-10-24 01:02:10
【问题描述】:

我有一组拼图(三角形和正方形),例如表格

{[1, 2, 3, 4], [2, 4, 5], [1, 3, 6]}

现在,我想检查这些部分是否可以放在一个网格上。

一个有效的布局例如是:

一组没有有效映射的谜题将是

{[1, 2, 3, 4], [2, 4, 5], [1, 5, 6]}

我的第一个 ansatz 是将所有数字放在拼图集合中(在上面的示例中,它将是 1、2、3、4、5、6)作为图中的节点,并根据拼图连接它们(如果连接发生多次,仅考虑一次)。 然后我检查结果图是否是平面的(这很便宜,它会随着边数的 2 次方缩放)。

然而,平面性仅对有效映射是必要的,但还不够,因为它没有考虑拼图必须形成正方形或三角形(没有拉伸或类似)。

所以我想到了一个禁止边缘的列表,通过循环一组谜题来附加它,但是,我被卡住了。是否有人有一个聪明的想法来回答这个问题:一组给定的谜题是否在网格上形成了一个有效的布局(最多在多项式时间内)。

集合的长度是任意的

编辑:对于诸如 [1, 2, 3, 4] 之类的拼图,四个数字必须形成一个正方形,并且这些数字在网格上出现的顺序无关紧要。这同样适用于三角形。因此,交换例如上图中的 2 和 4 仍然是有效的赋值

【问题讨论】:

  • 在我看来,棕色方块应该是 1,2,4,3(顺时针)或 1,3,42(逆时针)。当然,它永远不可能是 1,2,3,4,就像您在问题的第二行中所说的那样。
  • 它可以是 1、2、3、4 的任意排列
  • 你需要澄清你的问题。顶点标签的任何排列都非常令人困惑。请解释一下你的意思。
  • 您可以将 2 与 4 交换,两个拼图(红色和蓝色)仍然有效。也许我应该说拼图的顺序(或排列)不是先验确定的
  • 放松 - 我更新了我的问题

标签: python graph planar-graph


【解决方案1】:

我犹豫发布这个,因为它不完全满足您的要求,但也许这可以是一个开始。

这正如我在我的 cmets 中建议的那样,通过增加各个部分来构建一个大多边形。对于三角形,这很容易,但如果正方形的点不是按旋转顺序排列的,那么这将失败。您会看到我将矩形更改为 [1,2,4,3] 以使其通过。在这种情况下,您需要记住添加方格的位置,如果没有附上一块,请在翻转这些点后再次尝试。

def check(data):
    # Pick the first triangle to start our polygon
    poly = [p for p in data if len(p)==3][0]
    data.remove(poly)

    while data:
        undone = []
        for unit in data:
            print(poly)
            # How many sides are in common with our master polygon?

            common = [p for p in unit if p in poly]
            if len(common) > 2:
                # Impossible.
                return False
            if len(common) < 2:
                # Can't attach this one yet.
                undone.append( unit )
                continue

            # We extend the polygon by inserting the one or two new points
            # between the two known ones.

            # For a triangle, it's easy.  For a square, we can't know
            # the orientation of the other two sides.

            other = [p for p in unit if p not in poly]
            print(unit, common,other)
            for i in range(len(poly)-1):
                if poly[i] in common:
                    if poly[i+1] in common:
                        poly = poly[:i+1]+other+poly[i+1:]
                    elif i == 0 and poly[-1] in common:
                        poly.extend( other )
                    else:
                        return False
                    break
        if undone == data:
            return False
        data = undone
    print(poly)
    return True

data = [[1,2,4,3],[2,4,5],[1,3,6]]
print(check(data))
data = [[1,2,4,3],[2,4,5],[1,5,6]]
print(check(data))

【讨论】:

  • 感谢您的回答,不幸的是,我必须允许正方形旋转
  • 好吧,这不是“正方形的旋转”,而是点的顺序错误。我提到过。通过扫描对象列表,您可以通过检测一个对象何时加入具有非相邻点的正方形来找到错误排序。
【解决方案2】:

如果您只想知道是否存在可行映射(真或假结果)并且不关心其细节(将数字分配给网格),那么我认为一个好的起点是检查每一个以下列方式与其他所有棋子拼图。

如果两个部分的顶点集的交集大小为:

  • 0:那么碎片不相邻,继续检查,
  • 1:那么无法创建有效的映射,因为两个部分仅共享一个顶点而不是边(这只是我的假设,它是无效的),
  • 2:那么碎片是相邻的,边由两个顶点指定,继续检查,
  • 3:或更多,则无法创建有效映射,因为一个片段包含在另一个片段中。

上述方法可能就足够了,但它实际上取决于什么是布局被视为有效的正式标准。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多