我已经在线发现了一些在Python中生成紊乱的算法但它们在复杂性方面都是指数级的,因此我不能让它们与一组26个元素(字母表)汇合!
所以我试图找到一种方法来改进以下代码(来源here):
def derangement(vs):
l = [None for x in vs]
sol = set()
sol.add(tuple(l))
for v in vs:
sol1 = set()
for s in sol:
for (i, v1) in enumerate(s):
if not v1 and v != vs[i]:
s1 = list(s)
s1[i] = v
sol1.add(tuple(s1))
sol = sol1
return list(sol)
如果有人好奇,这是一个强力替代密码求解器。我试图看看强制破解密码需要多长时间!
答案 0 :(得分:5)
由于置换算法是Ω(n!),所以没有什么能使你的代码收敛。这可能会更快,但这对于那种复杂性的事情毫无意义:
import itertools
def derangement(x):
p = itertools.permutations(x)
return (i for i in p if not any(i[k] == x[k] for k in range(len(x))))
这是一个懒惰的迭代器。如果您需要所有值(我怀疑您需要),只需list()
答案 1 :(得分:1)
不一定,这取决于您使用的密码。如果你使用凯撒密码,我相信你不是,你只需要尝试全部26个!排列,然后找到一个*('s)与真实的单词,但我很确定你的意思是vigenere cypher在这种情况下你采取所有的第一组排列,你把那些排列在类似的派系的行中,找到那些排列,然后交叉检查字典单词,然后你可能得到一个很长的可能的消息列表,你必须排序那些有意义的。
答案 2 :(得分:0)
只需注意一下26个项目的错位数量是多少:使用SymPy,可以将26个项目的错位数量计算为26的子因子(!26)
>>> subfactorial(26)
148362637348470135821287825
>>> round(log(_,2))
87
因此,大约2^87
个字母的排列是可能的。有一些用于计算随机排列的例程here和一种生成连续排列而不将它们全部存储在内存中的方法,就像上面最初问题中引用的例程一样。