永发信息网

如何用 Scheme 把 FIB 写成尾递归的形式?

答案:1  悬赏:80  手机版
解决时间 2021-03-02 16:39
如何用 Scheme 把 FIB 写成尾递归的形式?
最佳答案

(define fib-naive ;; 弱智版
(lambda (x)
(cond
[(zero? x) 0]
[(zero? (sub1 x)) 1]
[else (+ (fib-naive (sub1 x)) (fib-naive (- x 2)))])))

;; Chez Scheme Version 8.4
;; Copyright (c) 1985-2011 Cadence Research Systems
;;
;; > (time (fib-naive 42))
;; (time (fib-naive 42))
;; no collections
;; 8932 ms elapsed cpu time
;; 8931 ms elapsed real time
;; 0 bytes allocated
;; 267914296

(define fib-cps-aux ;; Continuation Passing Style: 其实 CPS 是不会变快的。
(lambda (x k)
(cond
[(zero? x) (k x)]
[(zero? (sub1 x)) (k 1)]
[else (fib-cps-aux
(sub1 x)
(lambda (v1)
(fib-cps-aux
(- x 2)
(lambda (v2)
(k (+ v1 v2))))))])))

(define id (lambda (x) x))

(define fib-cps
(lambda (x)
(fib-cps-aux x id)))

;; > (time (fib-cps 42))
;; (time (fib-cps 42))
;; 3290 collections
;; 11746 ms elapsed cpu time, including 235 ms collecting
;; 11746 ms elapsed real time, including 239 ms collecting
;; 27744486208 bytes allocated, including 27742030496 bytes reclaimed
;; 267914296

(define fib-acc ;; Accumulator Passing Style:
;; Racket 标准库中大量函数都是用 named let 形式构造的
(lambda (x)
(let loop ([i x] [m 0] [n 1])
(cond
[(zero? i) m]
[(zero? (sub1 i)) n]
[else (loop (sub1 i) n (+ m n))]))))

;; > (time (fib-acc 42))
;; (time (fib-acc 42))
;; no collections
;; 0 ms elapsed cpu time
;; 0 ms elapsed real time
;; 0 bytes allocated
;; 267914296

;; > (time (fib-acc 100000))
;; (time (fib-acc 100000))
;; 43 collections
;; 622 ms elapsed cpu time, including 4 ms collecting
;; 622 ms elapsed real time, including 8 ms collecting
;; 435519664 bytes allocated, including 428330784 bytes reclaimed

(define fib-sps-aux ;; Store Passing Style: 穷人版的 State Monad
(lambda (n s)
(cond
[(assv n s) => (lambda (pr) `(,(cdr pr) . ,s))]
[(< n 2) `(,n . ((,n . ,n) . ,s))]
[else
(let* ([res2 (fib-sps-aux (- n 2) s)]
[v (car res2)]
[s^ (cdr res2)]
[res1 (fib-sps-aux (sub1 n) s^)]
[u (car res1)]
[s^^ (cdr res1)]
[u+v (+ u v)])
`(,u+v . ((,n . ,u+v) . ,s^^)))])))

(define fib-sps
(lambda (x)
(car (fib-sps-aux x '()))))

;; > (time (fib-sps 42))
;; (time (fib-sps 42))
;; no collections
;; 0 ms elapsed cpu time
;; 0 ms elapsed real time
;; 2704 bytes allocated
;; 267914296

;; > (time (fib-sps 100000))
;; (time (fib-sps 100000))
;; 52 collections
;; 9480 ms elapsed cpu time, including 437 ms collecting
;; 9480 ms elapsed real time, including 435 ms collecting
;; 443672544 bytes allocated, including 5324752 bytes reclaimed
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
今天我生日,老公忘记了,怎么办
万新路我想知道这个在什么地方
水电费按人算什么意思 平均分摊?暖气费也是6
属虎的和属牛的能在一起吗?
2.编一个java程序,程序中包含以下内容:
胡记饭店地址在哪,我要去那里办事
宠物活体饲料蟋蟀大量死亡,是不是有疾病
长沙市2017年2月失业金领取要签到不?
珠海壹按我帮你企业登记代理有限公司地址在哪
海象是鱼吗?
宋朝居当时世界首位的手工业是A. 造船业B. 丝
夫妻一方黑户贷款买车
大连市规划局西岗分局地址有知道的么?有点事
朋友朋友我想对你说描写一段难忘经历
13x减x等于19解放程
推荐资讯
镇江市第四人民医院-停车场在哪里啊,我有事
重庆兴华造船厂我想知道这个在什么地方
心塞的英文怎么说
PCB线径小了点,能凑合吗??
15度36度57度78度分别是什么角
87版红楼梦老神仙说的最后一段话出自哪里
平垫圈 GB 97.1-85是什么材质
马庄卤肉老店怎么去啊,有知道地址的么
蓝天布店这个地址在什么地方,我要处理点事
属羊的在今年里有桃花运吗
刚从银杏树上摘下的新鲜杏仁怎么处理?
米兰春天量贩小溪店地址有知道的么?有点事想
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?