问题:
Find the smallest number that can be expressed as
the sum of 7 consecutive prime numbers,
the sum of 21 consecutive prime numbers,
the sum of 481 consecutive prime numbers,
the sum of 851 consecutive prime numbers,
and is itself a prime number.
For example, 41 is the smallest prime number that can be expressed as
the sum of 3 consecutive primes (11 + 13 + 17 = 41) and
the sum of 6 consecutive primes (2 + 3 + 5 + 7 + 11 + 13 = 41).
这个问题是展示python迭代器的一个很好的示例。这篇文章主要讨论python迭代器,以及如何用python迭代器解决问题。
首先,什么是迭代器?迭代器是能够产生一个集合的一个对象。就像个售货机,每次使用都会吐出一个东西。例如一个整数的迭代器,可以用它产生一个自然数集合:
在python中的定义:
count函数是这个整数迭代器的核心,它使用yield关键词。每次调用count函数,它都会在yield停止,生成一个数n。下一次调用时不会从头开始执行而是从yield语句的下条语句开始执行直到再次碰到yield。定义好之后初始化它,这里为1。然后每次调用它的next()方法就会产生一系列整数1,2,3,4,...。
有了迭代器,解决这个问题就很简单了。只要创建一些迭代器,每次只生成一些数字处理。而不必一下子创建几个很大的数组了。这个问题需要创建六个迭代器,一个产生质数,四个产生连续质数的和,一个产生它们的交集。其中最关键的是质数迭代器。因为其余的迭代器都是基于它产生的。
第一个产生质数的迭代器(关于质数迭代器的更多讨论请看这篇文章产生质数的迭代器):
这个代码来自itoo.py
四个分别产生7,21,481,851个质数和的迭代器(参数it为质数迭代器,k为7或21或481或851):
这个代码来自itoo.py
collections.deque生成一个大小为k(也就是7,21,481,851)的双端队列。里面的值为连续k个质数。
产生交集的迭代器(*its为前五个迭代器组成的tuple):
这个代码来自itoo.py
它的算法跟求集合交集的算法差不多,只不过平时我们都用数组的下标或指针来递增,这里使用了迭代器。下面是一个3,6的例子:
1.首先每个迭代器先生成一个数字,质数迭代器产生2,求和迭代器产生10,41.取它们的最大值41给mx。
2.取出最小值,如果最小值等于最大值,那么就得到了答案。否则就删去最小值,刚产生最小值的迭代器继续产生数字。重复第二步。
3.现在10是最小值,它不等于41,所以由running_sum(it,3)产生数字了。重复第二步。
4.重复第二步,最后我们得到答案41。
最后是主程序的代码:
itertools.tee用来创建多个功能相同的独立迭代器,返回一个由迭代器组成的tuple。这里产生了5个质数迭代器,四个用于求和,一个用于就交集。
它的效率还不错。在我的03年笔记本1gcpu下的执行结果:
文章的中的python代码由Alex Martelli提供。