计算机程序的构造和解释(SICP) 第5章 习题解析 Part1
这次回顾第五章第一部分习题。
学习资料:
https://github.com/DeathKing/Learning-SICP
https://mitpress.mit.edu/sites/default/files/sicp/index.html
https://www.bilibili.com/video/BV1Xx41117tr?from=search&seid=14983483066585274454
参考资料:
https://sicp.readthedocs.io/en/latest
http://community.schemewiki.org/?SICP-Solutions
http://community.schemewiki.org/?sicp
https://liujiacai.net/blog/2016/02/22/recursion-without-name/
https://mvanier.livejournal.com/2897.html
https://github.com/jiacai2050/sicp
5.1(p346)
略过作图。
5.2(p348)
代码:
(controller
(assign (reg product) (const 1))
(assign (reg counter) (const 1))
test-b
(test (op >) (reg counter) (reg n))
(branch (label factorial-done))
(assign product (op *) (reg counter) (reg product))
(assign counter (op +) (reg counter) (const 1))
factorial-done)
5.3(p349)
代码:
(controller
(assign (reg guess) (const 1))
test-b
(test (op good-engough?) guess)
(branch (label sqrt-iter-done))
(assign guess (op improve) (reg guess))
(go-to (label test-b))
sqrt-iter-done)
(controller
(assign (reg guess) (const 1))
test-b
good-enough
(assign t1 (op square) (reg guess))
(assign t2 (op -) (reg t1) (reg x))
(assign t3 (op abs) (reg t2))
(test (op <) (reg t3) (const 0.001))
(branch (label sqrt-iter-done))
improve
(assign t4 (op /) (reg x) (reg guess))
(assign guess (op average) (reg guess) (reg t4))
impore-done
(go-to (label test-b))
sqrt-iter-done)
5.4(p357)
代码:
; a
(controller
(assign continue (label expt-done))
expt-loop
(test (op =) (reg n) (const 0))
(branch (label base-case))
(save continue)
(save n)
(assign n (op -) (reg n) (const 1))
(assign continue (label after-exp))
(goto (label expt-loop))
after-exp
(restore n)
(restore continue)
(assign val (op *) (reg b) (reg val))
(goto (reg continue))
base-case
(assign val (const 1))
(goto (reg continue))
expt-done)
; b
(controller
(assign (reg product) (const 1))
(assign counter (reg n))
test-b
(test (op =) (reg counter) (const 0))
(branch (label expt-done))
(assign counter (op -) (reg counter) (const 1))
(assign product (op *) (reg product) (reg b))
(goto (label test-b))
expt-done)
5.5(p358)
例子:
(fib 2)
调用过程:
continue n val
fib-done 2 None
afterfib-n-1 1 None
afterfib-n-1 1 1
afterfib-n-2 0 1
afterfib-n-2 0 0
fib-done 0 1
5.6(p358)
参考资料:
http://community.schemewiki.org/?sicp-ex-5.6
可以删除afterfib-n-1中如下语句:
(restore continue)
(save continue)
5.7(p360)
代码:
(load "ch5-regsim.scm")
; iter
(define expt-machine-iter
(make-machine
'(product counter b n)
(list (list '= =)
(list '- -)
(list '* *))
'((assign product (const 1))
(assign counter (reg n))
test-b
(test (op =) (reg counter) (const 0))
(branch (label expt-done))
(assign counter (op -) (reg counter) (const 1))
(assign product (op *) (reg product) (reg b))
(goto (label test-b))
expt-done)))
(set-register-contents! expt-machine-iter 'b 2)
(set-register-contents! expt-machine-iter 'n 10)
(start expt-machine-iter)
(get-register-contents expt-machine-iter 'product)
(set-register-contents! expt-machine-iter 'b 3)
(set-register-contents! expt-machine-iter 'n 5)
(start expt-machine-iter)
(get-register-contents expt-machine-iter 'product)
; rec
(define expt-machine-rec
(make-machine
'(b n continue val)
(list (list '= =)
(list '- -)
(list '* *))
'((assign continue (label expt-done))
expt-loop
(test (op =) (reg n) (const 0))
(branch (label base-case))
(save continue)
(save n)
(assign n (op -) (reg n) (const 1))
(assign continue (label after-exp))
(goto (label expt-loop))
after-exp
(restore n)
(restore continue)
(assign val (op *) (reg b) (reg val))
(goto (reg continue))
base-case
(assign val (const 1))
(goto (reg continue))
expt-done)))
(set-register-contents! expt-machine-rec 'b 2)
(set-register-contents! expt-machine-rec 'n 10)
(start expt-machine-rec)
(get-register-contents expt-machine-rec 'val)
(set-register-contents! expt-machine-rec 'b 3)
(set-register-contents! expt-machine-rec 'n 5)
(start expt-machine-rec)
(get-register-contents expt-machine-rec 'val)
实验结果:
1 ]=> (set-register-contents! expt-machine-iter 'b 2)
;Value: done
1 ]=> (set-register-contents! expt-machine-iter 'n 10)
;Value: done
1 ]=> (start expt-machine-iter)
;Value: done
1 ]=> (get-register-contents expt-machine-iter 'product)
;Value: 1024
1 ]=> (set-register-contents! expt-machine-iter 'b 3)
;Value: done
1 ]=> (set-register-contents! expt-machine-iter 'n 5)
;Value: done
1 ]=> (start expt-machine-iter)
;Value: done
1 ]=> (get-register-contents expt-machine-iter 'product)
;Value: 243
1 ]=> (set-register-contents! expt-machine-rec 'b 2)
;Value: done
1 ]=> (set-register-contents! expt-machine-rec 'n 10)
;Value: done
1 ]=> (start expt-machine-rec)
;Value: done
1 ]=> (get-register-contents expt-machine-rec 'val)
;Value: 1024
1 ]=> (set-register-contents! expt-machine-rec 'b 3)
;Value: done
1 ]=> (set-register-contents! expt-machine-rec 'n 5)
;Value: done
1 ]=> (start expt-machine-rec)
;Value: done
1 ]=> (get-register-contents expt-machine-rec 'val)
;Value: 243
5.8(p366)
ch5-regsim.scm新增规则:
; 5.8 add start
(define (extract-labels text receive)
(if (null? text)
(receive '() '())
(extract-labels (cdr text)
(lambda (insts labels)
(let ((next-inst (car text)))
(if (symbol? next-inst)
; add
(if (exist-label? next-inst labels)
(error "Multiply defined label -- ASSEMBLE" next-inst)
(receive insts
(cons (make-label-entry next-inst
insts)
labels)))
(receive (cons (make-instruction next-inst)
insts)
labels)))))))
(define (exist-label? label labels)
(cond ((null? labels) #f)
((equal? label (caar labels))
#t)
(else (exist-label? label (cdr labels)))))
; 5.8 add end
测试代码:
(load "ch5-regsim.scm")
(define test-machine
(make-machine
'(a)
(list)
'(start
(goto (label here))
here
(assign a (const 3))
(goto (label there))
here
(assign a (const 4))
(goto (label there))
there)))
(start test-machine)
(get-register-contents test-machine 'a)
实验结果:
;Multiply defined label -- ASSEMBLE here
;To continue, call RESTART with an option number:
; (RESTART 1) => Return to read-eval-print level 1.
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Doraemonzzz!
评论
ValineLivere