Python FreshMan

★☆ Python新手的Blog ☆★
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

学习Python列表内涵:一行代码搞定双倍超立方数计算

Posted on 2010-02-23 16:20  闫小勇  阅读(5566)  评论(2编辑  收藏  举报

今天学习了Python的列表内涵(List comprehension,也有译为列表推导式的),对这个东西有点着了魔。正好看到了园子里木野狐用Python求解双倍超立方数计算的文章(也玩有道难题的双立方数问题:Python 版解法),就跟着学了做了一个。

这道题目的要求是:双倍超立方数是指一个正整数可以正好被拆分为两种不同的a^3+b^3的方式,其中a,b均为整数且0<a<=b。对于任何一个指定的 int n, 返回所有的小于等于n的双倍超立方数的个数

 

我解题的算法思路是和木野狐以及yujiasw的《有道难题的双立方数问题的高速解法》学的,不过这个Python代码为了减少行数,有很多地方没有优化,效率不高(装B害死人啊)。

 

二话不说,上代码先:

print len([1 for a in [x+y for x,y in [(k,j) for k in [i**3 for i in xrange(int(round(pow(100000, 1./3))))] for j in [i**3 for i in xrange(int(round(pow(100000, 1./3))))] if k <= j]] if [x+y for x,y in [(k,j) for k in [i**3 for i in xrange(int(round(pow(100000, 1./3))))] for j in [i**3 for i in xrange(int(round(pow(100000, 1./3))))] if k <= j]].count(a)==2])/2

 

 

看看,是一行吧!这一行代码的功能就是把100000之内符合以上要求的数字个数打印出来。运行一下,结果肯定是对的(不信你试一下,建议把100000改为10000)。不过我估计能读懂这行代码的地球人不多啊。我10分钟前写好的,现在自己也读不懂了  囧!   (我是先写好每层循环,然后一层一层套成了一个List comprehension)。

 

写以上代码是为了说明Python不仅可以把复杂问题简单化,也能把简单问题复杂化:)。

下边这个版本就易读多了:

 

#coding: utf-8

n
= 10000 #计算的最大数上限n
cubes = [i**3 for i in xrange(int(round(pow(n, 1./3))))] #产生小于n的所有立方数
sum = [x+y for x,y in #将立方数二元组相加,得到所有超立方数
[(k,j) #得到所有立方数两两组成的二元组
for k in cubes #外层循环
for j in cubes #内层循环
if k <= j #此处没有优化,共循环了k^2次,实际上有k(k+1)/2次就够了
]
]
print len([1 #这行代码实际上效率很低,应用dict改为hash查找
for a in sum #在列表中遍历所有的超立方数,
if sum.count(a)==2 #如果某个数值出现了两次,说明它是一个双倍超立方数
])/2 #所有超立方数构成的列表长度除2就是双倍超立方数个数,打印输出


 

 

看来列表内涵可以用,但绝对不能滥用。适当使用还是可以提高工作效率的,如果像我这样滥用,就会适得其反。

 

至于具体的Python列表内涵使用方法,网上这方面的文章很多,我就不重复介绍了。如果感兴趣,我向你推荐《可爱的 Python:Python 中的函数编程》,关于Python列表内涵很不错的一篇文章。