【发布时间】:2019-09-02 07:07:13
【问题描述】:
我基本上被困在 SICP 的练习 3.56 上。问题是这样的:
练习 3.56。一个著名的问题,首先由 R. Hamming 提出,是按不重复的升序枚举所有除 2、3 或 5 之外没有素因数的正整数。一个明显的方法是简单地测试每个整数反过来看它是否有除 2、3 和 5 之外的任何因子。但这非常低效,因为随着整数变大,符合要求的整数越来越少。作为替代方案,让我们调用所需的数字流 S 并注意以下有关它的事实。
- S 以 1 开头。
- (scale-stream S 2) 的元素也是 S 的元素。
- 对于 (scale-stream S 3) 和 (scale-stream 5 S) 也是如此。
- 这些都是S的元素。
现在我们要做的就是组合来自这些来源的元素。为此,我们定义了一个过程合并,将两个有序流合并为一个有序结果流,消除重复:
(define (merge s1 s2) (cond ((stream-null? s1) s2) ((stream-null? s2) s1) (else (let ((s1car (stream-car s1)) (s2car (stream-car s2))) (cond ((< s1car s2car) (cons-stream s1car (merge (stream-cdr s1) s2))) ((> s1car s2car) (cons-stream s2car (merge s1 (stream-cdr s2)))) (else (cons-stream s1car (merge (stream-cdr s1) (stream-cdr s2)))))))))然后可以用merge构造出需要的流,如下:
(define S (cons-stream 1 (merge <??> <??>)))在上面标记的地方填上缺失的表达式。
在这个特殊问题之前,我已经能够使用信号处理框图来可视化和理解这些隐式流定义,并将原始流反馈到过程。
但我基本上遇到了这个特殊问题,我已经查找了解决方案,但我发现无法想象解决方案在我的头脑/论文中的工作方式。
有没有什么诀窍可以帮助你理解这些问题并想出解决方案?
这是有效的解决方案:
(define S
(cons-stream 1 (merge (scale-stream S 2)
(merge (scale-stream S 3)
(scale-stream S 5)))))
提前致谢。
【问题讨论】:
-
既然您已经看到了答案,您是否尝试过在评估它们之前了解Scheme 如何扩展这些表达式?我认为这可以帮助您理解这里发生了什么(使用书中给出的 cons-stream 的等效定义,在您手动扩展它时使用延迟。)我建议至少在您完成流的扩展之前达到 6(流中的最小数字,它是两个不同因子的倍数)。
-
尝试使用显式对象对其进行编码,表示为具有可变状态的闭包,它显式地从供应商那里提取输入以产生输出(作为一种可能的生成器模型)。你会在这里发现很多隐藏的东西、可能性和选择(参见 Python 的
tee函数及其复杂性)。然后,切换回流,您将能够了解流是如何自动(和/或更好地)完成它的,甚至可以看到可能的流实现中的不同选择。
标签: stream scheme lazy-evaluation sicp hamming-numbers