今天学习了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列表内涵很不错的一篇文章。
附:《从C#到Python》系列连载目录
从C#到Python —— 谈谈我学习Python一周来的体会
从C#到Python —— 0 前言:进入Python的世界
从C#到Python —— 1 变量和数据类型
从C#到Python —— 2 运算符、表达式和流程控制
从C#到Python —— 3 函数及函数编程
从C#到Python —— 4 类及面向对象
从C#到Python —— 5 模块和包
New! 从C#到Python —— PDF整理版(下载地址)