itertoolsで素数計算
30分プログラム、その651。itertoolsで素数計算をしてみた。
今日、ちょっと動揺することがあったので、心を落ち着けるために素数を数えるコードを書いてみました。ネタのつもりだったんですけど、わりと落ち着きました。よかったです。
で、その辺のことはおいといて、Pythonの話をしましょう。
何度も書いてるけど、Pythonのストリームと遅延リストは似て非なるものです。何も考えずエラトステネスをふるいを書くと、関数呼び出しが止まりません。
def sieve(xs): x = xs.next() ys = sieve(ifilter(lambda y: y % x != 0,xs)) return chain([x],ys)
この問題は、明示的にyieldを呼んでやればきっと回避できますが、それだと30分もかからず解けてしまいます。それにあんまりスマートじゃない気もします。
というわけで、遅延関数適用iapplyを作ってみました。
使い方
primes = sieve(count(2)) print take(10,primes) # [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
ソースコード
#! /usr/bin/python # -*- mode:python; coding:utf-8 -*- # # prime.py - # # Copyright(C) 2009 by mzp # Author: MIZUNO Hiroki / mzpppp at gmail dot com # http://howdyworld.org # # Timestamp: 2009/09/01 21:37:55 # # This program is free software; you can redistribute it and/or # modify it under MIT Lincence. # from itertools import * class iapply(): def __init__(self,f,*args): self.f = f self.args = args self.ret = None def __iter__(self): return self def next(self): if self.ret == None: self.ret = apply(self.f,self.args) return self.ret.next() def sieve(xs): x = xs.next() ys = iapply(sieve,ifilter(lambda y: y % x != 0,xs)) return chain([x],ys) def take(n, seq): return list(islice(seq, n)) primes = sieve(count(2)) print take(10,primes)