Python 检查矩阵中的某些元素是否具有内聚性

Python 检查矩阵中的某些元素是否具有内聚性,python,algorithm,Python,Algorithm,我必须编写一个非常小的Python程序来检查一些坐标组是否都连接在一起(通过一条直线,而不是对角线)。接下来的两张图片展示了我的意思。在左图中,所有颜色组都是内聚的,在右图中,不是: 我已经编写了这段代码,但它似乎不起作用,我被卡住了,关于如何修复它有什么想法吗 def cohesive(container): co = container.pop() container.add(co) return connected(co, container) def connect

我必须编写一个非常小的Python程序来检查一些坐标组是否都连接在一起(通过一条直线,而不是对角线)。接下来的两张图片展示了我的意思。在左图中,所有颜色组都是内聚的,在右图中,不是:

我已经编写了这段代码,但它似乎不起作用,我被卡住了,关于如何修复它有什么想法吗

def cohesive(container):
   co = container.pop()
   container.add(co)
   return connected(co, container)

def connected(co, container):
   done = {co}
   todo = set(container)
   while len(neighbours(co, container, done)) > 0 and len(todo) > 0:
       done = done.union(neighbours(co, container, done))
   return len(done) == len(container)

def neighbours(co, container, done):
   output = set()
   for i in range(-1, 2):
       if i != 0:
           if (co[0] + i, co[1]) in container and (co[0] + i, co[1]) not in done:
               output.add((co[0] + i, co[1]))
           if (co[0], co[1] + i) in container and (co[0], co[1] + i) not in done:
               output.add((co[0], co[1] + i))
   return output
这是一些参考资料,应该返回
True

cohesive({(1, 2), (1, 3), (2, 2), (0, 3), (0, 4)})
这应该返回
False

cohesive({(1, 2), (1, 4), (2, 2), (0, 3), (0, 4)})

这两种测试都能工作,但当我尝试用不同的数字测试时,函数会失败。

通常,要检查某些东西是否连接,需要使用不相交的集合数据结构,更有效的变化包括加权快速并集、加权快速并集和路径压缩

这是一个实现,您可以根据需要修改它。此外,A.Aho在《计算机算法的设计与分析》一书中的实现允许您指定添加2个连接元素的组的名称,因此我认为这是您正在寻找的修改(只需要使用1个额外的数组来跟踪组编号)

作为旁注,由于不相交集通常适用于数组,请不要忘记,可以将N×N矩阵表示为大小为N*N的数组

编辑:刚意识到我不清楚你一开始问的是什么,我意识到你还提到对角线分量没有连接,在这种情况下,算法如下所示:

0)检查所有元素是否引用同一组

1) 遍历表示相关矩阵中坐标的对数组

2) 对于每一对,制作一组满足以下公式的对:

|entry.x - otherEntry.x| + |entry.y - otherEntry.y|=1.
“entry”指的是外部for循环所指的元素

3) 检查所有集合是否重叠。这可以通过“联合”您正在查看的集合来实现,最后,如果您得到的集合超过1个,那么元素就没有内聚性

复杂度为O(n^2+n^2*log(n))

例如:

(0,4)、(1,2)、(1,4)、(2,2)、(2,3)

0)检查它们是否都在同一组中:

他们都属于第5组

1) 制作套装:

set1:(0,4),(1,4)

set2:(1,2),(2,2)

set3:(0,4),(1,4)//这里我们假设集合是排序的,而不是它 应该是(1,4),(0,4)

set4:(1,2),(2,2),(2,3)

set5:(2,2),(2,3)

2) 检查重叠:

set1与set3重叠,因此我们得到:

set1’:(0,4),(1,4)

set2与set4和SET5重叠,因此我们得到:

set2’:(1,2)、(2,2)、(2,3)

正如您所看到的,set1'和set2'不重叠,因此您得到了两个不相交的集合,它们位于同一组中,因此答案为“false”


请注意,这是低效的,但我不知道如何更有效地执行,但这回答了您的问题。

连接函数中的逻辑似乎是错误的。创建todo变量,但决不更改其内容。你总是在同一个起点附近寻找邻居

请尝试以下代码:

def connected(co, container):
   done = {co}
   todo = {co}
   while len(todo) > 0:
       co = todo.pop()
       n = neighbours(co, container, done)
       done = done.union(n)
       todo = todo.union(n)
   return len(done) == len(container)
todo
是我们仍要检查的所有点的集合


done
是一组我们发现的与起点4-连接的所有点。

我将以不同的方式解决这个问题。。。如果你要找五个,那就意味着:

  • 线中的每个坐标都必须与线中的另一个坐标相邻,因为小于此值意味着该坐标断开连接
  • 至少有三个坐标必须与线中的另外两个或更多坐标相邻,因为任何更少的坐标和组都将断开连接
  • 因此,您只需获取坐标的邻域并检查这两个条件是否都满足

    以下是一个基本解决方案:

    def cells_are_connected(connections):
        return all(c > 0 for c in connections)
    
    def groups_are_connected(connections):
        return len([1 for c in connections if c > 1]) > 2
    
    def cohesive(coordinates):
        connections = []
        for x, y in coordinates:
            neighbours = [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]
            connections.append(len([1 for n in neighbours if n in coordinates]))
        return cells_are_connected(connections) and groups_are_connected(connections)
    
    print cohesive([(1, 2), (1, 3), (2, 2), (0, 3), (0, 4)]) # True
    print cohesive([(1, 2), (1, 4), (2, 2), (0, 3), (0, 4)]) # False
    

    不需要通用案例解决方案或联合逻辑。:)请注意,这是一个特定于“五行合一”问题的问题。

    您可以在可能的情况下获取一个元素并附加其相邻元素

    def dist(A,B):return abs(A[0]-B[0]) + abs(A[1]-B[1])
    
    def grow(K,E):return {M for M in E for N in K if dist(M,N)<=1}
    
    def cohesive(E):
        K={min(E)} # an element 
        L=grow(K,E)
        while len(K)<len(L) : K,L=L,grow(L,E)
        return len(L)==len(E)
    

    为什么你不能检查所有的元素是否都有相同的颜色?甚至价值?或者“非对角部分”是不是意味着{(1,1),(2,2)}应该返回false?另外,您的示例查询有点向后,因为它们的意思是(y,x)而不是(x,y),非常不直观,但我只是说它们不是(y,x),而是(行,列)。这是一个矩阵,连标题都这么说。@StefanPochmann是的,我想我只是习惯了(x,y)。好问题,很好的图表。我建议直接使用。谢谢你的解释!这很有帮助!
    In [1]: cohesive({(1, 2), (1, 3), (2, 2), (0, 3), (0, 4)})
    Out[1]: True
    
    In [2]: cohesive({(1, 2), (1, 4), (2, 2), (0, 3), (0, 4)})
    Out[2]: False