我正在使用 Python 3 的功能,并尝试实现计算汉明数的经典算法。那是只有 2、3 或 5 作为素因数的数字。第一个汉明数是 2、3、4、5、6、8、10、12、15、16、18、20 等等。
我的实现如下:
def scale(s, m):
return (x*m for x in s)
def merge(s1, s2):
it1, it2 = iter(s1), iter(s2)
x1, x2 = next(it1), next(it2)
if x1 < x2:
x = x1
it = iter(merge(it1, s2))
elif x1 > x2:
x = x2
it = iter(merge(s1, it2))
else:
x = x1
it = iter(merge(it1, it2))
yield x
while True: yield next(it)
def integers():
n = 0
while True:
n += 1
yield n
m2 = scale(integers(), 2)
m3 = scale(integers(), 3)
m5 = scale(integers(), 5)
m23 = merge(m2, m3)
hamming_numbers = merge(m23, m5)
合并的问题似乎不起作用。在此之前,我以同样的方式实现了埃拉托色尼筛法,并且效果非常好:
def sieve(s):
it = iter(s)
x = next(it)
yield x
it = iter(sieve(filter(lambda y: x % y, it)))
while True: yield next(it)
这个使用与我的合并操作相同的技术。所以我看不出有什么区别。你有什么想法?
(我知道所有这些都可以通过其他方式实现,但我的目标完全是理解 Python 的生成器和纯函数功能,包括递归,而不使用类声明或特殊的预构建 Python 函数。)
UPD:对于 Will Ness,这是我在 LISP 中实现的算法(实际上是 Racket):
(define (scale str m)
(stream-map (lambda (x) (* x m)) str))
(define (integers-from n)
(stream-cons n
(integers-from (+ n 1))))
(define (merge s1 s2)
(let ((x1 (stream-first s1))
(x2 (stream-first s2)))
(cond ((< x1 x2)
(stream-cons x1 (merge (stream-rest s1) s2)))
((> x1 x2)
(stream-cons x2 (merge s1 (stream-rest s2))))
(else
(stream-cons x1 (merge (stream-rest s1) (stream-rest s2)))))))
(define integers (integers-from 1))
(define hamming-numbers
(stream-cons 1 (merge (scale hamming-numbers 2)
(merge (scale hamming-numbers 3)
(scale hamming-numbers 5)))))