Python 3.3.2-';分组';字符系统
我有一个有趣的小问题 我需要计算文件中字符的“组”数量。说文件是Python 3.3.2-';分组';字符系统,python,string,python-3.x,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),
..##.#..#
##..####.
.........
###.###..
##...#...
然后,代码将计算#组的数量。例如,上面是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.
我想出了一个天真的解决办法。最初我只想在所有元素之间循环一次,如果我可以将其放入现有的组中,则对每个元素进行检查。但是,这不起作用,因为某些组只是在稍后合并(例如,第二行中的第一个
在处理该行中的第二个
之前不会属于大组)。所以我开始研究一个合并算法,然后我想我可以从一开始就这样做
因此,我现在是如何将每个#
放入自己的组中的。然后我继续观察两组的组合,检查它们是否足够接近,是否属于同一组。如果是这样,我会合并它们并重新开始检查。如果我完全考虑了所有可能的组合,不能再合并了,我知道我已经完成了
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
来自itertools导入组合,产品
def可合并(g,h):
对于i,j in g:
对于h中的x,y:
如果abs(i-x)这里有一个简单的解决方案。最初我只想在所有元素之间循环一次,如果我可以将其放入现有的组中,则对每个元素进行检查。但是,这不起作用,因为某些组只是在稍后合并(例如,第二行中的第一个
在处理该行中的第二个
之前不会属于大组)。所以我开始研究一个合并算法,然后我想我可以从一开始就这样做
因此,我现在是如何将每个#
放入自己的组中的。然后我继续观察两组的组合,检查它们是否足够接近,是否属于同一组。如果是这样,我会合并它们并重新开始检查。如果我完全考虑了所有可能的组合,不能再合并了,我知道我已经完成了
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
来自itertools导入组合,产品
def可合并(g,h):
对于i,j in g:
对于h中的x,y:
如果abs(i-x)的话,我不确定你的代码要做什么。您的with
语句将打开一个文件,但您所做的只是在with
结束并关闭之前将文件对象附加到列表中(其内容从未被读取)。我怀疑他不是你想要的,但我不确定你的目的是什么
如果我正确理解了你的问题,那么你是在试图计算一张图的长度。在这种情况下,图形的顶点是“#”字符,边是这些字符在任何方向(水平、垂直或对角)彼此相邻的位置
解决这个问题有非常简单的算法。一种是使用数据结构(也称为“联合查找”结构,因为它支持的两种操作是union
和find
),将从文件读入的'#'
字符组连接在一起
这里有一个相当小的不相交集,我刚才写它来回答另一个问题:
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
元组处理节点:
nodes = set()
groups = UnionFind()
with open('file.txt') as f:
for y, line in enumerate(f): # iterate over lines
for x, char in enumerate(line): # and characters within a line
if char == '#':
nodes.add((x, y)) # maintain a set of node coordinates
# check for neighbors that have already been read
neighbors = [(x-1, y-1), # up-left
(x, y-1), # up
(x+1, y-1), # up-right
(x-1, y)] # left
for neighbor in neighbors:
if neighbor in nodes:
my_group = groups.find((x, y))
neighbor_group = groups.find(neighbor)
if my_group != neighbor_group:
groups.union(my_group, neighbor_group)
# finally, count the number of unique groups
number_of_groups = len(set(groups.find(n) for n in nodes))
我不太确定你的代码要做什么。您的with
语句将打开一个文件,但您所做的只是在with
结束并关闭之前将文件对象附加到列表中(其内容从未被读取)。我怀疑他不是你想要的,但我不确定你的目的是什么
如果我正确理解了你的问题,那么你是在试图计算一张图的长度。在这种情况下,图形的顶点是“#”字符,边是这些字符在任何方向(水平、垂直或对角)彼此相邻的位置
解决这个问题有非常简单的算法。一种是使用数据结构(也称为“联合查找”结构,因为它支持的两种操作是union
和find
),将从文件读入的'#'
字符组连接在一起
这里有一个相当小的不相交集,我刚才写它来回答另一个问题:
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
元组处理节点:
nodes = set()
groups = UnionFind()
with open('file.txt') as f:
for y, line in enumerate(f): # iterate over lines
for x, char in enumerate(line): # and characters within a line
if char == '#':
nodes.add((x, y)) # maintain a set of node coordinates
# check for neighbors that have already been read
neighbors = [(x-1, y-1), # up-left
(x, y-1), # up
(x+1, y-1), # up-right
(x-1, y)] # left
for neighbor in neighbors:
if neighbor in nodes:
my_group = groups.find((x, y))
neighbor_group = groups.find(neighbor)
if my_group != neighbor_group:
groups.union(my_group, neighbor_group)
# finally, count the number of unique groups
number_of_groups = len(set(groups.find(n) for n in nodes))
完美的它工作得很好。但是,有一次调整,您忘记在findGroups
中的while循环下放置返回组
。对,我在最后一刻才将其作为一个单独的函数^^^^^虽然这种蛮力方法适用于小字段,但对于较大字段可能会变得非常缓慢。我答案中的算法效率更高。@Blckknght因此我的“幼稚解决方案”警告:)我注意到了这一点。我用1000个使用定时器模块的测试用例轰炸了您的解决方案,但速度有点慢。否则,这是一个非常容易理解的解决方案!完美的它工作得很好。但是,有一次调整,您忘记在findGroups
中的while循环下放置返回组
。对,我在最后一刻才将其作为一个单独的函数^^^^^虽然这种蛮力方法适用于小字段,但对于较大字段可能会变得非常缓慢。我答案中的算法效率更高。@Blckknght因此我的“幼稚解决方案”警告:)我注意到了这一点。我用1000个使用定时器模块的测试用例轰炸了您的解决方案,但速度有点慢。否则,这是一个非常容易理解的解决方案!