基本问题:获取数字列表,查找所有排列,过滤,再次过滤和求和。 这是我的第一个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脚本,任何非优化指针也将受到赞赏。 谢谢!
答案 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个小时。