MASSACHVSETTS INSTITVTE OF TECHNOLOGY
Department of Electrical Engineering and Computer Science
6.001--Structure and Interpretation of Computer Programs
Fall Semester, 1998

Problem Set 5 Solutions

Computer Exercise 1:

Be careful to use the provided constructors, rather than using stream operators!

(define S1 (proc->series (lambda(x) 1)))
(define S2 (proc->series (lambda(x) (1+ x))))

Computer Exercise 2:

(define (mul-series s1 s2)
  (cons-stream (* (stream-car s1)
                  (stream-car s2))
               (add-series (scale-series (stream-car s1) (stream-cdr s2))
  (mul-series (stream-cdr s1) s2))))

 

Here we check if s1*s1=s2:

(define s3 (mul-series s1 s1))
;Value: "s3 --> (1 . #[promise 27])"

(show-series (subtract-series s3 s2) 6)
0
0
0
0
0
0

What is the coefficient of x^10 in s2*s2?

(series-coeff (mul-series s2 s2) 10)
;Value: 286

Computer Exercise 3:

(define (invert-unit-series s)
  (cons-stream 1 (negate-series (mul-series (stream-cdr s) 
                                            (invert-unit-series s)))))

The procedure doesn't go into an infinite loop, because of delayed evaluation.

Computer Exercise 4:

The idea here is to first divide the denominator series with its leading coefficient, to make it a unit-series, which we can then invert and multiply by the scaled numerator.

(define (div-series s1 s2)
  (let ((constant (stream-car s2)))
    (if (zero? constant)
        'error
        (mul-series (scale-series (/ 1 constant) s1)
                    (invert-unit-series (scale-series (/ 1 constant)  s2))))))

Computer Exercise 5:

(define (integrate-series-tail s)
  (define (index-map stream index)
    (if (stream-null? stream)
        the-empty-stream
        (cons-stream (/ (stream-car stream) index) (index-map (stream-cdr stream) (1+ index)))))
  (index-map s 1))

Here we integrate s2:

(show-series (integrate-series-tail s2) 10)
1
1
1
1
1
1
1
1
1
;Value: done

Computer Exercise 6:

Here's the correct approach:

(define cos-series
  (cons-stream 1 (negate-series (integrate-series-tail sin-series))))

(define sin-series
  (cons-stream 0 (integrate-series-tail cos-series)))

this is MUCH nicer than the versions given below, for your curiosity.

The following are NOT correct ways of doing it! I effectively filtered the exp-series:

;; attempt 1
(define (cycle n)
  (cond ((= n 1) 2)
        ((= n 2) 3)
        ((= n 3) 4)
        (else 1)))

(define (cos-series-maker stream)
  (define (stream-index-map proc n stream)
    (if (stream-null? stream)
        the-empty-stream
        (cons-stream (proc (stream-car stream) n) 
                     (stream-index-map proc (cycle n) (stream-cdr stream)))))
  (define (maker x n)
    (cond ((= n 1) x)
          ((= n 3)(- x))
          (else 0)))
  (stream-index-map maker 1 stream))

 

;; attempt 2
(define cos-series (cos-series-maker exp-series))

;; this works as desired but it is not good enough in terms of abstraction.
(define (sin-series-maker stream)
  (define (stream-index-map proc n stream)
    (if (stream-null? stream)
        the-empty-stream
        (cons-stream (proc (stream-car stream) n) 
                     (stream-index-map proc (cycle n) (stream-cdr stream)))))
  (define (maker x n)
    (cond ((= n 2) x)
          ((= n 4)(- x))
          (else 0)))
  (stream-index-map maker 1 stream))

(define sin-series (sin-series-maker exp-series))

Computer Exercise 7:

This is what happens:

(define (integrate-series series constant-term)
  (cons-stream constant-term (integrate-series-tail series)))
;Value: "integrate-series --> #[compound-procedure 56 integrate-series]"

(define exp-series3
  (integrate-series exp-series3 1))
;Unbound variable: exp-series3
;Type D to debug error, Q to quit back to REP loop: 

