(ns e2-24-25-26-27-28-29 (:use clojure.test)) | |

(deftest test-print-list (is (= (list 1 (list 2 (list 3 4))) [1 [2 [3 4]]]))) | |

(deftest test-get-7 (is (= (first (rest (first (rest (rest [1 3 [5 7] 9]))))) 7)) (is (= (first (first [[7]])) 7)) ; This is MADNESS! ; No! THIS! IS! DEEPLY NESTED LIST! (is (= (first (rest (first (rest (first (rest (first (rest (first (rest (first (rest [1 [2 [3 [4 [5 [6 7]]]]]])))))))))))) 7))) | |

(def x [1 2 3]) (def y [4 5 6]) | |

(deftest test-xy ; both arguments of (concat) are seqs (is (= (concat x y) [1 2 3 4 5 6])) ; (cons) expects the first argument to be a value and the second - a seq (is (= (cons x y) [[1 2 3] 4 5 6])) ; both arguments of (list) are values (is (= (list x y) [[1 2 3] [4 5 6]]))) | |

(defn deep-reverse [xs] (if (empty? xs) nil ; sequential? returns true for VECTORS as well as for other seqs ; while seq? is false for VECTORS (if (sequential? (first xs)) (concat (deep-reverse (rest xs)) [(deep-reverse (first xs))]) (concat (deep-reverse (rest xs)) [(first xs)])))) | |

(deftest test-deep-reverse (is (= (deep-reverse [[1 2] [3 4]]) [[4 3] [2 1]]))) | |

Flattens the given tree structure. | (defn fringe [t] (if (empty? t) nil (if (sequential? (first t)) (concat (fringe (first t)) (fringe (rest t))) (cons (first t) (fringe (rest t)))))) |

(deftest test-fringe (is (= (fringe [[1 2] [3 4]]) [1 2 3 4])) (is (= (fringe [[[1 2] [3 4]][[1 2] [3 4]]]) [1 2 3 4 1 2 3 4]))) | |

(defn make-mobile [l r] [l r]) | |

(defn make-branch [len structure] [len structure]) | |

(defn left-branch [m] (first m)) | |

(defn right-branch [m] (second m)) | |

(defn branch-len [b] (first b)) | |

Returns either the mobile connected to this branch or the weigth of the branch | (defn branch-structure [b] (second b)) |

(defn weight? [b] (number? b)) | |

(defn branch-weight [b] (letfn [(weight [b result] (let [structure (branch-structure b)] (if (weight? structure) (+ result structure) (+ (weight (left-branch structure) result) (weight (right-branch structure) result)))))] (weight b 0))) | |

(defn total-weight [m] (+ (branch-weight (left-branch m)) (branch-weight (right-branch m)))) | |

(def *mob1* (make-mobile (make-branch 1 5) (make-branch 1 10))) | |

(def *mob2* (make-mobile (make-branch 1 5) (make-branch 1 (make-mobile (make-branch 2 4) (make-branch 1 4))))) | |

(def *mob3* (make-mobile (make-branch 4 5) (make-branch 1 (make-mobile (make-branch 2 10) (make-branch 2 10))))) | |

(deftest test-total-weight (is (= (total-weight *mob1*) 15)) (is (= (total-weight *mob2*) (+ 5 4 4)))) | |

I bumped into a difficulty while solving this problem, as I didn't really understand what it meant for a binary mobile to be balanced. You need to calculate a torque not only for a branch which contains the weight, but for the branches which contain sub-mobiles too. It may be obvious for you, but it wasn't obvious for me. | |

(defn torque [b] (* (branch-weight b) (branch-len b))) | |

(def balanced?) | |

(defn branch-balanced? [b] (let [structure (branch-structure b)] (if (weight? structure) true (balanced? structure)))) | |

(defn balanced? [m] (and (= (torque (left-branch m)) (torque (right-branch m))) (branch-balanced? (left-branch m)) (branch-balanced? (right-branch m)))) | |

(deftest test-balanced? (is (not (balanced? *mob1*))) (is (balanced? *mob3*))) | |