From: Ramakrishnan Muthukrishnan Date: Thu, 22 Jul 2010 03:42:36 +0000 (+0530) Subject: solution to 2.29 X-Git-Url: https://git.rkrishnan.org/?a=commitdiff_plain;h=645caefa0c3d0cbfa183fbe6c5cc3d7a89640220;p=sicp.git solution to 2.29 --- diff --git a/src/sicp/ex2_29.clj b/src/sicp/ex2_29.clj new file mode 100644 index 0000000..7766f95 --- /dev/null +++ b/src/sicp/ex2_29.clj @@ -0,0 +1,106 @@ +(ns sicp.ex2_29 + (:use [clojure.test])) + +(defn make-mobile [left right] + (list left right)) + +(defn make-branch [length structure] + (list length structure)) + +;; a. Write the corresponding selectors left-branch and +;; right-branch, which return the branches of a mobile, and +;; branch-length and branch-structure, which return the +;; components of a branch. +(defn left-branch [mobile] + (first mobile)) + +(defn right-branch [mobile] + (first (rest mobile))) + +(defn branch-length [branch] + (first branch)) + +(defn branch-structure [branch] + (first (rest branch))) + +(deftest test-constructors-selectors + (let [m (make-mobile (make-branch 3 8) + (make-branch 9 + (make-mobile (make-branch 2 1) + (make-branch 1 2))))] + (are [x y] [= x y] + m '((3 8) (9 ((2 1) (1 2)))) + (right-branch m) '(9 ((2 1) (1 2))) + (left-branch m) '(3 8) + (branch-length (left-branch m)) 3 + (branch-length (right-branch m)) 9 + (branch-structure (left-branch m)) 8 + (branch-structure (right-branch m)) '((2 1) (1 2))))) + +;; b. Using your selectors, define a procedure total-weight that +;; returns the total weight of a mobile. + +(declare total-branch-weight) + +(defn total-weight [mobile] + (+ (total-branch-weight (right-branch mobile)) + (total-branch-weight (left-branch mobile)))) + +(defn total-branch-weight [branch] + (let [structure (branch-structure branch)] + (cond (number? structure) structure + :else (total-weight structure)))) + +(deftest test-weights + (let [m (make-mobile (make-branch 3 8) + (make-branch 9 + (make-mobile (make-branch 2 1) + (make-branch 1 2))))] + (are [x y] [= x y] + (total-weight m) 11))) + +;; c. A mobile is said to be balanced if the torque applied by its +;; top-left branch is equal to that applied by its top-right branch +;; (that is, if the length of the left rod multiplied by the weight +;; hanging from that rod is equal to the corresponding product for +;; the right side) and if each of the submobiles hanging off its +;; branches is balanced. Design a predicate that tests whether a +;; binary mobile is balanced. + +(defn torque [branch] + (* (branch-length branch) (total-branch-weight branch))) + +(defn mobile? [structure] + (seq? structure)) + +(defn balanced? [mobile] + (let [lstructure (branch-structure (left-branch mobile)) + rstructure (branch-structure (right-branch mobile))] + (and (= (torque (left-branch mobile)) + (torque (right-branch mobile))) + (if (mobile? lstructure) + (balanced? lstructure) + true) + (if (mobile? rstructure) + (balanced? rstructure) + true)))) + +(deftest test-balance + (let [m1 (make-mobile (make-branch 3 9) + (make-branch 9 + (make-mobile (make-branch 2 1) + (make-branch 1 2)))) + m2 (make-mobile (make-branch 2 4) + (make-branch 3 + (make-mobile (make-branch 2 1) + (make-branch 4 2))))] + (are [x y] [= x y] + (balanced? m1) true + (balanced? m2) false))) + +;; d. Suppose we change the representation of mobiles. +;; How much do you need to change your programs to convert +;; to the new representation? + +;; soln +;; if I were to do it in scheme, then oly selectors would change. \ No newline at end of file