BFS,想找到节点间的最长路径,减少findchildren-method
BFS, wanting to find the longest path between nodes, reducing the findchildren-method
我已经针对这个主题打开了另一个线程,但我认为我发布了太多代码并且我真的不知道我的问题出在哪里,现在我想我有一个更好的主意但仍然需要帮助.我们有一个 text-file 有 3 个字母的单词,只有 3 个字母的单词。我还有一个Word(节点)和queue-class。我的 findchildren-method 应该为一个词找到所有 children 这个词,假设我输入 "fan",然后我应该得到类似 ["kan","man"..等]。代码目前看起来像这样:
def findchildren(mangd,parent):
children=set()
lparent=list(parent)
mangd.remove(parent)
for word in mangd:
letters=list(word)
count=0
i=0
for a in letters:
if a==lparent[i]:
count+=1
i+=1
else:
i+=1
if count==2:
if word not in children:
children.add(word)
if i>2:
break
return children
上面的代码,对于 findchildren 目前工作正常,但是,当我将它用于我的其他方法(实现 bfs-search)时,一切都将花费太长时间,因此,我想将所有 children 收集到包含 children 列表的字典中。感觉这个任务现在不在我的能力范围内,但这可能吗?我试图创建这样的东西:
def findchildren2(mangd):
children=[]
for word in mangd:
lparent=list(word)
mangd.remove(word)
letters=list(word)
count=0
i=0
for a in letters:
if a==lparent[i]:
count+=1
i+=1
else:
i+=1
if count==2:
if word not in children:
children.append(word)
if i>2:
break
return children
我想我最后一次尝试完全是垃圾,我收到错误消息“使用迭代设置更改的大小”。
def findchildren3(mangd,parent):
children=defaultdict(list)
lparent=list(parent)
mangd.remove(parent)
for word in mangd:
letters=list(word)
count=0
i=0
for a in letters:
if a==lparent[i]:
count+=1
i+=1
else:
i+=1
if count==2:
children[0].append(word)
if i>2:
break
return children
有更有效的方法来做到这一点(下面是 O(n^2) 所以不是很好)但这里有一个简单的算法可以帮助您入门:
import itertools
from collections import defaultdict
words = ['abc', 'def', 'adf', 'adc', 'acf', 'dec']
bigrams = {k: {''.join(x) for x in itertools.permutations(k, 2)} for k in words}
result = defaultdict(list)
for k, v in bigrams.iteritems():
for word in words:
if k == word:
continue
if len(bigrams[k] & bigrams[word]):
result[k].append(word)
print result
生产:
defaultdict(<type 'list'>, {'abc': ['adc', 'acf'], 'acf': ['abc', 'adf', 'adc'], 'adf': ['def', 'adc', 'acf'], 'adc': ['abc', 'adf', 'acf', 'dec'], 'dec': ['def', 'adc'], 'def': ['adf', 'dec']})
这是一个带有一些注释的更有效的版本:
import itertools
from collections import defaultdict
words = ['abc', 'def', 'adf', 'adc', 'acf', 'dec']
# Build a map of {word: {bigrams}} i.e. {'abc': {'ab', 'ba', 'bc', 'cb', 'ac', 'ca'}}
bigramMap = {k: {''.join(x) for x in itertools.permutations(k, 2)} for k in words}
# 'Invert' the map so it is {bigram: {words}} i.e. {'ab': {'abc', 'bad'}, 'bc': {...}}
wordMap = defaultdict(set)
for word, bigramSet in bigramMap.iteritems():
for bigram in bigramSet:
wordMap[bigram].add(word)
# Create a final map of {word: {words}} i.e. {'abc': {'abc', 'bad'}, 'bad': {'abc', 'bad'}}
result = defaultdict(set)
for k, v in wordMap.iteritems():
for word in v:
result[word] |= v ^ {word}
# Display all 'childen' of each word from the original list
for word in words:
print "The 'children' of word {} are {}".format(word, result[word])
生产:
The 'children' of word abc are set(['acf', 'adc'])
The 'children' of word def are set(['adf', 'dec'])
The 'children' of word adf are set(['adc', 'def', 'acf'])
The 'children' of word adc are set(['adf', 'abc', 'dec', 'acf'])
The 'children' of word acf are set(['adf', 'abc', 'adc'])
The 'children' of word dec are set(['adc', 'def'])
Python 3 (运行 it here) 中更新要求的解决方案(遗憾的是 O(n^2)):
从集合导入 defaultdict
words = ['fan', 'ban', 'fbn', 'ana', 'and', 'ann']
def isChildOf(a, b):
return sum(map(lambda xy: xy[0] == xy[1], zip(a, b))) >= 2
result = defaultdict(set)
for word in words:
result[word] = {x for x in words if isChildOf(word, x) and x != word}
# Display all 'childen' of each word from the original list
for word in words:
print("The children of word {0} are {1}".format(word, result[word]))
产生:
The 'children' of word fan are set(['ban', 'fbn'])
The 'children' of word ban are set(['fan'])
The 'children' of word fbn are set(['fan'])
The 'children' of word ana are set(['and', 'ann'])
The 'children' of word and are set(['ann', 'ana'])
The 'children' of word ann are set(['and', 'ana'])
这里的算法很简单,效率不高,但让我试着分解一下。
isChildOf
函数将两个词作为输入并执行以下操作:
zip
的 a
和 b
在一起,这里两者都被视为可迭代对象,每个字符在迭代中都是一个 'item'。例如,如果 a
是 'fan'
并且 b
是 'ban'
那么 zip('fan', 'ban')
会生成这个列表 [('f', 'b'), ('a', 'a'), ('n', 'n')]
接下来它使用 map
函数将 lambda 函数(匿名函数的奇特名称)应用于列表中的 每个项目在第一步中产生。该函数只接受一对输入元素(即 'f'
& 'b'
)和 returns True
如果匹配,否则 False
。对于我们的示例,这将导致 [False, True, True]
,因为第一对字符不匹配,但其余两对都匹配。
最后,函数 运行 是第 2 步生成的列表中的 sum
函数。碰巧 True
的计算结果为 1
在 Python 和 False
到 0
中,因此我们列表的总和是 2
。然后我们简单地 return 该数字是否大于或等于 2
.
for word in words
循环简单地将每个输入词与所有其他词进行比较,并保留 isChildOf
计算结果为 True
的词,注意不要添加词本身。
我希望清楚!
我已经针对这个主题打开了另一个线程,但我认为我发布了太多代码并且我真的不知道我的问题出在哪里,现在我想我有一个更好的主意但仍然需要帮助.我们有一个 text-file 有 3 个字母的单词,只有 3 个字母的单词。我还有一个Word(节点)和queue-class。我的 findchildren-method 应该为一个词找到所有 children 这个词,假设我输入 "fan",然后我应该得到类似 ["kan","man"..等]。代码目前看起来像这样:
def findchildren(mangd,parent):
children=set()
lparent=list(parent)
mangd.remove(parent)
for word in mangd:
letters=list(word)
count=0
i=0
for a in letters:
if a==lparent[i]:
count+=1
i+=1
else:
i+=1
if count==2:
if word not in children:
children.add(word)
if i>2:
break
return children
上面的代码,对于 findchildren 目前工作正常,但是,当我将它用于我的其他方法(实现 bfs-search)时,一切都将花费太长时间,因此,我想将所有 children 收集到包含 children 列表的字典中。感觉这个任务现在不在我的能力范围内,但这可能吗?我试图创建这样的东西:
def findchildren2(mangd):
children=[]
for word in mangd:
lparent=list(word)
mangd.remove(word)
letters=list(word)
count=0
i=0
for a in letters:
if a==lparent[i]:
count+=1
i+=1
else:
i+=1
if count==2:
if word not in children:
children.append(word)
if i>2:
break
return children
我想我最后一次尝试完全是垃圾,我收到错误消息“使用迭代设置更改的大小”。
def findchildren3(mangd,parent):
children=defaultdict(list)
lparent=list(parent)
mangd.remove(parent)
for word in mangd:
letters=list(word)
count=0
i=0
for a in letters:
if a==lparent[i]:
count+=1
i+=1
else:
i+=1
if count==2:
children[0].append(word)
if i>2:
break
return children
有更有效的方法来做到这一点(下面是 O(n^2) 所以不是很好)但这里有一个简单的算法可以帮助您入门:
import itertools
from collections import defaultdict
words = ['abc', 'def', 'adf', 'adc', 'acf', 'dec']
bigrams = {k: {''.join(x) for x in itertools.permutations(k, 2)} for k in words}
result = defaultdict(list)
for k, v in bigrams.iteritems():
for word in words:
if k == word:
continue
if len(bigrams[k] & bigrams[word]):
result[k].append(word)
print result
生产:
defaultdict(<type 'list'>, {'abc': ['adc', 'acf'], 'acf': ['abc', 'adf', 'adc'], 'adf': ['def', 'adc', 'acf'], 'adc': ['abc', 'adf', 'acf', 'dec'], 'dec': ['def', 'adc'], 'def': ['adf', 'dec']})
这是一个带有一些注释的更有效的版本:
import itertools
from collections import defaultdict
words = ['abc', 'def', 'adf', 'adc', 'acf', 'dec']
# Build a map of {word: {bigrams}} i.e. {'abc': {'ab', 'ba', 'bc', 'cb', 'ac', 'ca'}}
bigramMap = {k: {''.join(x) for x in itertools.permutations(k, 2)} for k in words}
# 'Invert' the map so it is {bigram: {words}} i.e. {'ab': {'abc', 'bad'}, 'bc': {...}}
wordMap = defaultdict(set)
for word, bigramSet in bigramMap.iteritems():
for bigram in bigramSet:
wordMap[bigram].add(word)
# Create a final map of {word: {words}} i.e. {'abc': {'abc', 'bad'}, 'bad': {'abc', 'bad'}}
result = defaultdict(set)
for k, v in wordMap.iteritems():
for word in v:
result[word] |= v ^ {word}
# Display all 'childen' of each word from the original list
for word in words:
print "The 'children' of word {} are {}".format(word, result[word])
生产:
The 'children' of word abc are set(['acf', 'adc'])
The 'children' of word def are set(['adf', 'dec'])
The 'children' of word adf are set(['adc', 'def', 'acf'])
The 'children' of word adc are set(['adf', 'abc', 'dec', 'acf'])
The 'children' of word acf are set(['adf', 'abc', 'adc'])
The 'children' of word dec are set(['adc', 'def'])
Python 3 (运行 it here) 中更新要求的解决方案(遗憾的是 O(n^2)):
从集合导入 defaultdict
words = ['fan', 'ban', 'fbn', 'ana', 'and', 'ann']
def isChildOf(a, b):
return sum(map(lambda xy: xy[0] == xy[1], zip(a, b))) >= 2
result = defaultdict(set)
for word in words:
result[word] = {x for x in words if isChildOf(word, x) and x != word}
# Display all 'childen' of each word from the original list
for word in words:
print("The children of word {0} are {1}".format(word, result[word]))
产生:
The 'children' of word fan are set(['ban', 'fbn'])
The 'children' of word ban are set(['fan'])
The 'children' of word fbn are set(['fan'])
The 'children' of word ana are set(['and', 'ann'])
The 'children' of word and are set(['ann', 'ana'])
The 'children' of word ann are set(['and', 'ana'])
这里的算法很简单,效率不高,但让我试着分解一下。
isChildOf
函数将两个词作为输入并执行以下操作:
zip
的a
和b
在一起,这里两者都被视为可迭代对象,每个字符在迭代中都是一个 'item'。例如,如果a
是'fan'
并且b
是'ban'
那么zip('fan', 'ban')
会生成这个列表[('f', 'b'), ('a', 'a'), ('n', 'n')]
接下来它使用
map
函数将 lambda 函数(匿名函数的奇特名称)应用于列表中的 每个项目在第一步中产生。该函数只接受一对输入元素(即'f'
&'b'
)和 returnsTrue
如果匹配,否则False
。对于我们的示例,这将导致[False, True, True]
,因为第一对字符不匹配,但其余两对都匹配。最后,函数 运行 是第 2 步生成的列表中的
sum
函数。碰巧True
的计算结果为1
在 Python 和False
到0
中,因此我们列表的总和是2
。然后我们简单地 return 该数字是否大于或等于2
.
for word in words
循环简单地将每个输入词与所有其他词进行比较,并保留 isChildOf
计算结果为 True
的词,注意不要添加词本身。
我希望清楚!