SICP-2nd-Edition-Exercise-1.19
From Boozled
Contents |
Exercise 1.19 From SICP
There is a clever algorithm for computing the Fibonacci numbers in a logarithmic number of steps. Recall the transformation of the state variables a and b in the fib-iter process of section 1.2.2:
and
Call this transformation T, and observe that applying T over and over again n times, starting with 1 and 0, produces the pair Fib(n + 1) and Fib(n). In other words, the Fibonacci numbers are produced by applying Tn, the nth power of the transformation T, starting with the pair
. Now consider T to be the special case of p = 0 and q = 1 in a family of transformations Tp,q, where Tp,q transforms the pair
according to:
and
Show that if we apply such a transformation Tp,q twice, the effect is the same as using a single transformation Tp',q' of the same form, and compute p' and q' in terms of p and q. This gives us an explicit way to square these transformations, and thus we can compute Tn using successive squaring, as in the fast-expt procedure. Put this all together to complete the following procedure, which runs in a logarithmic number of steps:See Footnote 41
(define (fib n)
(fib-iter 1 0 0 1 n))
(define (fib-iter a b p q count)
(cond ((= count 0) b)
((even? count)
(fib-iter a
b
<??> ; compute p'
<??> ; compute q'
(/ count 2)))
(else (fib-iter (+ (* b q) (* a q) (* a p))
(+ (* b p) (* a q))
p
q
(- count 1)))))
Attempt
The trick I used to get this one was to assume we had been asked for Fib(n) where n is a power of 2 . Also note that it's b that's returned. I used a spreadsheet to see what was happening with this one.
The following table shows what happens if we had been asked for Fib(16).
| (a,b) | (q,p) | bq + aq + ap | bp + aq |
|---|---|---|---|
| (1,0) | (0,1) | 1 | 1 |
| (1,0) | (1,1) | 3 | 2 |
| (1,0) | (3,2) | 21 | 13 |
| (1,0) | (21,13) | 987 | 610 |
Scheme
(define (fib n)
(fib-iter 1 0 0 1 n))
(define (fib-iter a b p q count)
(cond ((= count 0) b)
((even? count)
(display "a=")(display a) (display " b=") (display b) (display " p=") (display p) (display " q=") (display q) (newline)
(fib-iter a
b
(+ (* p p) (* q q))
(+ (* q q) (* p q) (* q p))
(/ count 2)))
(else (fib-iter (+ (* b q) (* a q) (* a p))
(+ (* b p) (* a q))
p
q
(- count 1)))))
(display (fib 21)) ; Fib(21)=10946
Parent Course
6.001_Structure_and_Interpretation_of_Computer_Programs

