(wat-aro)

無職から有職者にランクアップしました

SICP 問題 5.46

5.45と同様に今度はフィボナッチ数列の計算でそれぞれ比べる.

gosh> (define fib  ;;一回目以外は省略
        (make-machine
         (list (list '< <)
               (list '- -)
               (list '+ +))
         '(controller
           (assign continue (label fib-done))
           fib-loop
           (test (op <) (reg n) (const 2))
           (branch (label immediate-answer))
           ;; Fib(n-1)を計算するよう設定
           (save continue)
           (assign continue (label afterfib-n-1))
           (save n)                      ;n の昔の値を退避
           (assign n (op -) (reg n) (const 1))   ;n を n-1 に変える
           (goto (label fib-loop))               ;再帰呼び出しを実行
           afterfib-n-1                ;戻った時 Fib(n-1) は val にある
           (restore n)
           (restore continue)
           ;; Fib(n-2)を計算するよう設定
           (assign n (op -) (reg n) (const 2))
           (save continue)
           (assign continue (label afterfib-n-2))
           (save val)                    ;Fib(n-1) を退避
           (goto (label fib-loop))
           afterfib-n-2            ;戻った時 Fib(n-2) の値は val にある
           (assign n (reg val))    ;n には Fib(n-2) がある
           (restore val)           ;val には Fib(n-1) がある
           (restore continue)
           (assign val                   ;Fib(n-1) + Fib(n-2)
                   (op +) (reg val) (reg n))
           (goto (reg continue))   ;呼び出し側に戻る.答えは val にある
           immediate-answer
           (assign val (reg n))          ;基底の場合: Fib(n)=n
           (goto (reg continue))
           fib-done
           (perform (op print-stack-statistics)))))

fib
gosh> (set-register-contents! fib 'n 1)
done
gosh> (start fib)

(total-pushes = 0 maximum-depth = 0)done
gosh> (get-register-contents fib 'val)
1

gosh> (set-register-contents! fib 'n 2)
done
gosh> (start fib)

(total-pushes = 4 maximum-depth = 2)done
gosh> (get-register-contents fib 'val)
1
gosh> (set-register-contents! fib 'n 3)
done
gosh> (start fib)

(total-pushes = 8 maximum-depth = 4)done
gosh> (get-register-contents fib 'val)
2
gosh> (set-register-contents! fib 'n 4)
done
gosh> (start fib)

(total-pushes = 16 maximum-depth = 6)done
gosh> (get-register-contents fib 'val)
3
gosh> (set-register-contents! fib 'n 5)
done
gosh> (start fib)

(total-pushes = 28 maximum-depth = 8)done
gosh> (get-register-contents fib 'val)
5
gosh> (set-register-contents! fib 'n 5)
done
gosh> (start fib)

(total-pushes = 28 maximum-depth = 8)done
gosh> (get-register-contents fib 'val)
5
gosh> (set-register-contents! fib 'n 6)
done
gosh> (start fib)

(total-pushes = 48 maximum-depth = 10)done
gosh> (get-register-contents fib 'val)
8
gosh> (set-register-contents! fib 'n 7)
done
gosh> (start fib)

(total-pushes = 80 maximum-depth = 12)done
gosh> (get-register-contents fib 'val)
13
gosh> (set-register-contents! fib 'n 8)
done
gosh> (start fib)

(total-pushes = 132 maximum-depth = 14)done
gosh> (get-register-contents fib 'val)
21
gosh> (set-register-contents! fib 'n 9)
done
gosh> (start fib)

(total-pushes = 216 maximum-depth = 16)done
gosh> (get-register-contents fib 'val)
34
gosh> (set-register-contents! fib 'n 10)
done
gosh> (start fib)

(total-pushes = 352 maximum-depth = 18)done
gosh> (get-register-contents fib 'val)
55

 
翻訳系

gosh> (compile-and-go
       '(define (fib n)
          (if (< n 2)
              n
              (+ (fib (- n 1)) (fib (- n 2))))))

(total-pushes = 0 maximum-depth = 0)
;;; EC-Eval value:
ok

;;; EC-Eval input:
(fib 1)

(total-pushes = 7 maximum-depth = 3)
;;; EC-Eval value:
1

;;; EC-Eval input:
(fib 2)

(total-pushes = 15 maximum-depth = 5)
;;; EC-Eval value:
1

;;; EC-Eval input:
(fib 3)

(total-pushes = 23 maximum-depth = 7)
;;; EC-Eval value:
2

;;; EC-Eval input:
(fib 4)

(total-pushes = 39 maximum-depth = 9)
;;; EC-Eval value:
3

;;; EC-Eval input:
(fib 5)

(total-pushes = 63 maximum-depth = 11)
;;; EC-Eval value:
5

;;; EC-Eval input:
(fib 6)

(total-pushes = 103 maximum-depth = 13)
;;; EC-Eval value:
8

;;; EC-Eval input:
(fib 7)

(total-pushes = 167 maximum-depth = 15)
;;; EC-Eval value:
13

;;; EC-Eval input:
(fib 8)

(total-pushes = 271 maximum-depth = 17)
;;; EC-Eval value:
21

;;; EC-Eval input:
(fib 9)

(total-pushes = 439 maximum-depth = 19)
;;; EC-Eval value:
34

;;; EC-Eval input:
(fib 10)

(total-pushes = 711 maximum-depth = 21)
;;; EC-Eval value:
55

 
積極制御評価器

;;; EC-Eval input:
(define (ec-fib n)
  (if (< n 2)
      n
      (+ (ec-fib (- n 1)) (ec-fib (- n 2)))))

(total-pushes = 3 maximum-depth = 3)
;;; EC-Eval value:
ok

;;; EC-Eval input:
(ec-fib 1)

(total-pushes = 16 maximum-depth = 8)
;;; EC-Eval value:
1

;;; EC-Eval input:
(ec-fib 2)

(total-pushes = 72 maximum-depth = 13)
;;; EC-Eval value:
1

;;; EC-Eval input:
(ec-fib 3)

(total-pushes = 128 maximum-depth = 18)
;;; EC-Eval value:
2

;;; EC-Eval input:
(ec-fib 4)

(total-pushes = 240 maximum-depth = 23)
;;; EC-Eval value:
3

;;; EC-Eval input:
(ec-fib 5)

(total-pushes = 408 maximum-depth = 28)
;;; EC-Eval value:
5

;;; EC-Eval input:
(ec-fib 6)

(total-pushes = 688 maximum-depth = 33)
;;; EC-Eval value:
8

;;; EC-Eval input:
(ec-fib 7)

(total-pushes = 1136 maximum-depth = 38)
;;; EC-Eval value:
13

;;; EC-Eval input:
(ec-fib 8)

(total-pushes = 1864 maximum-depth = 43)
;;; EC-Eval value:
21

;;; EC-Eval input:
(ec-fib 9)

(total-pushes = 3040 maximum-depth = 48)
;;; EC-Eval value:
34

;;; EC-Eval input:
(ec-fib 10)

(total-pushes = 4944 maximum-depth = 53)
;;; EC-Eval value:
55

プッシュ数

n 計算機 翻訳系 評価器 評/機 翻/機
3 8 23 128 16.0 2.87
4 16 39 240 15.0 2.43
5 28 63 408 14.57 2.25
6 48 103 688 14.33 2.14
7 80 167 1136 14.2 2.08
8 132 271 1864 14.12 2.05
9 216 439 3040 14.07 2.03
10 352 711 4944 14.04 2.01|
20 43780 87567 612936 14.0 2.0

 
最大スタック深さ

計算機 翻訳系 評価器 評/機 翻/機
2n-2 2n+1 5n+3 2.500 1.00