NOTE! I used exp-series3, because exp-series is already bound in the global environment, and I wouldn't get the desirable behavior/error.

The expression in Exercise 6 uses "cons-stream" which is a special form, which delays the call to exp-series (in this case exp-series3). In the code above, the evaluator first evaluates the argument, exp-series3, and sees that it is unbound.

Computer Exercise 8:

This is implemented in a very similar way to integrate-series-tail:

(define (deriv-series s)
  (define (index-map stream index)
    (if (stream-null? stream)
        the-empty-stream
        (cons-stream (* (stream-car stream) index) (index-map (stream-cdr stream) (1+ index)))))
  (index-map (stream-cdr s) 1))
;Value: "deriv-series --> #[compound-procedure 65 deriv-series]"

(show-series integers 5)
1
2
3
4
5
;Value: done

(define deriv-integers
  (deriv-series integers))
;Value: "deriv-integers --> (2 . #[promise 66])"

(show-series deriv-integers 5)
2
6
12
20
30
;Value: done

Computer Exercise 9:

Tan=sin/cos:

(define tan-series
  (div-series sin-series cos-series))

(show-series tan-series 10)
0
1
0
1/3
0
2/15
0
17/315
0
62/2835
;Value: done

Sec= 1/cos:

(define sec-series
   (div-series (coeffs->series '(1)) cos-series))

(show-series sec-series 10)
1
0
1/2
0
5/24
0
61/720
0
277/8064
0
;Value: done

Now we need to implement xcotx. First I defined (1/x)sinx, and then just divided cosx by it.

(define sin/x-series (stream-cdr sin-series))
(define xcot-series (div-series cos-series sin/x-series))

(show-series xcot-series 5)
1
0
-1/3
0
-1/45
;Value: done

Here I test d/dx(tan)=?=sec^2

(define test1 (deriv-series tan-series))
;Value: "test1 --> (1 . #[promise 69])"

(define test2 (mul-series sec-series sec-series))
;Value: "test2 --> (1 . #[promise 70])"

(show-series (subtract-series test1 test2) 10)
0
0
0
0
0
0
0
0
0
0
;Value: done

Computer Exercise 10:

(a) We need to realize that x/(e^x-1) can be generated by: (invert-unit-series (stream-cdr exp-series))

We need to define factorial first:

(define (fact n)
  (define (iter ans togo)
    (if (>= 0 togo)
        ans
        (iter (* ans togo) (- togo 1))))
  (iter 1 n))

(define (bernoulli n)
  (let ((bern-series (invert-unit-series (stream-cdr exp-series))))
    (* (series-coeff bern-series n)
       (fact n))))

Now we just generate a table of the first ten non-zero Bernoulli numbers:

B(0)= 1
B(1)=-1/2
B(2)= 1/12
B(4)=-1/720
B(6)= 1/30240
B(8)=-1/1209600
B(10)= 1/47900160
B(12)=-691/1307674368000
B(14)=1/74724249600
B(16)=-3617/10670622842880000
(b) Here the answers may vary, but I just tried to automate most of what needed to be done, so I wouldn’t have to type it in over and over.
(define (tan-coef-2n-1 n)
  (/  (* (expt -1 (- n 1)) 
         (expt 2 (* 2 n)) 
         (- (expt 2 (* 2 n)) 1) 
         (bernoulli (* 2 n)))
      (fact (* 2 n))))
;Value: "tan-coef-2n-1 --> #[compound-procedure 86 tan-coef-2n-1]"

(define (check-tan-series n)
  (series-coeff tan-series (- (* 2 n) 1)))
;Value: "check-tan-series --> #[compound-procedure 88 check-tan-series]"

(define (checker n)
  (equal? (tan-coef-2n-1 n) (check-tan-series n)))
;Value: "checker --> #[compound-procedure 91 checker]"

(map checker '(1 2 3 4 5 6 7 8 9 10))
;Value: (#t #t #t #t #t #t #t #t #t #t)

From this we see that the first 10 terms are the same!

Solutions by: George Dolina

Last Modified: Wed Oct 21 11:38:35 EDT 1998