从元组优化的元组迭代

时间:2014-12-03 00:15:48

标签: python python-2.7 tuples

基本问题:获取数字列表,查找所有排列,过滤,再次过滤和求和。 这是我的第一个python脚本,所以经过一些研究后我决定使用itertools.permutations。然后我遍历元组,并创建一个新的元组元组,只有我想要的元组。然后我连接元组,因为我希望排列为数字,而不是断字符串。 然后我再做一次过滤并将它们加在一起。

对于8位数字,这花了我大约2.5秒,如果我想扩展到15位数(我的目标)太慢。 (我决定使用元组,因为排列列表对于内存来说太大了)

编辑:我意识到我并不关心排列的总和,而只关心计数。如果去发电机路径,我怎么能包括一个计数器而不是总和呢? 使用[非常]略有改进的快捷方式更新了我的原始代码,不仅仅是在我真正了解它们之前复制面食建议的答案。

import itertools

digits= [0,1,2,3,4,5,6,7]
digital=(itertools.permutations(digits))


mytuple=()
for i in digital:
    q=''
    j=list(i)
    if j[0] != 0:
        for k in range(len(j)):
            q=q+str(j[k])

        mytuple=mytuple+(q,)

#print mytuple

z = [i for i in mytuple if i%7==0]

print len(z)

这是我的第一个python脚本,任何非优化指针也将受到赞赏。 谢谢!

3 个答案:

答案 0 :(得分:2)

“发电机理解”是你的朋友。尤其是因为“生成器”一次只能在一个元素上运行,帮助您节省内存。此外,通过预先计算10的相关幂并执行整数运算而不是转换为字符串和从字符串转换,可以节省一些时间:

import itertools

digits = [0,1,2,3,4,5,6,7,8,9]
oom = [ 10 ** i for i, digit in enumerate( digits ) ][ ::-1 ] # orders of magnitude
allperm = itertools.permutations( digits )

firstpass = ( sum( a * b for a, b in zip( perm, oom ) ) for perm in allperm if perm[ 0 ] )

print sum( i for i in firstpass if i % 7 == 0 )

这比一个大因素更快,但排列的因子性质意味着15个数字仍然很长一段距离。 len(digits)==8为0.05,len(digits)==9为0.5,len(digits)==10为9.3。

由于您在基数10工作,digits长度> 10的序列将包含重复,从而导致在排列集中重复。如果重复不应单独计算,那么您的策略将需要改变(例如,如果问题被表述为“7个多数的15位数乘以下列数字的数量......”)。

答案 1 :(得分:1)

使用itertools是一个不错的选择。好好调查。

我试图改进@jez的漂亮解决方案。我重新安排了range,将zip替换为izip并将查找缓存在局部变量中。

N = 10
gr = xrange(N-1,-1,-1)
ap = itertools.permutations(gr)
o = [10 ** i for i in gr]
zip = itertools.izip
print sum(i for i in (sum(a*b for a, b in zip(p, o)) for p in ap if p[0]) if i % 7 == 0)

对我来说,N = 9时快17%,N = 10时快7%。对于较大的N,速度改善可以忽略不计,但未经测试。

答案 2 :(得分:0)

你错过了许多python中的捷径。试试这个:

import itertools

digits= [0,1,2,3,4,5,6,7]
digital=(itertools.permutations(digits))

mytuple=set()
for i in digital:
    if i[0] != 0:
        mytuple.add(int(''.join(str(d) for d in i)))

z = [i for i in mytuple if i%7==0]

print sum(z)

虽然可能难以达到15位数。 15!是1.3万亿......如果你每秒可以处理1000万个排列,那么它仍然需要36个小时。