关于SICP中练习3.66

起初在做这题的时候,第一时间想到的是写一个迭代过程和一个计数器相互配合,循环地比较pairs流中每个数对,当和(1, 100)或是(100, 100)相等的时候,就把计数器的值输出就可以了(假设是从0开始标记第一个数对的)。但是理想很丰满,现实很骨感。前者(1, 100)能按照这个思路很快就可以得出答案来(197),但是后者直接内存溢出了,说明这个序对应该排在非常得后面。正如我下面的分析,也证实了这一点。
首先,我们来写一个辅助打印的过程,这样就能比较容易地找出规律了,永远记住一点,把弱智又烦人的事情交给计算机去做,从而把自己的精力解放出来花在更有意义的事情上。

; 同时打印 m个流的前 n 项
(define (show-streams n . streams)
    (if (accumulate
            (lambda (a b) (or a b))
            #f
            (cons (= n 0) (map stream-null? streams)))
        (newline)
        (begin
            (display-line (map stream-car streams))
            (apply show-streams (cons (- n 1) (map stream-cdr streams))))))

有了这个辅助过程,我们就可以这样做:

(show-streams 17 (cons-stream 0 integers) (pairs integers integers))

这样找规律的时候就轻松多了。比如我上面的这行代码,就从第0号序对开始,一直分行打印到了第16号序对。
然后按照书上的逻辑,我们可以设一个二元整标函数 f(i, j),而i与j合起来就是所对应的序对,而函数值就是这个序对在流pairs中的位置。将这些函数值放在如书本236页中类似的二维网格图中时,我们不难总结出 f(i, j) 函数的如下约束:
f(i+1, j+1) = 2*[f(i, j) + 1]
f(0, j) = 2j - 1
f(0, 0) = 0
(i, j ∈ N+) & (i =< j)
于是,我们惊奇地发现,这是一个二阶偏差分方程。就这样,一道看似是CS的题目,其实本质是一道数学题。
我们首先观察一下这个偏差分方程
f(i+1, j+1) = 2
[f(i, j) + 1]
当不去考虑它的约束条件时,发现其实它是一个关于变元对称的方程,比如将f(j, i)带入原方程,仍可以成立。这样就启发我们可以根据变元的对称性去解方程,分两种情况:
当 i = j 时,设 i = k,那么原方程就变成:
f(k+1, k+1) = 2*[f(k, k) + 1]
这样就可以再令 a(k) = f(k, k) , 于是原方程可以化简成:
a(k+1) = 2*[a(k) + 1] 并且 a(0) = f(0, 0) = 0
上面这个方程我想高中生都应该会解了吧,那我就直接给答案了:
f(i,j) = 2^(i+1) - 2 (当 i = j)

当 i < j 时 , 可设 k = j - i
然后观察原方程与边界条件 f(0, j) = 2j - 1 后不难发现,k其实递归到最后就变成边界条件上的一个常数了。因此,可以再将原方程化简为:
f(i, i+k) = 2
[f(i-1, i-1+k) + 1]
这样就可以再令 a(i) = f(i, i+k) , 于是原方程可以化简成:
a(i) = 2*[a(i-1) + 1] 并且 a(0) = f(0, k) = 2k - 1
上面是一个一阶线性非齐次常差分方程,于是可以求得其通解为:
a(i) = C
2^i - 2
然后根据 a(0) = 2k - 1 可以得到 C = 2k + 1 = 2*(j - i) + 1
所以得到:
f(i,j) = [2*(j - i) + 1]*2^i - 2 (当 i < j)

宗上可得:
f(i,j) = 2^(i+1) - 2 (当 i = j)
[2*(j - i) + 1]*2^i - 2 (当 i < j)

但是,习题中的 (pairs integers integers) 里的 integers 流是从 1 开始展开的,所以,上述公式如果要直接用在练习中还需加一个自变量的线性变换,令:
p = i + 1
q = j + 1
于是我们有:
g(p, q) = 2^p - 2 (当 p = q)
[2*(p - q) + 1]*2^(p-1) - 2 (当 p < q)
于是可以得到:
g(1, 100) = 197
g(100, 100) = 2^100 - 2
可见真的好大,怪不得内存会溢出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值