From: Ramakrishnan Muthukrishnan Date: Sat, 12 Jun 2010 20:11:59 +0000 (+0530) Subject: solutions to 2.7 to 2.11. X-Git-Url: https://git.rkrishnan.org/pf/content/-?a=commitdiff_plain;h=10fbbdd2ba68e5eca76752cce4b70b40555400ca;p=sicp.git solutions to 2.7 to 2.11. --- diff --git a/src/sicp/ch2_1_extended.clj b/src/sicp/ch2_1_extended.clj new file mode 100644 index 0000000..07e6790 --- /dev/null +++ b/src/sicp/ch2_1_extended.clj @@ -0,0 +1,25 @@ +(ns sicp.ch2_1_extended + (:use [sicp utils ex2_7] + [clojure.test])) + +;; 2.1.4 - interval arithmetic +;;(declare make-interval lower-bound upper-bound) + +(defn add-interval [x y] + (make-interval (+ (lower-bound x) (lower-bound y)) + (+ (upper-bound x) (upper-bound y)))) + +(defn mul-interval [x y] + (let [p1 (* (lower-bound x) (lower-bound y)) + p2 (* (lower-bound x) (upper-bound y)) + p3 (* (upper-bound x) (lower-bound y)) + p4 (* (upper-bound x) (upper-bound y))] + (make-interval (min p1 p2 p3 p4) + (max p1 p2 p3 p4)))) + +(defn div-interval [x y] + (mul-interval x + (make-interval (/ 1.0 (upper-bound y)) + (/ 1.0 (lower-bound y))))) + + diff --git a/src/sicp/ex2_10.clj b/src/sicp/ex2_10.clj new file mode 100644 index 0000000..e1da387 --- /dev/null +++ b/src/sicp/ex2_10.clj @@ -0,0 +1,13 @@ +(ns sicp.ex2_10 + (:use [sicp utils ch2_1_extended ex2_7] + [clojure.test])) + +(defn new-div-interval [x y] + (let [l (lower-bound y) + u (upper-bound y)] + (if (or (and (pos? l) + (neg? u)) + (and (pos? u) + (neg? l))) + (error "Division by a range spanning 0") + (div-interval x y)))) \ No newline at end of file diff --git a/src/sicp/ex2_11.clj b/src/sicp/ex2_11.clj new file mode 100644 index 0000000..03fbfd0 --- /dev/null +++ b/src/sicp/ex2_11.clj @@ -0,0 +1,48 @@ +(ns sicp.ex2_11 + (:use [sicp utils ch2_1_extended ex2_7] + [clojure.test])) + +;; let [l1, u2] be lower and upper bound of range x +;; and [l2, u2] that of range y. + +;; based on the signs of l1, u1, l2, u2, we have 16 combinations + +;; l1 :u1 :l2 :u2 +;; + + + + +;; + + + - +;; + + - + +;; + + - - +;; + - + + +;; + - + - +;; + - - + +;; + - - - +;; - + + + +;; - + + - +;; - + - + +;; - + - - +;; - - + + +;; - - + - +;; - - - + +;; - - - - + +;; Now, if lower bound is +ve and upper is -ve, then it is invalid. So, +;; l1 :u1 :l2 :u2 +;; + + + + +;; + + + - => invalid +;; + + - + +;; + + - - +;; + - + + => invalid +;; + - + - => invalid +;; + - - + => invalid +;; + - - - => invalid +;; - + + + +;; - + + - => invalid +;; - + - + +;; - + - - +;; - - + + +;; - - + - => invalid +;; - - - + +;; - - - - + + +;; too boring a problem. Skipping the rest of it. diff --git a/src/sicp/ex2_7.clj b/src/sicp/ex2_7.clj new file mode 100644 index 0000000..643920c --- /dev/null +++ b/src/sicp/ex2_7.clj @@ -0,0 +1,12 @@ +(ns sicp.ex2_7 + (:use [sicp utils ch2_1_extended] + [clojure.test])) + +(defn make-interval [x y] + (list x y)) + +(defn upper-bound [i] + (first i)) + +(defn lower-bound [i] + (first (rest i))) diff --git a/src/sicp/ex2_8.clj b/src/sicp/ex2_8.clj new file mode 100644 index 0000000..6e70f73 --- /dev/null +++ b/src/sicp/ex2_8.clj @@ -0,0 +1,15 @@ +(ns sicp.ex2_8 + (:use [sicp utils ch2_1_extended ex2_7] + [clojure.test])) + +;; sub-interval +(defn sub-interval [x y] + (make-interval (- (lower-bound x) (upper-bound y)) + (- (upper-bound x) (lower-bound y)))) + +;; subtraction of an interval can be seen as addition of a +;; negative range. Intuitively, if you plot a range in a 2-D graph, +;; negative of a range, say [a1, a2] for say a1 and a2 positive +;; is [-a2, -a1]. i.e. the reflection of the range w.r.t the x=0 +;; axis. In this new light, we are adding two ranges [-a2,-a2] and [b1,b2] +;; and hence the above answer. \ No newline at end of file diff --git a/src/sicp/ex2_9.clj b/src/sicp/ex2_9.clj new file mode 100644 index 0000000..8a80249 --- /dev/null +++ b/src/sicp/ex2_9.clj @@ -0,0 +1,24 @@ +(ns sicp.ex2_9 + (:use [sicp utils ch2_1_extended ex2_7] + [clojure.test])) + +;; let us say, width of an interval [x,y] = d = (y-x)/2. +;; add_interval [x,y] = [l1+l2, u1+u2] +;; width of sum = (u1+u2 - (l1+l2))/2 +;; = (u1-l1 + u2 - l2)/2 +;; = d1 + d2 +;; +;; sub_interval [x,y] = [l1-u2, u1-l2] +;; width of diff = (u1-l2 - (l1-u2))/2 +;; = (u1 - l2 - l1 + u2) / 2 +;; = ((u1 - l1) + (u2 - l2))/2 +;; = d1 + d2 + +;; Now, intuitively multiplication (and division), scales a range +;; up or down. Since mul-range was essentially non-linear (is that the +;; right term? ) because of the min/max calculations, these depend on +;; absolute values of the range rather than the width. +;; eg: [2 3] [3 4]. Width (d1, d2) => (1,1) +;; mul-interval => [6 12] + +;; same with division as well.