练习1.11
这种题目太像是数学题目了,不过拿到编程上又有一些的难度。我们先根据题目中的条件,写出类似于第25页最下面的变换规则。我们先列出如下内容:
a-- f(n-1) f(2) f(3) f(4) f(5)
b-- f(n-2) f(1) f(2) f(3) f(4)
c—f(n-3) f(0) f(1) f(2) f(3)
于是继而得出下式:
a—a+2b+3c
b—a
c—b
于是核心部分已经出来了:
(f-iter (a+2b+3c) a b (- counter 1))
最终写成代码即可:
(define (f n)
(f-iter 1 0 0 n))
(define (f-iter a b c count)
(if (= counter 0)
b
(f-iter (+ a (* 2 b) (* 3 c)) a b (- count 1))))
类比其实是一个很好的学习方法,在博主的【Scheme归纳】3中,通过类比学习了几个很重要的关键字。
练习1.12
这道练习的翻译有误。原文是:Write a procedure that computes elements of Pascal’s triangle by means of a recursive process.正确的翻译应该是计算帕斯卡三角形的各个元素。
y :
0 1
1 1 1
2 1 2 1
3 1 3 3 1
4 1 4 6 4 1
5
x: 0 1 2 3 4
如果用x代表帕斯卡三角形中列的元素的值,y则代表行的元素的值。那么(x,y)上的值等于(x-1,y-1)和(x-1,y)上的元素的和。当y=0,或者x=y时,该处的值为1。
综合以上的两个性质,就可以写出递归版本的pascal函数了:
(define (pascal y x)
(cond ((> x y) (error ‘unvalid col value”))
((or (= x 0) (= x y)) 1)
(else (+ (pascal (- y 1) (- x 1))
(pascal (- y 1) x)))))
下面我们来检验一下:
(pascal 5 4)
;Value: 5
(pascal 5 3)
;Value: 10
虽然题目中只要求用递归,但作为学习者,不妨也用迭代试试看。更何况在前面的学习中,我们遇到了好几次超过最大递归深度。就像书中的斐波那契一样,带有太多的重复计算。利用刚才的函数,博主测试了一下(pascal 100 49),结果毫无疑问了。
帕斯卡三角形我们在数学中也学过的吧,另外在维基百科中也有相关介绍。除了刚才的计算方法之外还有一种:
(pascal y x)=y!/(x!*(y-x)!)
传说中的什么排版东东我都不太会用,大家将就着看了。
阶乘可以用第22页的注释中的代码:
(define (factorial n)
(define (iter product counter)
(if (> counter n)
product
(iter (* counter product)
(+ counter 1))))
(iter 1 1))
迭代版本的pascal:
(define (pascal y x)
(/ (factorial y)
(* (factorial x)
(factorial (- y x)))))
迭代的好处书中有大篇幅介绍,像什么空间需求。另外计算的值的大小不受递归栈深度的控制。我们再将前文中的100和49两个参数测试一下:
(pascal 100 49)
;Value: 98913082887808032681188722800
即便是用10000和499两个参数也可以算出来,结果大概有110位数,这就是递归和迭代最显而易见的区别了。
下一节的习题因为太难以输入到电脑中,就先搁置了。