What am I doing wrong for this SICP question in clojure?

Viewed 120

I'm working through SICP in Clojure. I'm stuck on exercise 1.38.

In 1.37 I made recursive and iterative procedures to compute finite continued fractions, and then in 1.38 I'm supposed to use that code to estimate Euler's number where the fraction is:

N1/(D1+N2/(D2+N3/(D3...+Nk/Dk)))

Where e-2 is equal to this fraction where N is always 1 and D is 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, ...

In order to compute e, I want to do:

(+ 2 (cont-frac-4 (constantly 1.0) d 10))

Where d is defined as:

(defn d [i] (if (zero? (rem (+ 2 i) 3)) (* 2 (/ (+ 2 i) 3)) 1))

This works with my recursive procedure:

(defn cont-frac-3 [n d k]
  (defn cont-frac-rec [i]
        (if (= i k)
        0
    (/ (n i) (+ (d i) (cont-frac-rec (inc i))))))
(cont-frac-rec 0))

But not with my iterative procedure: (I tried 2 ways and get the same incorrect result)

;; first iterative try
(defn cont-frac-4 [n d k]
  (letfn [(cont-frac-iter [i acc]
         (if (zero? i)
         acc
     (cont-frac-iter (dec i) (/ (n i) (+ (d i) acc)))))]
(cont-frac-iter k 0)))

;; second iterative try
(defn cont-frac-5 [n d k]
  (defn frac-iter [i result]
        (if (zero? i)
        result
    (frac-iter (dec i) (/ (n i) (+ (d i) result)))))
(frac-iter (dec k) (/ (n k) (d k))))

I used this as a reference, but it's not written in Clojure so I'm not sure what I'm missing: https://billthelizard.blogspot.com/2010/07/sicp-137-138-and-139-continued.html

Thank you for any advice!

1 Answers

The first iterative procedure looks fine, what I think it's causing the issue is your definition of d, which needs to be rewritten to fit the iterative process. This worked for me, and gives the same result as the recursive procedure:

(defn cont-frac [n d k]
  (letfn [(cont-frac-iter [i acc]
            (if (zero? i)
              acc
              (cont-frac-iter (dec i) (/ (n i) (+ (d i) acc)))))]
    (cont-frac-iter k 0)))

(defn d [i]
  (if (= (mod i 3) 2)
    (* 2 (Math/ceil (/ i 3)))
    1))

The result is as expected:

(+ 2 (cont-frac (constantly 1.0) d 10))
=> 2.7182817182817183
Related