我必须在Python程序中找到所有连接的细菌簇(4连接)。输入是一个如下所示的文件:
###
#####
#######
#######
######
###### ##
#### #####
## ###### ####
# ###### ####
### ########## #####
####### #### ## ######
######### ## # #####
# #### ### ###
##### #### # ## ##
##### ###### #
###### ########
#### ########
#######
#######
注意:无法计算与网格边缘相邻的群集
此文件以类的形式保存在我的班级中。我写了这个函数来查找所有集群,但它创建了许多集群(22而不是5)。知道我可能做错了吗?
我的代码:
def findAll(self):
self.colonies = [set()]
for i in range(len(self.grid)):
for j in range(len(self.grid[i])):
if self.grid[i][j] == "#":
added = False
count = 0
for k in self.colonies:
if self.checkNeighbours((i, j), k):
k.add((i, j))
added = True
count += 1
if not added:
self.colonies.append({(i, j)})
def checkNeighbours(self, pos, current):
return ((pos[0] + 1, pos[1]) in current
or (pos[0] - 1, pos[1]) in current
or (pos[0], pos[1] + 1) in current
or (pos[0], pos[1] - 1) in current)
答案 0 :(得分:3)
你遇到的问题是,从你组成两个集群的那一刻起,你就无法加入它们。即使最终这两个集群意味着通过添加中间节点而加入。
这可以通过应用union-find data structure来解决。一个未经优化的python版本是:
s = """\
### \
##### \
####### \
####### \
###### \
###### ## \
#### ##### \
## ###### ####\
# ###### #### \
### ########## ##### \
####### #### ## ###### \
######### ## # ##### \
# #### ### ### \
##### #### # ## ## \
##### ###### # \
###### ######## \
#### ######## \
####### \
####### \
"""
representatives = {i: i for i, c in enumerate(s) if c == '#'}
nrows, ncols = 19, 44
def neighbours(idx):
i, j = divmod(idx, ncols)
if i > 0: yield idx - ncols
if i < nrows - 1: yield idx + ncols
if j > 0: yield idx - 1
if j < ncols - 1: yield idx + 1
def representative(a):
while representatives[a] != a: a = representatives[a]
return a
def join(a, b):
repr_a, repr_b = representative(a), representative(b)
if repr_a != repr_b: representatives[repr_a] = repr_b
for idx in representatives:
for n in neighbours(idx):
if s[n] == '#': join(idx, n)
cluster_count = len(set(map(representative, representatives)))
结果:
6
您还可以创建图表并使用depth first search查找已连接的组件。上述方法的优点是它是增量的,您可以通过添加新点轻松更新集群。
答案 1 :(得分:3)
使用scipy ndimage measurements模块可轻松检测功能。如果你这样做,它还有速度的附加优势。
import numpy as np
from scipy.ndimage.measurements import label, find_objects
q = np.genfromtxt('bacteria.txt', dtype='S1', comments=':', delimiter=1)
arr = (q == b'#') # convert to boolean mask because ' ' evaluates to True
labelled, num_features = label(arr)
def count_edge_objects(labelled):
hulls = find_objects(labelled)
nbr_edgeobjects = 0
for rowslice, colslice in hulls:
if (rowslice.start == 0 or rowslice.stop == labelled.shape[0] or
colslice.start == 0 or colslice.stop == labelled.shape[1]):
nbr_edgeobjects += 1
return nbr_edgeobjects
print('{} objects'.format(num_features - count_edge_objects(labelled)))
# output:
# 4 objects
在您显示的数据集中,边缘附近有两个对象:顶部的一个和底部的一个。注意我目前假设数据集在每一行上都有相同数量的字符(如果没有,请查看missing_values
的{{1}}选项)