Python 3.3.2 - 使用字符“分组”系统

时间:2013-09-02 08:27:18

标签: python string python-3.x

我有一个有趣的小问题。

我需要计算文件中字符的“组”数量。说文件是......

..##.#..#
##..####.
.........
###.###..
##...#...

然后代码将计算#的组数量。例如,上面的内容为3。它包括对角线。到目前为止,这是我的代码:

build = []
height = 0
with open('file.txt') as i:
  build.append(i)
  height += 1
length = len(build[0])
dirs = {'up':(-1, 0), 'down':(1, 0), 'left':(0, -1), 'right':(0, 1), 'upleft':(-1, -1), 'upright':(-1, 1), 'downleft':(1, -1), 'downright':(1, 1)}

def find_patches(grid, length):
  queue = []
  queue.append((0, 0))
  patches = 0
  while queue:
    current = queue.pop(0)
    line, cell = path[-1]
    if ## This is where I am at. I was making a pathfinding system.

2 个答案:

答案 0 :(得分:1)

这是我提出的一个天真的解决方案。最初我只想检查每个元素,如果我可以将它放入现有组中,我只想循环遍历所有元素。然而,这不起作用,因为某些组仅在稍后组合(例如,第二行中的第一个#将不属于大组,直到处理该行中的第二个#为止。所以我开始研究合并算法,然后发现我可以从一开始就这样做。

所以现在的工作方式是我将每个#放入自己的组中。然后我继续查看两组的组合,检查它们是否足够接近它们属于同一组。如果是这种情况,我合并它们并重新启动检查。如果我完全看了所有可能的组合而又无法合并,我知道我已经完成了。

from itertools import combinations, product
def canMerge (g, h):
    for i, j in g:
        for x, y in h:
            if abs(i - x) <= 1 and abs(j - y) <= 1:
                return True
    return False

def findGroups (field):
    # initialize one-element groups
    groups = [[(i, j)] for i, j in product(range(len(field)), range(len(field[0]))) if field[i][j] == '#']

    # keep joining until no more joins can be executed
    merged = True
    while merged:
        merged = False
        for g, h in combinations(groups, 2):
            if canMerge(g, h):
                g.extend(h)
                groups.remove(h)
                merged = True
                break

    return groups

# intialize field
field = '''\
..##.#..#
##..####.
.........
###.###..
##...#...'''.splitlines()
groups = findGroups(field)

print(len(groups)) # 3

答案 1 :(得分:0)

我不确定您的代码尝试做什么。您的with语句会打开一个文件,但您所做的就是在with结束之前将文件对象附加到列表中并将其关闭(不会读取其内容)。我怀疑他不是你想要的,但我不确定你的目标是什么。

如果我正确理解您的问题,您就会尝试计算图表的connected components。在这种情况下,图形的顶点是'#'字符,边缘是这些字符在任何方向(水平,垂直或对角)彼此相邻的任何地方。

有很简单的算法可以解决这个问题。一种是使用disjoint set数据结构(也称为“union-find”结构,因为unionfind是它支持的两个操作)来连接{{1当它们从文件中读入时,它们在一起。

这是我之前写的另一个问题的相当小的不相交集:

'#'

以下是如何使用class UnionFind: def __init__(self): self.rank = {} self.parent = {} def find(self, element): if element not in self.parent: # leader elements are not in `parent` dict return element leader = self.find(self.parent[element]) # search recursively self.parent[element] = leader # compress path by saving leader as parent return leader def union(self, leader1, leader2): rank1 = self.rank.get(leader1,1) rank2 = self.rank.get(leader2,1) if rank1 > rank2: # union by rank self.parent[leader2] = leader1 elif rank2 > rank1: self.parent[leader1] = leader2 else: # ranks are equal self.parent[leader2] = leader1 # favor leader1 arbitrarily self.rank[leader1] = rank1+1 # increment rank 元组为节点使用它来解决问题:

x, y