├── .gitignore ├── README ├── clojure ├── section1.1 │ ├── exercise1.1.txt │ ├── exercise1.2.txt │ ├── exercise1.3.txt │ ├── exercise1.4.txt │ ├── exercise1.5.txt │ ├── exercise1.7.clj │ └── exercise1.8.clj ├── section1.2 │ ├── 1.10.clj │ ├── 1.11.clj │ ├── 1.12.clj │ ├── 1.14.clj │ ├── 1.15.clj │ ├── 1.16.clj │ ├── 1.17.clj │ ├── 1.18.clj │ ├── 1.19.clj │ ├── 1.20.clj │ ├── 1.21.clj │ ├── 1.22.clj │ ├── 1.23.clj │ ├── 1.24.clj │ ├── 1.25.clj │ ├── 1.26.clj │ ├── 1.27.clj │ └── 1.9.clj ├── section1.3 │ ├── 1.29.clj │ ├── 1.30.clj │ ├── 1.31.clj │ ├── 1.32.clj │ ├── 1.33.clj │ ├── 1.34.clj │ ├── 1.35.clj │ ├── 1.36.clj │ ├── 1.41.clj │ ├── 1.42-1.44.clj │ ├── 1.45.clj │ └── 1.46.clj ├── section2.1 │ ├── 2.1.clj │ ├── 2.2-2.3.clj │ ├── 2.4.clj │ ├── 2.5.clj │ ├── 2.6.clj │ └── 2.7-2.10.clj ├── section2.2 │ ├── 2_17.clj │ ├── 2_18.clj │ ├── 2_19.clj │ ├── 2_20.clj │ ├── 2_21.clj │ ├── 2_22.clj │ ├── 2_23.clj │ ├── 2_24.clj │ ├── 2_25.clj │ ├── 2_26.clj │ ├── 2_27.clj │ ├── 2_28.clj │ ├── ex2_29.clj │ ├── ex2_30.clj │ ├── ex2_31.clj │ ├── ex2_32.clj │ ├── ex2_33.clj │ ├── ex2_34.clj │ ├── ex2_35.clj │ ├── ex2_36.clj │ ├── ex2_37.clj │ ├── ex2_38-39.clj │ ├── ex2_40.clj │ ├── ex2_41.clj │ └── ex2_42.clj ├── section2.3 │ ├── ex2_53.clj │ ├── ex2_54.clj │ ├── ex2_55.clj │ ├── ex2_59.clj │ ├── ex2_60.clj │ ├── ex2_61.clj │ ├── ex2_62.clj │ ├── ex2_63.clj │ ├── ex2_64.clj │ ├── ex2_65.clj │ ├── ex2_66.clj │ ├── huffman_encoding.clj │ ├── symbolic_diff_2_58.clj │ └── symbolic_differentiation.clj ├── section2.4 │ ├── ex2_73.clj │ ├── ex2_73_multimethods.clj │ ├── ex2_75.clj │ └── ex2_76.clj ├── section2.5 │ ├── ex2_77.clj │ ├── ex2_78.clj │ ├── ex2_79.clj │ ├── ex2_80.clj │ ├── ex2_81.clj │ ├── ex2_82.clj │ ├── ex2_83.clj │ ├── ex2_84.clj │ ├── ex2_85.clj │ ├── ex2_86.clj │ └── polynomials.clj ├── section3.1 │ ├── ex3_1.clj │ ├── ex3_2.clj │ ├── ex3_3.clj │ ├── ex3_4.clj │ ├── ex3_5.clj │ ├── ex3_6.clj │ ├── ex3_7.clj │ └── ex3_8.clj ├── section3.3 │ ├── .gitignore │ ├── project.clj │ ├── src │ │ ├── agenda.clj │ │ ├── circuit_building_blocks.clj │ │ ├── constraint_system.clj │ │ ├── deque.clj │ │ ├── ex3_12.clj │ │ ├── ex3_13.clj │ │ ├── ex3_14.clj │ │ ├── ex3_15.clj │ │ ├── ex3_16.clj │ │ ├── ex3_17.clj │ │ ├── ex3_18.clj │ │ ├── ex3_19.clj │ │ ├── ex3_22.clj │ │ ├── ex3_24.clj │ │ ├── ex3_25.clj │ │ ├── ex3_26.clj │ │ ├── ex3_27.clj │ │ ├── ex3_28.clj │ │ ├── ex3_29.clj │ │ ├── ex3_30.clj │ │ ├── ex3_31.clj │ │ ├── ex3_32.clj │ │ ├── ex3_33.clj │ │ ├── ex3_34.clj │ │ ├── ex3_35.clj │ │ ├── ex3_36.clj │ │ ├── ex3_37.clj │ │ ├── localtable.clj │ │ ├── mypair.clj │ │ └── queue.clj │ └── test │ │ ├── celsius_fahrenheit_converter.clj │ │ ├── simple_simulation.clj │ │ ├── test_constraints.clj │ │ ├── test_deque.clj │ │ ├── test_ex3_17.clj │ │ ├── test_ex3_18.clj │ │ ├── test_ex3_19.clj │ │ ├── test_ex3_22.clj │ │ ├── test_ex3_25.clj │ │ ├── test_ex3_33.clj │ │ ├── test_ex3_35.clj │ │ ├── test_ex3_37.clj │ │ ├── test_localtable.clj │ │ ├── test_mypair.clj │ │ └── test_queue.clj ├── section3.4 │ ├── ex3_38.clj │ ├── ex3_39.clj │ ├── ex3_40.clj │ ├── ex3_41.clj │ ├── ex3_42.clj │ ├── ex3_43.clj │ ├── ex3_44.clj │ ├── ex3_45.clj │ ├── ex3_46.clj │ ├── ex3_47.clj │ ├── ex3_48.clj │ └── ex3_49.clj ├── section3.5 │ ├── .gitignore │ ├── project.clj │ ├── src │ │ ├── ex3_50.clj │ │ ├── ex3_51.clj │ │ ├── ex3_52.clj │ │ ├── ex3_53.clj │ │ ├── ex3_54.clj │ │ ├── ex3_55.clj │ │ ├── ex3_56.clj │ │ ├── ex3_57.clj │ │ ├── ex3_58.clj │ │ ├── ex3_59.clj │ │ ├── ex3_60.clj │ │ ├── ex3_61.clj │ │ ├── ex3_62.clj │ │ ├── ex3_63.clj │ │ ├── ex3_64.clj │ │ ├── ex3_65.clj │ │ ├── ex3_67.clj │ │ ├── ex3_68.clj │ │ ├── ex3_69.clj │ │ ├── ex3_70.clj │ │ ├── ex3_71.clj │ │ ├── ex3_73.clj │ │ ├── ex3_74.clj │ │ ├── ex3_75.clj │ │ ├── ex3_76.clj │ │ ├── ex3_77.clj │ │ ├── ex3_78.clj │ │ ├── ex3_79.clj │ │ ├── ex3_80.clj │ │ ├── ex3_81.clj │ │ └── ex3_82.clj │ └── test │ │ ├── test_ex3_55.clj │ │ ├── test_ex3_59.clj │ │ ├── test_ex3_61.clj │ │ ├── test_ex3_70.clj │ │ └── test_ex3_74.clj ├── section4.1 │ ├── .gitignore │ ├── project.clj │ ├── src │ │ ├── environment.clj │ │ ├── ex4_1.clj │ │ ├── ex4_10.clj │ │ ├── ex4_11.clj │ │ ├── ex4_12.clj │ │ ├── ex4_13.clj │ │ ├── ex4_14.clj │ │ ├── ex4_15.clj │ │ ├── ex4_16.clj │ │ ├── ex4_17.clj │ │ ├── ex4_18.clj │ │ ├── ex4_19.clj │ │ ├── ex4_2.clj │ │ ├── ex4_20.clj │ │ ├── ex4_21.clj │ │ ├── ex4_22.clj │ │ ├── ex4_23.clj │ │ ├── ex4_24.clj │ │ ├── ex4_3.clj │ │ ├── ex4_5.clj │ │ ├── ex4_6.clj │ │ ├── ex4_7.clj │ │ ├── ex4_8.clj │ │ ├── scheme_helpers.clj │ │ ├── section4.clj │ │ └── section4_optimized.clj │ └── test │ │ ├── environment_test.clj │ │ ├── ex4_21_test.clj │ │ ├── ex4_3_tests.clj │ │ ├── section4_optimized_test.clj │ │ └── section4_test.clj ├── section4.2 │ ├── .gitignore │ ├── project.clj │ ├── src │ │ ├── environment.clj │ │ ├── ex4_25.clj │ │ ├── ex4_26.clj │ │ ├── ex4_27.clj │ │ ├── ex4_28.clj │ │ ├── ex4_29.clj │ │ ├── ex4_30.clj │ │ ├── ex4_32.clj │ │ ├── scheme_helpers.clj │ │ └── section4.clj │ └── test │ │ └── section4_test.clj └── section4.3 │ └── src │ ├── ex4_35.clj │ ├── ex4_36.clj │ └── ex4_47.clj └── q └── section1.2 └── 1.12.q /.gitignore: -------------------------------------------------------------------------------- 1 | .*\.swp 2 | .*\.swo 3 | .*\#.* 4 | .*~ 5 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Solutions for problems from the Structure and Interpretation of 2 | Computer Programs. 3 | 4 | Primary language for solving the problems will be Clojure but other 5 | languages might show up as desire arises. 6 | 7 | The Clojure code should not necessarily be taken as idiomatic Clojure. 8 | There are numerous examples which could be improved by using more 9 | of Clojure's features. 10 | 11 | Choosing Clojure to work through the problems was more of a choice 12 | to do the exercises in a language I plan on spending more time after 13 | the book is complete. The goal was not to strive for using specific 14 | Clojure features to solve SICP problems. 15 | -------------------------------------------------------------------------------- /clojure/section1.1/exercise1.1.txt: -------------------------------------------------------------------------------- 1 | Exercise 1.1 2 | Below is a sequence of expressions. What is the result printed by the interpreter in response to each expression? Assume that the sequence is to be evaluated in the order in which it is presented. 3 | 4 | Answers have -> before them 5 | If code had to be changed to work in clojure, clojure code is included with the problem. 6 | 7 | 10 8 | -> 10 9 | 10 | (+ 5 3 4) 11 | -> 12 12 | 13 | (- 9 1) 14 | -> 8 15 | 16 | (/ 6 2) 17 | -> 3 18 | 19 | (+ (* 2 4) (- 4 6)) 20 | -> 6 21 | 22 | //(define a 3) 23 | (def a 3) 24 | -> #'user/a 25 | 26 | //(define b (+ a 1)) 27 | (def b (+ a 1)) 28 | -> #'user/b 29 | 30 | (+ a b (* a b)) 31 | -> 19 32 | 33 | (= a b) 34 | -> false 35 | 36 | (if (and (> b a) (< b (* a b))) 37 | b 38 | a) 39 | -> 4 40 | 41 | //(cond ((= a 4) 6) 42 | // ((= b 4) (+ 6 7 a)) 43 | // (else 25)) 44 | (cond (= a 4) 6 45 | (= b 4) (+ 6 7 a) 46 | (= 1 1) 25) 47 | -> 16 48 | 49 | (+ 2 (if (> b a) b a)) 50 | -> 6 51 | 52 | (* (cond ((> a b) a) 53 | ((< a b) b) 54 | (else -1)) 55 | (+ a 1)) 56 | -> 16 57 | -------------------------------------------------------------------------------- /clojure/section1.1/exercise1.2.txt: -------------------------------------------------------------------------------- 1 | Exercise 1.2 2 | Write the below using s-expressions 3 | Numerator: 5 + 4 + (2 - (3 - (6 + 4/5))) 4 | Denominator: 3(6 - 2)(2 - 7) 5 | 6 | (/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5))))) (* 3 (- 6 2) (- 2 7))) 7 | -------------------------------------------------------------------------------- /clojure/section1.1/exercise1.3.txt: -------------------------------------------------------------------------------- 1 | Exercise 1.3. Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers. 2 | 3 | (defn square [x] 4 | (* x x)) 5 | 6 | (defn sum-of-squares [x y] 7 | (+ (square x) (square y))) 8 | 9 | (defn sum-squares-larger [x y z] 10 | (cond (and (< x z) (< x y)) (sum-of-squares y z) 11 | (and (< y z) (< y x)) (sum-of-squares x z) 12 | (= 1 1) (sum-of-squares x y))) 13 | -------------------------------------------------------------------------------- /clojure/section1.1/exercise1.4.txt: -------------------------------------------------------------------------------- 1 | Exercise 1.4. Observe that our model of evaluation allows for combinations whose operators are compound expressions. Use this observation to describe the behavior of the following procedure: 2 | 3 | (define (a-plus-abs-b a b) 4 | ((if (> b 0) + -) a b)) 5 | 6 | 7 | If b is less than zero then subtract b from a. If b is greater than zero add it to a. 8 | This function has the behavior of taking the absolute value of b and adding it to a. 9 | -------------------------------------------------------------------------------- /clojure/section1.1/exercise1.5.txt: -------------------------------------------------------------------------------- 1 | Exercise 1.5. Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures: 2 | 3 | (define (p) (p)) 4 | 5 | (define (test x y) 6 | (if (= x 0) 7 | 0 8 | y)) 9 | 10 | Then he evaluates the expression 11 | 12 | (test 0 (p)) 13 | 14 | What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer. (Assume that the evaluation rule for the special form if is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.) 15 | 16 | 17 | Answer: 18 | First definitions: 19 | applicative-order -> "evaluate the arguements and apply" 20 | normal-order -> "fully expand and then reduce" 21 | 22 | 23 | With applicative-order evaluation Ben will see the arguments get evalulated first. This will cause (p) to be called over and over again. 24 | 25 | With normal-order evaluation the arguements to (test) will not be evaluated until needed. This will caused the number '0' to be returned from the (test 0 (p)) call as the if statement would evaluate to true, causing (p) to never actually be executed. 26 | -------------------------------------------------------------------------------- /clojure/section1.1/exercise1.7.clj: -------------------------------------------------------------------------------- 1 | ;; (good-enough? 0.01 0.001) 2 | ;; -> true 3 | ;; .01 shouldn't be a good guess. 4 | ;; 5 | ;; Large failures: 6 | ;; Potentially because squaring the guess, even when it is very close to the proper guess, will still cause it to be further than .001 away from goal number x. This would cause infinite loop 7 | ;; user=> (good-enough? 31622.7766 1000000000) 8 | ;; false 9 | ;; 10 | ;; Different implementation: 11 | 12 | (defn change [first second] 13 | (Math/abs (- first second))) 14 | 15 | (defn good-enough?? [first second] 16 | (< (change first second) (* 0.001 second))) 17 | 18 | (defn average [x y] 19 | (/ (+ x y) 2)) 20 | 21 | (defn improve [guess x] 22 | (average guess (/ x guess))) 23 | 24 | (defn sqrt-iter [prev-guess curr-guess x] 25 | (if (good-enough?? prev-guess curr-guess) 26 | curr-guess 27 | (recur curr-guess (improve curr-guess x) x))) 28 | 29 | (defn sqrt [x] 30 | (sqrt-iter 0 1.0 x)) 31 | 32 | (sqrt 1000000000) 33 | (sqrt 0.001) 34 | 35 | ;; Using it: 36 | ;; user=> (sqrt 1000000000) 37 | ;; 31622.780588899368 38 | ;; 39 | ;; user=> (sqrt 0.001) 40 | ;; 0.03162278245070105 41 | ;; user=> (* 0.03162278245070105 0.03162278245070105) 42 | ;; 0.0010000003699243661 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /clojure/section1.1/exercise1.8.clj: -------------------------------------------------------------------------------- 1 | ; exercise 1.8 2 | 3 | (defn diff-between [first second] 4 | (Math/abs (- first second))) 5 | 6 | (defn good-enough? [first second] 7 | (< (diff-between first second) (* 0.001 second))) 8 | 9 | (defn square [x] (* x x)) 10 | 11 | (defn improve [guess x] 12 | (/ (+ (/ x (square guess)) (* 2.0 guess)) 3)) 13 | 14 | (defn cube-root [x] 15 | (let [cube-root-iter (fn [prev-guess curr-guess] 16 | (if (good-enough? prev-guess curr-guess) 17 | curr-guess 18 | (recur curr-guess (improve curr-guess x) )))] 19 | (cube-root-iter 0 1.0))) 20 | 21 | (println (cube-root 9)) 22 | 23 | ; Do it using (loop) 24 | (defn cube-root [x] 25 | (loop [prev-guess 0 curr-guess 1.0] 26 | (if (good-enough? prev-guess curr-guess) 27 | curr-guess 28 | (recur curr-guess (improve curr-guess x))))) 29 | 30 | (println (cube-root 9)) 31 | ; user=> (cube-root 9) 32 | ; 2.0800838232385224 33 | -------------------------------------------------------------------------------- /clojure/section1.2/1.10.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.10 from SICP 2 | 3 | ; Ackermann's function 4 | (defn A [x y] 5 | (cond (= y 0) 0 6 | (= x 0) (* 2 y) 7 | (= y 1) 2 8 | :else (A (- x 1) 9 | (A x (- y 1))))) 10 | 11 | ; What are values of the following? 12 | (A 1 10) 13 | ; => 1024 14 | (A 2 4) 15 | ; => 65536 16 | (A 3 3) 17 | ; => 65536 18 | 19 | ; What are the following functions in mathematical terms? 20 | (defn f [n] (A 0 n)) 21 | ; f[n] = 2*n 22 | 23 | (defn g [n] (A 1 n)) 24 | ; g[n] = 2^n 25 | 26 | (defn h [n] (A 2 n)) 27 | ; h[n] = { when n == 1 => 2 28 | ; { n > 2 => 2^h[n-1] 29 | 30 | (defn k [n] (* 5 n n)) 31 | ; k[n] = 5n^2 32 | 33 | 34 | -------------------------------------------------------------------------------- /clojure/section1.2/1.11.clj: -------------------------------------------------------------------------------- 1 | (ns sicp.exercise1.11) 2 | ; Exercise 1.11 3 | 4 | ; f(n) = n if n < 3 5 | ; = f(n - 1) + 2*f(n - 2) + 3*f(n - 3) if n >= 3 6 | 7 | 8 | ; Write recursive process 9 | (defn f [n] 10 | (if (< n 3) n 11 | (+ (f (- n 1)) 12 | (* 2 (f (- n 2))) 13 | (* 3 (f (- n 3)))))) 14 | 15 | (f 3) 16 | (f 4) 17 | (f 5) 18 | (f 6) 19 | 20 | ; Iterative 21 | 22 | (defn f2 [n] 23 | (let [f-iter (fn [a b c count] 24 | (if (< count 3) a 25 | (recur (+ a (* 2 b) (* 3 c)) 26 | a 27 | b 28 | (dec count))))] 29 | (if (< n 3) n 30 | (f-iter 2 1 0 n)))) 31 | 32 | (f2 3) 33 | (f2 4) 34 | (f2 5) 35 | (f2 6) 36 | 37 | 38 | -------------------------------------------------------------------------------- /clojure/section1.2/1.12.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.12 2 | ; A work in progress. Right now it only calculates rows in Pascal's 3 | ; Trianangle. Need to clean up and make it get back the actual 4 | ; triangle 5 | (defn moving-sum2 [coll] 6 | (let [helper (fn [i res] 7 | (if (< i (dec (count coll))) 8 | (recur (inc i) 9 | (cons (+ (nth coll i) 10 | (nth coll (inc i))) 11 | res)) 12 | (cons 1 res)))] 13 | (helper 0 [1]))) 14 | 15 | (defn pascals-triangle-row [n] 16 | (let [helper (fn [previous-row i] 17 | (println previous-row) 18 | (if (< i n) 19 | (recur (moving-sum2 previous-row) (inc i)) 20 | (moving-sum2 previous-row)))] 21 | (if (= n 0) 22 | (println '(1)) 23 | (helper '(1) 1)))) 24 | 25 | (do println (pascals-triangle-row 50)) 26 | 27 | -------------------------------------------------------------------------------- /clojure/section1.2/1.14.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.4 2 | 3 | ; Draw graph for (count-change 11) 4 | ; Code from book pulled out and translated into Clojure 5 | 6 | (defn first-denomination [kinds-of-coins] 7 | (cond (= kinds-of-coins 1) 1 8 | (= kinds-of-coins 2) 5 9 | (= kinds-of-coins 3) 10 10 | (= kinds-of-coins 4) 25 11 | (= kinds-of-coins 5) 50)) 12 | 13 | (defn cc [amount kinds-of-coins] 14 | (cond (= amount 0) 1 15 | (or (< amount 0) (= kinds-of-coins 0)) 0 16 | :else (+ (cc amount 17 | (- kinds-of-coins 1)) 18 | (cc (- amount 19 | (first-denomination kinds-of-coins)) 20 | kinds-of-coins)))) 21 | 22 | (defn count-change [amount] 23 | (cc amount 5)) 24 | 25 | (count-change 100) 26 | ; -> 292 27 | 28 | (count-change 11) 29 | 30 | ; (count-change 11) 31 | ; (cc 11 5) 32 | ; (+ (cc 11 4) (cc -39 5)) 33 | ; (+ (+ (cc 11 3) (cc -14 4)) 0) 34 | ; (+ (+ (+ (cc 11 2) (cc 1 3)) 0) 0) 35 | ; (+ (+ (+ (+ (cc 11 1) (cc 6 2)) (+ (cc 1 2) (cc -4 3))) 0) 0) 36 | ; (+ (+ (+ (+ (+ (cc 11 0) (cc 10 1)) (+ (cc 6 1) (cc 1 2)) (+ (+ (cc 1 1) (cc -4 2)) 0))) 0) 0) 37 | ; (+ (+ (+ (+ (+ 0 (+ (cc 10 0) (cc 9 1))) (+ (+ (cc 6 0) (cc 5 1)) (+ (cc 1 1) (cc -4 2))) (+ (+ (+ (cc 1 0) (cc 0 1)) 0) 0))) 0) 0) 38 | ; (+ (+ (+ (+ (+ 0 (+ 0 (+ (cc 9 0) (cc 8 1))) (+ (+ 0 (+ (cc 5 0) (cc 4 1))) (+ (+ (cc 1 0) (cc 0 1)) 0) 1 )))))) 39 | ; SKIPPED SOME STEPS HERE, ANY LINE WITH KINDS-OF-COINS == 1 REDUCES TO 1 40 | ; (+ (+ (+ (+ (+ 0 (+ 0 (+ 0 1)) (+ (+ 0(+ 0 1))) (+ (+ 0 1) 0) 1))))) 41 | ; 4 42 | ; 43 | ; space growth = O(amount) 44 | ; Reason: Space grows linearly since deepest part of tree is when it is taking 1 sent off a turn. 45 | ; Time growth = Terrible. 46 | -------------------------------------------------------------------------------- /clojure/section1.2/1.15.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.15 2 | 3 | ;(ns exercise1.15) 4 | 5 | (defn cube [x] (* x x x)) 6 | 7 | (defn p [x] 8 | (- (* 3 x) 9 | (* 4 (cube x)))) 10 | 11 | (defn abs [x] (if (< x 0) (- x) x)) 12 | 13 | (defn sine [angle] 14 | (if (not (> (abs angle) 0.1)) 15 | angle 16 | (p (sine (/ angle 3.0))))) 17 | 18 | 19 | ; a) How many times is p called when (sine 12.15) is evaluated? 20 | ; (sine 12.15) 21 | ; 5 times 22 | 23 | ; b) What is the order of growth in space and number of steps when (sine a) is evaluated 24 | ; number of steps: O(log a), as input a doubles, p increases linearly 25 | ; space: O(log a), same thing, since calls to p increase linearly and that is what is left to calculate with each step the growth in space grows linearly 26 | (sine 2.0) 27 | (sine 4.0) 28 | (sine 8.0) 29 | (sine 16.0) 30 | (sine 32.0) 31 | 32 | -------------------------------------------------------------------------------- /clojure/section1.2/1.16.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.16 2 | 3 | (defn square [x] (* x x)) 4 | 5 | (defn fast-expt [b n] 6 | (let [helper (fn [b n accum] 7 | (cond (= n 0) accum 8 | (even? n) (recur (square b) (/ n 2) accum) 9 | :else (recur b (- n 1) (* b accum))))] 10 | (helper b n 1))) 11 | 12 | 13 | 14 | (fast-expt 2 3) 15 | (fast-expt 2 4) 16 | -------------------------------------------------------------------------------- /clojure/section1.2/1.17.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.17 2 | 3 | ; Original O(b) 4 | ; (defn my-mult [a b] 5 | ; (if (= b 0) 6 | ; 0 7 | ; (+ a (my-mult a (- b 1))))) 8 | 9 | (defn doub [x] (* x 2)) 10 | (defn halve [x] (/ x 2)) 11 | 12 | (defn my-mult [a b] 13 | (cond (= b 0) 0 14 | (even? b) (my-mult (doub a) (halve b)) 15 | :else (+ a (my-mult a (dec b))))) 16 | 17 | (defn print-mult [a b] 18 | (do println (str a " * " b " = " (my-mult a b)))) 19 | (print-mult 2 4) 20 | (print-mult 2 5) 21 | (print-mult 1 5) 22 | (print-mult 3 7) 23 | (print-mult 3 10) 24 | 25 | -------------------------------------------------------------------------------- /clojure/section1.2/1.18.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.18 2 | 3 | ; Write an iterative multiplcation function 4 | ; with a run time of O(log b) 5 | 6 | (defn doub [x] (* x 2)) 7 | (defn halve [x] (/ x 2)) 8 | 9 | (defn my-mult [a b] 10 | (let [my-mult-iter (fn [a b accum] 11 | (cond (= b 1) (+ a accum) 12 | (even? b) (recur (doub a) (halve b) accum) 13 | :else (recur a (dec b) (+ accum a))))] 14 | (if (= b 0) 0 15 | (my-mult-iter a b 0)))) 16 | 17 | (defn print-mult [a b] 18 | (do println (str a " * " b " = " (my-mult a b)))) 19 | 20 | (print-mult 2 0) 21 | (print-mult 0 2) 22 | (print-mult 2 1) 23 | (print-mult 2 5) 24 | (print-mult 1 5) 25 | (print-mult 3 7) 26 | (print-mult 3 8) 27 | -------------------------------------------------------------------------------- /clojure/section1.2/1.19.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.19 2 | (ns exercise1.19 (:use clojure.test)) 3 | ; Was attempting to use clojure.test, was having issues though, leaving in to hopefully 4 | ; have discussion on it 5 | 6 | ; Compute p' and q' 7 | ; Tpq = { a <- bq + aq + ap 8 | ; { b <- bp + aq 9 | ; If Tpq is applied twice that is the same as Tp'q'. 10 | ; Therefor to figure out p' and q' apply Tpq twice 11 | ; Tpq^2 = { a <- bpq + aqq + bqq + aqq + apq + bqp + aqp + app = 12 | ; b(pq + qq + qp) + a(pq + qq + qp) + a(pp + qq) 13 | ; { b <- bpp + aqp + bqq + aqq + apq = b(pp + qq) + a(qp + qq + pq) 14 | ; Looking at the equations you can see that p' = pp + qq, q' = 2*pq + qq 15 | ; Put those into fib-iter and it works 16 | 17 | 18 | (defn fib-iter [a b p q count] 19 | (cond (= count 0) b 20 | (even? count) 21 | (fib-iter a 22 | b 23 | (+ (* p p) (* q q)) ; compute p' 24 | (+ (* 2 p q) (* q q)) ; compute q' 25 | (/ count 2)) 26 | :else 27 | (fib-iter (+ (* b q) (* a q) (* a p)) 28 | (+ (* b p) (* a q)) 29 | p 30 | q 31 | (- count 1)))) 32 | 33 | (defn fib [n] 34 | (fib-iter 1 0 0 1 n)) 35 | 36 | (fib 0) ;0 37 | (fib 1) ;1 38 | (fib 2) ;1 39 | (fib 3) ;2 40 | (fib 4) ;3 41 | (fib 5) ;5 42 | (fib 6) ;8 43 | (fib 7) ;13 44 | 45 | -------------------------------------------------------------------------------- /clojure/section1.2/1.20.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.20 2 | ; 3 | 4 | (defn remainder [a b] 5 | (mod a b)) 6 | 7 | (defn gcd [a b] 8 | (if (= b 0) 9 | a 10 | (gcd b (remainder a b)))) 11 | 12 | ; How many times is the procedure remainder called if (gcd 206 40) is evaluated and normal-order evaluation is used? 13 | ; 14 | ; (gcd 206 40) 15 | ; (gcd 40 (remainder 206 40)) 16 | ; -> causes remainder to be called 1 time 17 | ; (gcd (remainder 206 40) (remainder 40 (remainder 206 40))) 18 | ; -> causes remainder to be called 2 times 19 | ; (gcd (remainder 40 (remainder 206 40)) (remainder (remainder 206 40) (remainder 40 (remainder 206 40)))) 20 | ; -> causes remainder to be called 4 times 21 | ; (gcd (remainder (remainder 206 40) (remainder 40 (remainder 206 40))) (remainder (remainder 40 (remainder 206 40)) (remainder (remainder 206 40) (remainder 40 (remainder 206 40))))) 22 | ; -> causes remainder to be called 11 times, reason is said below 23 | ; If statement evaluates (remainder (remainder 40 (remainder 206 40)) (remainder (remainder 206 40) (remainder 40 (remainder 206 40)))) and gets 0 which causes a to be evaluated (remainder (remainder 206 40) (remainder 40 (remainder 206 40))) 24 | ; 11 + 4 + 2 + 1 = 18 calls 25 | ; 26 | ; How many times if applicative-order evaluation is used? 27 | ; 28 | ; (gcd 206 40) 29 | ; (gcd 40 (remainder 206 40)) -> (gcd 40 6) [ 1 called to remainder ] 30 | ; (gcd 6 (remainder 40 6)) -> (gcd 6 4) [ 1 called to remainder ] 31 | ; (gcd 4 (remainder 6 4)) -> (gcd 4 2) [ 1 called to remainder ] 32 | ; (gcd 2 (remainder 4 2)) -> (gcd 2 0) [ 1 called to remainder ] 33 | ; Total number of calls = 4 34 | -------------------------------------------------------------------------------- /clojure/section1.2/1.21.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.21 2 | (ns exercise1.21) 3 | 4 | (defn divides? [a b] 5 | (= (mod b a) 0)) 6 | 7 | (defn square [x] (* x x)) 8 | 9 | (defn find-divisor [n test-divisor] 10 | (cond (> (square test-divisor) n) n 11 | (divides? test-divisor n) test-divisor 12 | :else (recur n (+ test-divisor 1)))) 13 | 14 | (defn smallest-divisor [n] 15 | (find-divisor n 2)) 16 | 17 | (smallest-divisor 199) 18 | ; 199 19 | (smallest-divisor 1999) 20 | ; 1999 21 | (smallest-divisor 19999) 22 | ; 7 23 | -------------------------------------------------------------------------------- /clojure/section1.2/1.23.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.23 2 | 3 | (defn next-divisor [x] 4 | (if (= x 2) 5 | 3 6 | (+ x 2))) 7 | 8 | (defn divides? [a b] 9 | (= (mod b a) 0)) 10 | 11 | (defn square [x] (* x x)) 12 | 13 | (defn find-divisor [n test-divisor] 14 | (cond (> (square test-divisor) n) n 15 | (divides? test-divisor n) test-divisor 16 | :else (recur n (next-divisor test-divisor)))) 17 | 18 | (defn smallest-divisor [n] 19 | (find-divisor n 2)) 20 | 21 | ; back to 1.22 22 | (defn prime? [n] 23 | (= n (smallest-divisor n))) 24 | 25 | (defn current-time [] 26 | (System/nanoTime)) 27 | 28 | (defn report-prime [n elapsed-time] 29 | (println (str n " *** " elapsed-time " nanoseconds")) 30 | true) 31 | 32 | (defn start-prime-test [n start-time] 33 | (if (prime? n) 34 | (report-prime n (- (current-time) start-time)))) 35 | false 36 | 37 | (defn timed-prime-test [n] 38 | (start-prime-test n (current-time))) 39 | 40 | (defn search-for-primes [lower-bound] 41 | (let [consecutive-odd-search 42 | (fn [x] 43 | (if (timed-prime-test x) 44 | x 45 | (recur (+ x 2)))) 46 | find-three-primes 47 | (fn [x] 48 | (consecutive-odd-search 49 | (+ 2 (consecutive-odd-search 50 | (+ 2 (consecutive-odd-search x))))))] 51 | (if (odd? lower-bound) 52 | (find-three-primes lower-bound) 53 | (find-three-primes (inc lower-bound))))) 54 | 55 | 56 | 57 | (timed-prime-test 199) 58 | (timed-prime-test 199) 59 | (timed-prime-test 199) 60 | (println "Real tests") 61 | (search-for-primes 1000) 62 | (search-for-primes 10000) 63 | (search-for-primes 100000) 64 | (search-for-primes 1000000) 65 | 66 | (search-for-primes 10000000000) 67 | 68 | 69 | ; 1009 *** 35829 nanoseconds 70 | ; 1013 *** 35549 nanoseconds 71 | ; 1019 *** 35549 nanoseconds 72 | ; 10007 *** 103924 nanoseconds 73 | ; 10009 *** 104972 nanoseconds 74 | ; 10037 *** 104622 nanoseconds 75 | ; 100003 *** 322947 nanoseconds 76 | ; 100019 *** 322178 nanoseconds 77 | ; 100043 *** 324482 nanoseconds 78 | ; 1000003 *** 1141486 nanoseconds 79 | ; 1000033 *** 824825 nanoseconds 80 | ; 1000037 *** 789695 nanoseconds 81 | ; 82 | ; Ratio betweeen 1.22 times and 1.23 times. 83 | ; First argument is 1.23 times 84 | ; Clojure=> (/ 35829 50705.0) 85 | ; 0.7066167044670151 86 | ; Clojure=> (/ 103924 159587) 87 | ; 103924/159587 88 | ; Clojure=> (/ 103924 159587.0) 89 | ; 0.6512059252946668 90 | ; Clojure=> (/ 322947 502368.0) 91 | ; 0.6428494649340722 92 | ; Clojure=> (/ 824825 934127.0) 93 | ; 0.8829902143926897 94 | ; 95 | ; 10000000061 *** 63369500 nanoseconds 96 | ; 10000000061 *** 108381309 nanoseconds 97 | ; Clojure=> (/ 63369500 108381309.0) 98 | ; 0.5846902993208912 99 | ; 100 | ; When we do the search for larger numbers it gets closer to 50% time. 101 | ; It isn't all the way to 50% which may be because of 102 | ; the additional function call and if check every time 103 | ; a new never is required. 104 | -------------------------------------------------------------------------------- /clojure/section1.2/1.25.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.25 2 | ; 3 | ; expmod prevents us from doing the computation with very 4 | ; large numbers. Extremely large numbers could cause 5 | ; issues for the process as they may have to be dealt with 6 | ; specially. 7 | ; 8 | ; Large numbers would be an issue with fast-exp 9 | ; 10 | ; Footnote 46 pretty much says this but with more words. 11 | -------------------------------------------------------------------------------- /clojure/section1.2/1.26.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.26 2 | 3 | ; With this code (* (expmod base (/ exp 2) m) (expmod base (/ exp 2) m) 4 | ; expmod gets called twice. 5 | ; 6 | ; (square (expmod base (/ exp 2) m) 7 | ; With the above code expmod only gets called once. 8 | ; 9 | ; Doubling the number of times expmod gets called brings the O(log n) proccess 10 | ; to O(n) 11 | -------------------------------------------------------------------------------- /clojure/section1.2/1.27.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.27 2 | ; Not working yet 3 | 4 | (defn expmod [base exp m] 5 | (cond (= exp 0) 1 6 | (even? exp) 7 | (rem (square (expmod base (/ exp 2) m)) 8 | m) 9 | :else (rem (* base (expmod base (- exp 1) m)) 10 | m))) 11 | 12 | (defn carmichael? [n] 13 | (let [try-it (fn [a] 14 | (= (expmod a n n) a)) 15 | all-under (fn [x] 16 | (cond (= x 1) true 17 | (try-it x) (recur (dec x)) 18 | :else false ))] 19 | (all-under (dec n)))) 20 | 21 | (carmichael? 199) ; false 22 | (carmichael? 561) ; true 23 | (carmichael? 1105) ; true 24 | (carmichael? 1729) ; true 25 | (carmichael? 2465) ; true 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /clojure/section1.2/1.9.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.9 2 | 3 | (defn my-plus [a b] 4 | (if (= a 0) 5 | b 6 | (inc (my-plus (dec a) b)))) 7 | 8 | (my-plus 4 5) 9 | 10 | ; + is equal to my-plus above, is + in SICP 11 | ; (+ 4 5) 12 | ; (inc (+ 3 5)) 13 | ; (inc (inc (+ 2 5))) 14 | ; (inc (inc (inc (+ 1 5)))) 15 | ; (inc (inc (inc (inc (+ 0 5))))) 16 | ; (inc (inc (inc (inc 5)))) 17 | ; (inc (inc (inc 6))) 18 | ; (inc (inc 7)) 19 | ; (inc 8) 20 | ; 9 21 | 22 | (defn my-plus2 [a b] 23 | (if (= a 0) 24 | b 25 | (my-plus (dec a) (inc b)))) 26 | 27 | (my-plus2 4 5) 28 | 29 | ; + is equal to my-plus2 above, is + in SICP 30 | ; (+ 4 5) 31 | ; (+ 3 6) 32 | ; (+ 2 7) 33 | ; (+ 1 8) 34 | ; (+ 0 9) 35 | ; 9 36 | -------------------------------------------------------------------------------- /clojure/section1.3/1.29.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.29 2 | 3 | ; Code from book to compare answer with 4 | (defn sum [term a nxt b] 5 | (if (> a b) 0 6 | (+ (term a) 7 | (sum term (nxt a) nxt b)))) 8 | 9 | (defn integral [f a b dx] 10 | (let [add-dx (fn [x] (+ x dx))] 11 | (* (sum f (+ a (/ dx 2.0)) add-dx b) 12 | dx))) 13 | 14 | (defn cube [x] (* x x x)) 15 | 16 | (integral cube 0 1 0.01) 17 | (integral cube 0 1 0.001) 18 | 19 | ;(defn h [a b n] 20 | ; (/ (- b a) n)) 21 | 22 | (defn simp-rule [f a b n] 23 | (let [h (/ (- b a) n) 24 | next-input (fn [k] (+ a (* k h))) 25 | iter (fn [k accum] 26 | (cond (= k n) (+ accum (f (next-input k))) 27 | (odd? k) (recur (inc k) (+ accum (* 4 (f (next-input k))))) 28 | :else (recur (inc k) (+ accum (* 2 (f (next-input k)))))))] 29 | (* (/ h 3) (iter 1 (f a))))) 30 | 31 | (println (simp-rule cube 0.0 1.0 100)) 32 | (println (simp-rule cube 0.0 1.0 1000)) 33 | 34 | ; Showing what it looks like using loop instead of function 35 | (defn simp-rule [f a b n] 36 | (let [h (/ (- b a) n) 37 | next-input (fn [k] (+ a (* k h)))] 38 | (* (/ h 3) 39 | (loop [k 1 40 | accum (f a)] 41 | (cond (= k n) (+ accum (f (next-input k))) 42 | (odd? k) (recur (inc k) (+ accum (* 4 (f (next-input k))))) 43 | :else (recur (inc k) (+ accum (* 2 (f (next-input k)))))))))) 44 | 45 | (println (simp-rule cube 0.0 1.0 100)) 46 | (println (simp-rule cube 0.0 1.0 1000)) 47 | -------------------------------------------------------------------------------- /clojure/section1.3/1.30.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.30 2 | ; 3 | 4 | (defn cube [x] (* x x x)) 5 | ; Linear recusive version 6 | (defn sum [term a nxt b] 7 | (if (> a b) 8 | 0 9 | (+ (term a) 10 | (sum term (nxt a) nxt b)))) 11 | 12 | (defn sum-cubes [a b] 13 | (sum cube a inc b)) 14 | 15 | (sum-cubes 1 10) 16 | 17 | ; Iterative version 18 | (defn sum [term a nxt b] 19 | (let [iter (fn [a result] 20 | (if (> a b) 21 | result 22 | (recur (nxt a) (+ result (term a)))))] 23 | (iter a 0))) 24 | 25 | (sum-cubes 1 10) 26 | -------------------------------------------------------------------------------- /clojure/section1.3/1.31.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.31 2 | 3 | ;{{{ Iterative version 4 | (defn product [term a nxt b] 5 | (let [iter (fn [a result] 6 | (if (> a b) 7 | result 8 | (recur (nxt a) 9 | (* result (term a)))))] 10 | (iter a 1))) 11 | 12 | (defn factorial [n] 13 | (product identity 1 inc n)) 14 | 15 | (println (factorial 4)) 16 | (println (factorial 5)) 17 | 18 | ; Iterative using (loop ...) 19 | (defn product [term a nxt b] 20 | (loop [a a 21 | result 1] 22 | (if (> a b) 23 | result 24 | (recur (nxt a) 25 | (* result (term a)))))) 26 | 27 | (println (factorial 4)) 28 | (println (factorial 5)) 29 | ;}}} 30 | 31 | 32 | 33 | ;{{{ Recursive version 34 | (defn product [term a nxt b] 35 | (if (> a b) 36 | 1 37 | (* (term a) 38 | (product term (nxt a) nxt b)))) 39 | 40 | (println (factorial 4)) 41 | (println (factorial 5)) 42 | ;}}} 43 | 44 | ; vim: foldmethod=marker 45 | -------------------------------------------------------------------------------- /clojure/section1.3/1.32.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.32 2 | 3 | ;{{{ Iterative solution 4 | (defn accumulate 5 | [combiner null-value term a nxt b] 6 | (let [iter (fn [a result] 7 | (if (> a b) result 8 | (recur (nxt a) 9 | (combiner result (term a)))))] 10 | (iter a null-value))) 11 | ;}}} 12 | 13 | ; Product defined using accumulate 14 | (defn product [term a nxt b] 15 | (accumulate * 1 term a nxt b)) 16 | 17 | ; Sum from 1.30 defined using accumulate 18 | (defn sum [term a nxt b] 19 | (accumulate + 0 term a nxt b)) 20 | 21 | (defn cube [x] (* x x x)) 22 | 23 | (defn sum-cubes [a b] 24 | (sum cube a inc b)) 25 | 26 | ; Compare to 1.30. Same answer 27 | (println (sum-cubes 1 10)) 28 | 29 | (defn factorial [n] 30 | (product identity 1 inc n)) 31 | 32 | ; Compare to 1.31 33 | (println (factorial 5)) 34 | 35 | 36 | 37 | 38 | ;{{{ Recursive solution 39 | (defn accumulate 40 | [combiner null-value term a nxt b] 41 | (letfn [(iter [a] 42 | (if (> a b) null-value 43 | (combiner (term a) (iter (nxt a)))))] 44 | (iter a))) 45 | ;}}} 46 | (println (sum-cubes 1 10)) 47 | (println (factorial 5)) 48 | 49 | ; vim: foldmethod=marker 50 | -------------------------------------------------------------------------------- /clojure/section1.3/1.33.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.33 2 | 3 | (defn filtered-accumulate 4 | [include? combiner null-value term a nxt b] 5 | (let [iter (fn [a result] 6 | (if (> a b) result 7 | (if (include? a) 8 | (recur (nxt a) 9 | (combiner result (term a))) 10 | (recur (nxt a) 11 | (combiner result null-value)))))] 12 | (iter a null-value))) 13 | 14 | ;{{{ Procedures pulled from section 1.2 15 | (defn- divides? [a b] 16 | (= (mod b a) 0)) 17 | 18 | (defn- square [x] (* x x)) 19 | 20 | (defn- next-divisor [x] 21 | (if (= x 2) 22 | 3 23 | (+ x 2))) 24 | (defn- find-divisor [n test-divisor] 25 | (cond (> (square test-divisor) n) n 26 | (divides? test-divisor n) test-divisor 27 | :else (recur n (next-divisor test-divisor)))) 28 | 29 | (defn- smallest-divisor [n] 30 | (find-divisor n 2)) 31 | 32 | (defn- prime? [n] 33 | (= n (smallest-divisor n))) 34 | ; }}} 35 | 36 | ;{{{ a) write procedure using filtered-accumulate which returns sum of squares from a to b 37 | 38 | (defn sum-squares-primes [a b] 39 | (filtered-accumulate prime? + 0 square a inc b)) 40 | 41 | ; 1^2 + 2^2 3^2 + 5^2 = 39 42 | (println (sum-squares-primes 1 5)) 43 | 44 | ; }}} 45 | 46 | ;{{{ b) Write procedure that returns the product of all positive integers less 47 | ; than n that are relatively prime to n 48 | (defn- gcd [a b] 49 | (if (= b 0) 50 | a 51 | (gcd b (rem a b)))) 52 | 53 | (defn product-integers-less-than-n-and-relatively-prime-n [n] 54 | (filtered-accumulate 55 | (fn [i] (= (gcd i n) 1)) 56 | * 57 | 1 58 | identity 59 | 1 60 | inc 61 | (dec n))) 62 | 63 | (product-integers-less-than-n-and-relatively-prime-n 10) 64 | 65 | ; }}} 66 | ; vim: foldmethod=marker 67 | -------------------------------------------------------------------------------- /clojure/section1.3/1.34.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.34 2 | ; 3 | ; What happens if we have the following 4 | ; definition of the procedure f and then 5 | ; do (f f). 6 | ; 7 | (defn f [g] 8 | (g 2)) 9 | 10 | (f f) 11 | 12 | ; (f f) 13 | ; (f 2) 14 | ; (2 2) <- results in an error since 2 is not a function 15 | -------------------------------------------------------------------------------- /clojure/section1.3/1.35.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.35 2 | (defn average [x y] 3 | (/ (+ x y) 2)) 4 | 5 | (defn abs [x] (Math/abs x)) 6 | 7 | (def tolerance 0.00001) 8 | (defn close-enough? [v1 v2] 9 | (< (abs (- v1 v2)) tolerance)) 10 | 11 | (defn fixed-point [f first-guess] 12 | (let [attempt (fn [guess] 13 | (let [next (f guess)] 14 | (println guess) 15 | (if (close-enough? guess next) 16 | next 17 | (recur next))))] 18 | (attempt first-guess))) 19 | 20 | (defn calculate-golden-ratio 21 | [] 22 | (fixed-point (fn [x] (+ 1 (/ 1 x))) 23 | 1.0)) 24 | 25 | (calculate-golden-ratio) 26 | ; 1.0 27 | ; 2.0 28 | ; 1.5 29 | ; 1.6666666666666665 30 | ; 1.6 31 | ; 1.625 32 | ; 1.6153846153846154 33 | ; 1.619047619047619 34 | ; 1.6176470588235294 35 | ; 1.6181818181818182 36 | ; 1.6179775280898876 37 | ; 1.6180555555555556 38 | ; 1.6180257510729614 39 | ; 1.6180371352785146 40 | ; 1.6180327868852458 <- Close to golden ratio 41 | -------------------------------------------------------------------------------- /clojure/section1.3/1.36.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.36 2 | 3 | (defn average [x y] 4 | (/ (+ x y) 2)) 5 | 6 | (defn abs [x] (Math/abs x)) 7 | 8 | (def tolerance 0.00001) 9 | (defn close-enough? [v1 v2] 10 | (< (abs (- v1 v2)) tolerance)) 11 | 12 | (defn fixed-point [f first-guess] 13 | (let [attempt (fn [guess] 14 | (let [next (f guess)] 15 | (println guess) 16 | (if (close-enough? guess next) 17 | next 18 | (recur next))))] 19 | (attempt first-guess))) 20 | 21 | (defn sqrt [x] 22 | (fixed-point (fn [y] (average y (/ x y))) 23 | 1.0)) 24 | 25 | (defn log [x] 26 | (Math/log x)) 27 | ; x^x = 1000 as a fixed point equation 28 | (defn no-dampening [guess] 29 | (fixed-point (fn [x] (/ (log 1000) (log x))) 30 | guess)) 31 | 32 | (defn dampening [guess] 33 | (fixed-point (fn [x] (average x (/ (log 1000) (log x)))) 34 | guess)) 35 | 36 | 37 | (println "with dampening") 38 | (dampening 2.0) 39 | ; With dampening -> 10 tries 40 | ; 2.0 41 | ; 5.9828921423310435 42 | ; 4.922168721308343 43 | ; 4.628224318195455 44 | ; 4.568346513136242 45 | ; 4.5577305909237005 46 | ; 4.555909809045131 47 | ; 4.555599411610624 48 | ; 4.5555465521473675 49 | ; 4.555537551999825 50 | (println "no dampening") 51 | (no-dampening 2.0) 52 | ; With no dampening 35 53 | ; 2.0 54 | ; 9.965784284662087 55 | ; 3.004472209841214 56 | ; 6.279195757507157 57 | ; 3.759850702401539 58 | ; 5.215843784925895 59 | ; 4.182207192401397 60 | ; 4.8277650983445906 61 | ; 4.387593384662677 62 | ; 4.671250085763899 63 | ; 4.481403616895052 64 | ; 4.6053657460929 65 | ; 4.5230849678718865 66 | ; 4.577114682047341 67 | ; 4.541382480151454 68 | ; 4.564903245230833 69 | ; 4.549372679303342 70 | ; 4.559606491913287 71 | ; 4.552853875788271 72 | ; 4.557305529748263 73 | ; 4.554369064436181 74 | ; 4.556305311532999 75 | ; 4.555028263573554 76 | ; 4.555870396702851 77 | ; 4.555315001192079 78 | ; 4.5556812635433275 79 | ; 4.555439715736846 80 | ; 4.555599009998291 81 | ; 4.555493957531389 82 | ; 4.555563237292884 83 | ; 4.555517548417651 84 | ; 4.555547679306398 85 | ; 4.555527808516254 86 | ; 4.555540912917957 87 | ; 4.555532270803653 88 | -------------------------------------------------------------------------------- /clojure/section1.3/1.41.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.41 2 | 3 | ; Define a procedure called double (my-double) which takes a procedure 4 | ; as one argument and retuns a procedure that applies the 5 | ; original twice 6 | 7 | (defn my-double [f] 8 | (fn [x] (f (f x)))) 9 | 10 | 11 | ; What value is returned by 12 | ; (((my-double (my-double my-double)) inc) 5) 13 | ; 21 14 | 15 | (((my-double (my-double my-double)) inc) 5) 16 | ; 21 17 | 18 | ; Using clojures comp 19 | (defn dub [f] 20 | (comp f f)) 21 | 22 | (((dub (dub dub)) inc) 5) 23 | -------------------------------------------------------------------------------- /clojure/section1.3/1.42-1.44.clj: -------------------------------------------------------------------------------- 1 | ; Odd tab foramatting in this file is to take advantage of 2 | ; folding so all answers to individual problems can be 3 | ; seen without being distracted by answers to other problems. 4 | ; 5 | ; 6 | ; 7 | ; Exercise 1.42 8 | ; f and g are one-argument functions 9 | ; Define a procedure compose that implements composition of functions. 10 | ; Example: ((compose square inc) 6) -> 49 11 | 12 | (defn square [x] (* x x)) 13 | 14 | (defn compose [f g] 15 | (fn [x] (f (g x)))) 16 | 17 | ((compose square inc) 6) 18 | 19 | ; Could also use Clojure's comp 20 | (defn compose [f g] 21 | (comp f g)) 22 | 23 | ((compose square inc) 6) 24 | 25 | 26 | ; Exercise 1.43 27 | ; Write a function which takes a function f 28 | ; and a number n and returns a function which 29 | ; applies f n times 30 | 31 | (defn repeated [f n] 32 | (let [helper (fn [g n] 33 | (if (= n 0) g 34 | (recur (fn [x] (f (g x))) (dec n))))] 35 | (helper f (dec n)))) 36 | 37 | ((repeated square 1) 5) 38 | ((repeated square 2) 5) 39 | ((repeated square 3) 5) 40 | 41 | ; using loop 42 | (defn repeated [f n] 43 | (loop [g f n (dec n)] 44 | (if (= n 0) g 45 | (recur (fn [x] (f (g x))) (dec n))))) 46 | 47 | ((repeated square 1) 5) 48 | ((repeated square 2) 5) 49 | ((repeated square 3) 5) 50 | 51 | 52 | ; Exercise 1.44 53 | ; Write a function 'smooth which smoothes a function f by taking the average 54 | ; of f(x - dx), f(x), f(x + dx) 55 | 56 | 57 | (defn avg [x y z] 58 | (/ (+ x y z) 3)) 59 | 60 | (def dx 0.01) 61 | (defn smooth [f] 62 | (fn [x] 63 | (avg (f (- x dx)) 64 | (f x) 65 | (f (+ x dx))))) 66 | 67 | ((smooth square) 6) 68 | 69 | 70 | ; Write a function which returns a procedure which smooths a provided procedure f 71 | ; n times 72 | 73 | (defn n-smooth [f n] 74 | (fn [x] 75 | (((repeated smooth n) f) x))) 76 | 77 | ((n-smooth square 2) 6) 78 | -------------------------------------------------------------------------------- /clojure/section1.3/1.45.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.45 2 | 3 | ; Procudures below pulled from previous exercises 4 | (defn average [x y] 5 | (/ (+ x y) 2)) 6 | 7 | (defn average-damp [f] 8 | (fn [x] (average x (f x)))) 9 | 10 | (defn abs [x] (Math/abs x)) 11 | 12 | (def tolerance 0.00001) 13 | (defn close-enough? [v1 v2] 14 | (< (abs (- v1 v2)) tolerance)) 15 | 16 | (defn repeated [f n] 17 | (let [helper (fn [g n] 18 | (if (= n 0) g 19 | (recur (fn [x] (f (g x))) (dec n))))] 20 | (helper f (dec n)))) 21 | 22 | (defn fixed-point [f first-guess] 23 | (let [attempt (fn attempt[guess] 24 | (let [next (f guess)] 25 | (if (close-enough? guess next) 26 | next 27 | (recur next))))] 28 | (attempt first-guess))) 29 | 30 | ; New code 31 | 32 | (defn pow [a b] 33 | (Math/pow a b)) 34 | 35 | (defn nth-root [n x] 36 | (fixed-point ((repeated average-damp 37 | (Math/ceil (/ n 2.0))) 38 | (fn [y] (/ x (pow y (dec n))))) 39 | 1.0)) 40 | 41 | 42 | (defn sqrt [x] 43 | (nth-root 2 x)) 44 | 45 | 46 | (defn cube-root [x] 47 | (nth-root 3.0 x)) 48 | 49 | (defn fourth-root [x] 50 | (nth-root 4.0 x)) 51 | 52 | (defn fifth-root [x] 53 | (nth-root 5.0 x)) 54 | 55 | (defn sixth-root [x] 56 | (nth-root 6.0 x)) 57 | 58 | ; Use following syntax on wolframalpha.com to get answers 59 | ; fifth root of 52 60 | ; fourth root of 16 61 | (println (sqrt 4.0)) 62 | (println (cube-root 9.0)) 63 | (println (fourth-root 16.0)) 64 | (println (fifth-root 32.0)) 65 | (println (sixth-root 64.0)) 66 | -------------------------------------------------------------------------------- /clojure/section1.3/1.46.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 1.46 2 | 3 | (defn iterative-improve [good? improve-guess] 4 | (fn [guess] 5 | (loop [previous-guess guess 6 | current-guess (improve-guess guess)] 7 | (if (good? previous-guess current-guess) 8 | current-guess 9 | (recur current-guess (improve-guess current-guess)))))) 10 | 11 | ; Redefine sqrt from section 1.1.7 using iterative-improve 12 | (defn average [x y] 13 | (/ (+ x y) 2)) 14 | 15 | (defn sqrt [n] 16 | ((iterative-improve 17 | (fn [g1 g2] (< (Math/abs (- g1 g2)) 18 | (* 0.0001 g2))) 19 | (fn [guess] (average guess (/ n guess)))) 20 | 1.0)) 21 | 22 | (println (sqrt 4)) 23 | (println (sqrt 16)) 24 | 25 | ; Redefine fixed-point of section 1.3.3 to use iterative-improve 26 | (defn fixed-point [f first-guess] 27 | ((iterative-improve 28 | (fn [g1 g2] (< (Math/abs (- g1 g2)) 0.00001)) 29 | f) 30 | first-guess)) 31 | 32 | ; Procedure to show that fixed-point works 33 | (defn calculate-golden-ratio 34 | [] 35 | (fixed-point (fn [x] (+ 1 (/ 1 x))) 36 | 1.0)) 37 | (println (calculate-golden-ratio)) 38 | -------------------------------------------------------------------------------- /clojure/section2.1/2.1.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.1 2 | 3 | ; Define a better version of make-rat which 4 | ; handles constructing a rational number 5 | ; with both positive and negative numbers 6 | 7 | (defn gcd [a b] 8 | (if (= b 0) a 9 | (recur b (rem a b)))) 10 | 11 | (defn make-rat [n d] 12 | (let [g (gcd n d)] 13 | (list (/ n g) (/ d g)))) 14 | 15 | (def numer first) 16 | (def denom last) 17 | 18 | (defn print-rat [x] 19 | (println (str (numer x) "/" (denom x)))) 20 | 21 | (print-rat (make-rat 4 10)) 22 | (print-rat (make-rat -4 10)) 23 | (print-rat (make-rat -4 -10)) 24 | (print-rat (make-rat 4 -10)) 25 | 26 | ; I didn't have to change anything in the 27 | ; make-rat implementation. GCD returns the 28 | ; appropiate signed negative number which causes 29 | ; the division to cause the correct signs be on 30 | ; the numbers 31 | -------------------------------------------------------------------------------- /clojure/section2.1/2.4.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.4 2 | 3 | ; Show that cons and car implemented as below works as expected 4 | (defn my-cons [x y] 5 | (fn [m] (m x y))) 6 | 7 | (defn my-car [z] 8 | (z (fn [p q] p))) 9 | 10 | ; Expect a 1 to be printed 11 | (println (my-car (my-cons 1 2))) 12 | 13 | ; Implement cdr following these definitions 14 | (defn my-cdr [z] 15 | (z (fn [p q] q))) 16 | 17 | ; Expect a 2 to be printed 18 | (println (my-cdr (my-cons 1 2))) 19 | 20 | ; Show using substituion how my-cdr works 21 | ; 22 | ; (my-cdr (my-cons 1 2)) 23 | ; (my-cdr (fn [m] (m 1 2))) 24 | ; ((fn [m] (m 1 2)) (fn [p q] q)) 25 | ; ((fn [p q] q) 1 2) 26 | ; 2 27 | -------------------------------------------------------------------------------- /clojure/section2.1/2.5.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.5 2 | ; 3 | ; Show that we can represent pairs of nonnegative integers 4 | ; using only numbers and arithmetic operations 5 | ; if we represent the pair a and b as the interger 6 | ; that is produced by 2^a * 3^a. 7 | ; 8 | ; Define cons, car, and cdr 9 | 10 | (defn- pow [x n] 11 | (Math/pow x n)) 12 | 13 | (defn- logn [x n] 14 | (/ (Math/log x) 15 | (Math/log n))) 16 | 17 | (defn my-cons [a b] 18 | (* (pow 2 a) 19 | (pow 3 b))) 20 | 21 | ; P = 2^a*3^b 22 | ; 2^a is always even. 23 | ; 3^b is always odd. 24 | ; This means the largest even result of 2^a which divides 25 | ; evenly into p gives us what 'a equals. 26 | ; Similarily for finding b. 27 | (defn- find-highest-even-exponent 28 | "Returns maximum exponent which allows passed in 29 | max value to be divided evently by base^exp" 30 | [base next-exp max-value] 31 | (if (= 0 (rem max-value (pow base next-exp))) 32 | (recur base (inc next-exp) max-value) 33 | (dec next-exp))) 34 | 35 | (defn my-car [z] 36 | (find-highest-even-exponent 2 1 z)) 37 | 38 | (defn my-cdr [z] 39 | (find-highest-even-exponent 3 1 z)) 40 | 41 | (my-car (my-cons 4 5)) 42 | (my-cdr (my-cons 4 5)) 43 | -------------------------------------------------------------------------------- /clojure/section2.1/2.6.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.6 2 | 3 | (def zero (fn [f] (fn [x] x))) 4 | 5 | (defn add-1 [n] 6 | (fn [f] (fn [x] (f ((n f) x))))) 7 | 8 | ; (add-1 zero) 9 | ; (add-1 (fn [f] (fn [x] x))) 10 | ; (fn [f] (fn [x] (f (((fn [f] (fn [x] x))) f) x)))) 11 | ; (fn [f] (fn [x] (f x)) == one 12 | 13 | (def one (fn [f] (fn [x] (f x)))) 14 | 15 | ; (add-1 one) 16 | ; (add-1 (fn [f] (fn [x] (f x)))) 17 | ; (fn [f] (fn [x] (f ((fn [f] (fn [x] (f x))) f) x))) 18 | ; (fn [f] (fn [x] (f ((fn [x] (f x))) x))) 19 | ; (fn [f] (fn [x] (f (f x)))) == two 20 | 21 | (def two (fn [f] (fn [x] (f (f x))))) 22 | 23 | (def three (fn [f] (fn [x] (f (f (f x)))))) 24 | 25 | (defn- compose [f g] 26 | (fn [x] (f (g x)))) 27 | 28 | ; Modeled after add-1. add-1 passes f 29 | ; as an argument to number passed to it. 30 | ; Compose the two numbers to get them to 31 | ; be more nexted f calls 32 | (defn add-church [a b] 33 | (fn [f] 34 | (compose (a f) (b f)))) 35 | 36 | ((one inc) 0) 37 | ((two inc) 0) 38 | (((add-church two two) inc) 0) 39 | 40 | (defn mul-church [a b] 41 | (fn [f] 42 | (a (b f)))) 43 | 44 | (defn exp-church [a b] 45 | (b a)) 46 | 47 | (((mul-church (add-church two two) two) inc) 0) 48 | (((mul-church three two) inc) 0) 49 | (((mul-church two three) inc) 0) 50 | 51 | (((exp-church two three) inc) 0) 52 | (((exp-church three two) inc) 0) 53 | 54 | ; http://briancarper.net/blog/church-numerals-in-clojure 55 | ; Good blog post. Brian's unchurch function was useful 56 | ; in wrapping mind around this 57 | -------------------------------------------------------------------------------- /clojure/section2.2/2_17.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.17 2 | 3 | ; Define a procedure last-pair that returns the list that contains 4 | ; only the lasts element of a given (nonempty) list 5 | 6 | ; Example from book: 7 | ; (last-pair (list 23 72 149 34)) 8 | ; (34) 9 | 10 | ; Using clojure's last 11 | (defn last-pair [l] 12 | (list (last l))) 13 | 14 | (last-pair (list 23 72 149 34)) 15 | 16 | 17 | ; Using equivalent Clojure procedures as Scheme 18 | ; mentioned ones in SICP book up to this point 19 | (defn last-pair [l] 20 | (list 21 | (loop [x (first l) 22 | xs (rest l)] 23 | (if (empty? xs) 24 | x 25 | (recur (first xs) (rest xs)))))) 26 | 27 | (last-pair (list 23 72 149 34)) 28 | -------------------------------------------------------------------------------- /clojure/section2.2/2_18.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.18 2 | ; 3 | ; Define a procedure 'reverse' that takes a list as argument 4 | ; and returns a list of the same element in reverse order 5 | 6 | ; (reverse (list 1 4 9 16 25)) 7 | ; (25 16 9 4 1) 8 | 9 | ; This just works in Clojure since the reverse procedure already 10 | ; exists 11 | (reverse (list 1 4 9 16 25)) 12 | 13 | ; Here is my own version 14 | 15 | (defn my-reverse [l] 16 | (loop [nl (list (first l)) 17 | ol (rest l)] 18 | (if (empty? ol) 19 | nl 20 | (recur (cons (first ol) nl) 21 | (rest ol))))) 22 | 23 | 24 | (my-reverse (list 1 4 9 16 25)) 25 | -------------------------------------------------------------------------------- /clojure/section2.2/2_19.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.19 2 | 3 | ; Make changes the change-counting program of section 1.2.2 so 4 | ; a list of potential coins can be supplied instead of it 5 | ; only working wiith U.S. coins 6 | 7 | ; Want the following behavior 8 | ; (def us-coins (list 50 25 10 5 1)) 9 | ; (def uk-coins (list 100 50 20 10 5 2 1 0.5)) 10 | ; (cc 100 us-coins) 11 | ; 293 12 | 13 | ; Implement first-denomination, except-first-denomination and no-more? s 14 | ; the following cc procedure works 15 | (defn cc [amount coin-values] 16 | (cond (= amount 0) 1 17 | (or (< amount 0) (no-more? coin-values)) 0 18 | :else 19 | (+ (cc amount 20 | (except-first-denomination coin-values)) 21 | (cc (- amount 22 | (first-denomination coin-values)) 23 | coin-values)))) 24 | 25 | (defn first-denomination [x] 26 | (first x)) 27 | 28 | (defn except-first-denomination [x] 29 | (rest x)) 30 | 31 | (defn no-more? [x] 32 | (empty? x)) 33 | 34 | (def us-coins (list 50 25 10 5 1)) 35 | (def uk-coins (list 100 50 20 10 5 2 1 0.5)) 36 | (cc 100 us-coins) 37 | (cc 50 uk-coins) 38 | 39 | ; Does the order of the list of coins affect answer produced by cc? 40 | ; No. It simply affects the order in which solutions are found. 41 | -------------------------------------------------------------------------------- /clojure/section2.2/2_20.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.20 2 | 3 | ; Write a procedure same-parity that takes 4 | ; one or more integers and returns a list of all the arguments 5 | ; that have the saame even-odd parity as the first 6 | 7 | (defn same-parity [& l] 8 | (let [keep? (if (even? (first l)) 9 | even? 10 | odd?)] 11 | (filter keep? l))) 12 | 13 | 14 | (same-parity 1 2 3 4 5 6 7) 15 | (same-parity 2 3 4 5 6 7) 16 | -------------------------------------------------------------------------------- /clojure/section2.2/2_21.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.21 2 | ; 3 | ; The procedure square-list takes a list of numbers as an argument 4 | ; and returns the square of each numbers. 5 | ; 6 | ; Define square-list using map and without using map 7 | 8 | (defn square [x] (* x x)) 9 | 10 | (defn square-list [items] 11 | (if (empty? items) 12 | nil 13 | (cons (square (first items)) 14 | (square-list (rest items))))) 15 | 16 | (square-list (list 1 2 3 4)) 17 | 18 | (defn square-list [items] 19 | (map square items)) 20 | 21 | (square-list (list 1 2 3 4)) 22 | -------------------------------------------------------------------------------- /clojure/section2.2/2_22.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.22 2 | 3 | ; Louis Reasoner trieds to make square-list iterative. 4 | ; In the process he made it return the result list in 5 | ; reverse order. 6 | ; 7 | ; 8 | ; What is wrong with the Louis Reasoner's first attempt? (below) 9 | 10 | (defn square [x] (* x x)) 11 | 12 | (defn square-list [items] 13 | (letfn [(iter [things answer] 14 | (if (empty? things) 15 | answer 16 | (recur (rest things) 17 | (cons (square (first things)) 18 | answer))))] 19 | (iter items nil))) 20 | 21 | (square-list (list 1 2 3 4)) 22 | 23 | ; The issue is that he is building up the answer list by pulling 24 | ; elements off the front of the input list. This is causing the resulting 25 | ; list to be built backwards as elements originally further back in the 26 | ; input list are put onto the front of the answer list 27 | 28 | ; In Louis Reasoner's second attempt he switched the order of the arguments to cons. 29 | ; (To do this in clojure needed to change cons to list call. 30 | ; This causes a list of lists which is not the desired result 31 | 32 | (defn square-list [items] 33 | (letfn [(iter [things answer] 34 | (if (empty? things) 35 | answer 36 | (recur (rest things) 37 | (list answer (square (first things))))))] 38 | (iter items nil))) 39 | 40 | (println (square-list (list 1 2 3 4))) 41 | -------------------------------------------------------------------------------- /clojure/section2.2/2_23.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.23 2 | 3 | ; for-each is a procedure which takes a list and procedure 4 | ; as arguments. The procedure is applied for each element 5 | ; in the list. Nothing is done with return values. 6 | ; 7 | ; Implement for-each 8 | 9 | ; Not sure if I like how this handles emtpy lists 10 | (defn for-each [p l] 11 | (letfn [(iter [x xs] 12 | (p x) 13 | (if (empty? xs) true 14 | (recur (first xs) (rest xs))))] 15 | (iter (first l) (rest l)))) 16 | 17 | (for-each (fn [x] (println x)) 18 | (list 57 321 88)) 19 | 20 | (for-each (fn [x] (println x)) 21 | (list)) 22 | -------------------------------------------------------------------------------- /clojure/section2.2/2_24.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.24 2 | 3 | ; Clojure=> (list 1 (list 2 (list 3 4))) 4 | ; (1 (2 (3 4))) 5 | ; 6 | ; 7 | ; Tree below. Not going to show boxes 8 | ; (1 (2 (3 4))) 9 | ; / \ 10 | ; 1 (2 (3 4)) 11 | ; / \ 12 | ; 2 (3 4) 13 | ; / \ 14 | ; 3 4 15 | -------------------------------------------------------------------------------- /clojure/section2.2/2_25.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.25 2 | ; 3 | ; 4 | ; Give the combination of car and cdrs (first and rest) that will pick 7 from the following 5 | 6 | 7 | ; (1 3 (5 7) 9) 8 | (first (rest (first (rest (rest '(1 3 (5 7) 9)))))) 9 | ; 10 | ; ((7)) 11 | (first (first '((7)))) 12 | ; 13 | ; 14 | ; (1 (2 (3 (4 (5 (6 7)))))) 15 | (first 16 | (rest 17 | (first 18 | (rest 19 | (first 20 | (rest 21 | (first 22 | (rest 23 | (first 24 | (rest 25 | (first 26 | (rest '(1 (2 (3 (4 (5 (6 7)))))))))))))))))) 27 | -------------------------------------------------------------------------------- /clojure/section2.2/2_26.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.26 2 | 3 | ; Given x and y 4 | (def x (list 1 2 3)) 5 | (def y (list 4 5 6)) 6 | 7 | ; What is the result of the following 8 | 9 | ; Given in section 2.2.1 10 | (defn append [list1 list2] 11 | (if (empty? list1) 12 | list2 13 | (cons (first list1) (append (rest list1) list2)))) 14 | 15 | ; (append x y) -> '(1 2 3 4 5 6) 16 | (append x y) 17 | 18 | ; (cons x y) -> '((1 2 3) 4 5 6) 19 | (cons x y) 20 | 21 | ; (list x y) -> '((1 2 3) (4 5 6)) 22 | (list x y) 23 | -------------------------------------------------------------------------------- /clojure/section2.2/2_27.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.27 2 | 3 | (defn deep-reverse [s] 4 | (cond (empty? s) nil 5 | (seq? (first s)) 6 | (concat (deep-reverse (rest s)) 7 | (list (deep-reverse (first s)))) 8 | :else 9 | (concat (deep-reverse (rest s)) 10 | (list (first s))))) 11 | 12 | 13 | (defn print-dr [s] 14 | (println "Before: " s) 15 | (println "After : " (deep-reverse s))) 16 | 17 | (print-dr '(1 2 3)) 18 | (print-dr '((1 2) (3 4))) 19 | (print-dr '((1 2 (3 4)) (5 6 7))) 20 | -------------------------------------------------------------------------------- /clojure/section2.2/2_28.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.28 2 | 3 | ; Write a procedure named fringe that takes as an argument 4 | ; a tree (represented as a list) and returns a list 5 | ; whose elements are all the leaves of the tree arranged in 6 | ; left-to-right order. 7 | ; 8 | ; Example: 9 | ; (def x '((1 2) (3 4))) 10 | ; (fringe x) 11 | ; (1 2 3 4) 12 | 13 | (defn fringe [x] 14 | (cond (not (seq? x)) (list x) 15 | (empty? x) nil 16 | :else 17 | (concat (fringe (first x)) 18 | (fringe (rest x))))) 19 | 20 | (fringe '(1 2 3)) 21 | (def x '((1 2) (3 4))) 22 | (fringe x) 23 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_30.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.30 2 | 3 | (use 'clojure.test) 4 | 5 | (defn square [x] (* x x)) 6 | (defn square-tree [tree] 7 | (cond (not (seq? tree)) (square tree) 8 | (empty? tree) nil 9 | :else (cons (square-tree (first tree)) 10 | (square-tree (rest tree))))) 11 | 12 | (deftest square-tree-example-works 13 | (is (= '(1 (4 (9 16) 25) (36 49)) 14 | (square-tree '(1 (2 (3 4) 5) (6 7)))))) 15 | 16 | (run-tests) 17 | 18 | (defn square-tree [tree] 19 | (map (fn [sub-tree] 20 | (if (seq? sub-tree) 21 | (square-tree sub-tree) 22 | (square sub-tree))) 23 | tree)) 24 | 25 | (run-tests) 26 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_31.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.31 2 | 3 | (use 'clojure.test) 4 | 5 | (defn tree-map [op tree] 6 | (map (fn [sub-tree] 7 | (if (seq? sub-tree) 8 | (tree-map op sub-tree) 9 | (op sub-tree))) 10 | tree)) 11 | 12 | (defn square-tree [tree] 13 | (tree-map (fn [x] (* x x)) tree)) 14 | 15 | 16 | (deftest square-tree-example-works 17 | (is (= '(1 (4 (9 16) 25) (36 49)) 18 | (square-tree '(1 (2 (3 4) 5) (6 7)))))) 19 | 20 | (run-tests) 21 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_32.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.31 2 | 3 | (use 'clojure.test) 4 | (defn subsets [s] 5 | (if (empty? s) 6 | (list nil) 7 | (let [rst (subsets (rest s))] 8 | (concat rst (map (fn [x] (cons (first s) x)) rst))))) 9 | 10 | (subsets '(1 2 3)) 11 | 12 | (deftest subsets-works-with-example-from-book 13 | (is (= '(() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))))) 14 | 15 | (run-tests) 16 | 17 | ; expected '( () (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3)) 18 | ; 19 | ; This solution works the following way: 20 | ; 1) Take a set (from here called orig-set) and take away every element of it 21 | ; -> this leaves '(()) which I will call new-set from now on. 22 | ; 2) Take one element element from orig-set and add it to new-set along 23 | ; with add it concated with any element that was previously in new-set 24 | ; 3) Repeat step two till every element in orig-set has been choosen 25 | ; 4) You are left with new-set having every combination of elements from 26 | ; orig-set 27 | 28 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_33.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.33 2 | 3 | (use 'clojure.test) 4 | 5 | ; clojurefied accumulate from book 6 | (defn accumulate [op initial sq] 7 | (if (empty? sq) 8 | initial 9 | (op (first sq) 10 | (accumulate op initial (rest sq))))) 11 | 12 | (deftest test-accumulate 13 | (is (= 15 (accumulate + 0 (list 1 2 3 4 5))))) 14 | 15 | 16 | 17 | (defn my-map [p sq] 18 | (accumulate (fn [x y] (cons (p x) y)) nil sq)) 19 | 20 | (deftest test-my-map 21 | (is (= '(2 3 4 5 6) (my-map inc (list 1 2 3 4 5))))) 22 | 23 | 24 | 25 | (defn append [seq1 seq2] 26 | (accumulate cons seq2 seq1)) 27 | 28 | (deftest test-append 29 | (is (= '(1 2 3 4 5 6) (append '(1 2 3) '(4 5 6))))) 30 | 31 | 32 | (defn length [sq] 33 | (accumulate (fn [x y] (inc y)) 0 sq)) 34 | 35 | (deftest test-length 36 | (is (= 5 (length '(1 2 3 4 5))))) 37 | 38 | 39 | 40 | (run-tests) 41 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_34.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.34 2 | (use 'clojure.test) 3 | 4 | (defn accumulate [op initial sq] 5 | (if (empty? sq) 6 | initial 7 | (op (first sq) 8 | (accumulate op initial (rest sq))))) 9 | 10 | (defn horner-eval [x coefficent-sequence] 11 | (accumulate (fn [this-coeff higher-terms] (+ this-coeff (* x higher-terms)) ) 12 | 0 13 | coefficent-sequence)) 14 | 15 | (deftest test-horner-eval 16 | (is (= 79 (horner-eval 2 (list 1 3 0 5 0 1))))) 17 | 18 | (run-tests) 19 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_35.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.35 2 | (use 'clojure.test) 3 | 4 | (defn accumulate [op initial sq] 5 | (if (empty? sq) 6 | initial 7 | (op (first sq) 8 | (accumulate op initial (rest sq))))) 9 | 10 | (defn count-leaves [t] 11 | (accumulate + 0 (map (fn [x] 12 | (if (seq? x) 13 | (count-leaves x) 14 | 1)) 15 | t))) 16 | 17 | (deftest test-count-leaves 18 | (is (= 3 (count-leaves '(1 (2 3))))) 19 | (is (= 5 (count-leaves '((8 7 9) (2 3)))))) 20 | 21 | (run-tests) 22 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_36.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.36 2 | 3 | (use 'clojure.test) 4 | 5 | (defn accumulate [op initial sq] 6 | (if (empty? sq) 7 | initial 8 | (op (first sq) 9 | (accumulate op initial (rest sq))))) 10 | 11 | (defn accumulate-n [op init seqs] 12 | (if (empty? (first seqs)) 13 | nil 14 | (cons (accumulate op init (map first seqs)) 15 | (accumulate-n op init (map rest seqs))))) 16 | 17 | (deftest test-accumulate-n 18 | (is (= '(22 26 30) (accumulate-n + 0 '((1 2 3) (4 5 6) (7 8 9) (10 11 12)))))) 19 | 20 | (run-tests) 21 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_37.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.37 2 | (use 'clojure.test) 3 | 4 | (defn accumulate [op initial sq] 5 | (if (empty? sq) 6 | initial 7 | (op (first sq) 8 | (accumulate op initial (rest sq))))) 9 | 10 | (defn accumulate-n [op init seqs] 11 | (if (empty? (first seqs)) 12 | nil 13 | (cons (accumulate op init (map first seqs)) 14 | (accumulate-n op init (map rest seqs))))) 15 | 16 | 17 | 18 | (def matrix '((1 2 3 4) (4 5 6 6) (6 7 8 9))) 19 | ; Matrix represented by matrix 20 | ; [1 2 3 4] 21 | ; [4 5 6 6] 22 | ; [6 7 8 9] 23 | 24 | (defn dot-product [v w] 25 | (accumulate + 0 (map * v w))) 26 | 27 | (println (dot-product '(2 4 6) '(3 5 7))) 28 | 29 | ; I think there may be a different way of doing this. 30 | ; book only had ?? before the second parameter to map, 31 | ; I ended up making map take another list of mulitpliers 32 | (defn matrix-*-vector [m v] 33 | (map (fn [s a] (* a (accumulate + 0 s))) 34 | m 35 | v)) 36 | 37 | (deftest test-matrix-*-vector 38 | (is (= '(10 42 0) 39 | (matrix-*-vector matrix '(1 2 0))))) 40 | 41 | (defn transpose [m] 42 | (accumulate-n cons nil m)) 43 | ; [1 2 3 4] 44 | ; [4 5 6 6] 45 | ; [6 7 8 9] 46 | ; TRANPOSED 47 | ; [1 4 6] 48 | ; [2 5 7] 49 | ; [3 6 8] 50 | ; [4 6 9] 51 | (deftest test-transpose 52 | (is (= '((1 4 6) (2 5 7) (3 6 8) (4 6 9)) (transpose matrix)))) 53 | 54 | (defn matrix-*-matrix [mat1 mat2] 55 | (let [cols (transpose mat2)] 56 | (map (fn [row] 57 | (map 58 | (fn [column] 59 | (accumulate 60 | + 61 | 0 62 | (map * row column))) 63 | cols)) 64 | mat1))) 65 | 66 | ; [1 2 3 4] [1 4 6] [30 56 80] 67 | ; [4 5 6 6] * [2 5 7] = [56 113 161] 68 | ; [6 7 8 9] [3 6 8] [80 161 230] 69 | ; [4 6 9] 70 | 71 | (def expected '((30 56 80) (56 113 161) (80 161 230))) 72 | (deftest test-matrix-*-matrix 73 | (is (= expected 74 | (matrix-*-matrix matrix (transpose matrix))))) 75 | 76 | 77 | (run-tests) 78 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_38-39.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.38 2 | 3 | (defn fold-right [op initial sq] 4 | (if (empty? sq) 5 | initial 6 | (op (first sq) 7 | (fold-right op initial (rest sq))))) 8 | 9 | (defn fold-left [op initial sq] 10 | (loop [result initial 11 | remaining sq] 12 | (if (empty? remaining) 13 | result 14 | (recur (op result (first remaining)) 15 | (rest remaining))))) 16 | 17 | (println (fold-right / 1 (list 1 2 3))) 18 | (println (fold-left / 1 (list 1 2 3))) 19 | (println (fold-right list nil (list 1 2 3))) 20 | (println (fold-left list nil (list 1 2 3))) 21 | 22 | ; If an operation is associative then fold-right 23 | ; and fold-left will have the same output 24 | (println (fold-right + 1 (list 1 2 3))) 25 | (println (fold-left + 1 (list 1 2 3))) 26 | 27 | 28 | ; Exercise 2.39 29 | (use 'clojure.test) 30 | 31 | (defn reverse-using-fold-right [sq] 32 | (fold-right (fn [x y] (concat y (list x))) nil sq)) 33 | 34 | (deftest test-using-fold-right-to-reverse 35 | (is (= '(5 4 3 2 1) (reverse-using-fold-right '(1 2 3 4 5))))) 36 | 37 | (defn reverse-using-fold-left [sq] 38 | (fold-left (fn [x y] (cons y x)) nil sq)) 39 | 40 | (deftest test-using-fold-left-to-reverse 41 | (is (= '(5 4 3 2 1) (reverse-using-fold-left '(1 2 3 4 5))))) 42 | 43 | (run-tests) 44 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_40.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.40 2 | 3 | (use 'clojure.test) 4 | 5 | (defn accumulate [op initial sq] 6 | (if (empty? sq) 7 | initial 8 | (op (first sq) 9 | (accumulate op initial (rest sq))))) 10 | 11 | (defn enumerate-interval [low high] 12 | (loop [cur high 13 | res nil] 14 | (if (< cur low) 15 | res 16 | (recur (dec cur) (cons cur res))))) 17 | 18 | (deftest test-enum-int 19 | (is (= '(1 2 3 4) (enumerate-interval 1 4))) 20 | (is (= nil (enumerate-interval 1 0))) 21 | (is (= '(1) (enumerate-interval 1 1)))) 22 | 23 | (defn flatmap [proc sq] 24 | (accumulate concat nil (map proc sq))) 25 | 26 | (defn unique-pairs [n] 27 | (flatmap (fn [i] 28 | (map (fn [j] (list i j)) 29 | (enumerate-interval 1 (dec i)))) 30 | (enumerate-interval 1 n))) 31 | 32 | (println (unique-pairs 5)) 33 | 34 | ;{{{ Procedures pulled from section 1.2 35 | (defn- divides? [a b] 36 | (= (mod b a) 0)) 37 | 38 | (defn- square [x] (* x x)) 39 | 40 | (defn- next-divisor [x] 41 | (if (= x 2) 42 | 3 43 | (+ x 2))) 44 | (defn- find-divisor [n test-divisor] 45 | (cond (> (square test-divisor) n) n 46 | (divides? test-divisor n) test-divisor 47 | :else (recur n (next-divisor test-divisor)))) 48 | 49 | (defn- smallest-divisor [n] 50 | (find-divisor n 2)) 51 | 52 | (defn- prime? [n] 53 | (= n (smallest-divisor n))) 54 | ; }}} 55 | 56 | (defn prime-sum? [pair] 57 | (prime? (+ (first pair) (last pair)))) 58 | 59 | (defn make-pair-sum [pair] 60 | (list (first pair) (last pair) (+ (first pair) (last pair)))) 61 | 62 | (defn prime-sum-pairs [n] 63 | (map make-pair-sum 64 | (filter prime-sum? 65 | (unique-pairs n)))) 66 | 67 | (println (prime-sum-pairs 5)) 68 | 69 | (run-tests) 70 | 71 | ; vim: foldmethod=marker 72 | -------------------------------------------------------------------------------- /clojure/section2.2/ex2_41.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.41 2 | 3 | (use 'clojure.test) 4 | 5 | (defn accumulate [op initial sq] 6 | (if (empty? sq) 7 | initial 8 | (op (first sq) 9 | (accumulate op initial (rest sq))))) 10 | 11 | (defn flatmap [proc sq] 12 | (accumulate concat nil (map proc sq))) 13 | 14 | (defn enumerate-interval [low high] 15 | (loop [cur high 16 | res nil] 17 | (if (< cur low) 18 | res 19 | (recur (dec cur) (cons cur res))))) 20 | 21 | (defn order-triples [n] 22 | (flatmap (fn [i] 23 | (flatmap 24 | (fn [j] 25 | (map (fn [k] (list i j k)) 26 | (enumerate-interval 1 (dec j)))) 27 | (enumerate-interval 2 (dec i)))) 28 | (enumerate-interval 3 n))) 29 | 30 | (defn order-triple-sum-matches? [s] 31 | (fn [x] (= s (accumulate + 0 x)))) 32 | 33 | (deftest test-otsm? 34 | (is (= true ((order-triple-sum-matches? 6) '(1 2 3)))) 35 | (is (= false ((order-triple-sum-matches? 5) '(1 2 3))))) 36 | 37 | (defn order-triples-that-sum [n s] 38 | (let [sum-checker (order-triple-sum-matches? s)] 39 | (filter sum-checker 40 | (order-triples n)))) 41 | 42 | (deftest test-order-triples-sum-works 43 | (is (= 2 (count (order-triples-that-sum 5 8))))) 44 | 45 | (println (order-triples-that-sum 5 8)) 46 | 47 | (run-tests) 48 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_53.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.53 2 | 3 | ; What would the interpreter print in response 4 | ; of the following expressions? 5 | 6 | ;(list 'a 'b 'c) 7 | ; (a b c) 8 | (println (list 'a 'b 'c)) 9 | 10 | ;(list (list 'george)) 11 | ; ((george)) 12 | (println (list (list 'george))) 13 | 14 | ;(cdr '((x1 x2) (y1 y2))) -> (rest '((x1 x2) (y1 y2))) 15 | ; ((y1 y2)) 16 | (println (rest '((x1 x2) (y1 y2)))) 17 | 18 | ;(cadr '((x1 x2) (y1 y2))) -> (first (rest '((x1 x2) (y1 y2)))) 19 | ; (y1 y2) 20 | (println (first (rest '((x1 x2) (y1 y2))))) 21 | 22 | ;(pair? (car '(a short list))) 23 | ; false 24 | (println (seq? (first '(a short list)))) 25 | 26 | (defn memq [item x] 27 | (cond (empty? x) false 28 | (= item (first x)) x 29 | :else (memq item (rest x)))) 30 | ; (memq 'red '((red shoes) (blue socks)) 31 | ; false 32 | (println (memq 'red '((red shoes) (blue socks)))) 33 | 34 | ; (memq 'red '(red shoes blue socks)) 35 | ; true 36 | (println (memq 'red '(red shoes blue socks))) 37 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_54.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.54 2 | ; 3 | ; Two lists are said to be equal? if they contain 4 | ; equal elements arranged in the same order. Implement equal? for 5 | ; lists of symbols 6 | 7 | (use 'clojure.test) 8 | 9 | (def equal? =) 10 | 11 | (deftest equal?-works 12 | (is (= true (equal? '(a b c) '(a b c)))) 13 | (is (= false (equal? '(a b) '(a b z)))) 14 | (is (= false (equal? '(b a c) '(b a d))))) 15 | 16 | (run-tests) 17 | 18 | (defn equal? [x y] 19 | "equal? defined using recursion instead of cheating and using =" 20 | (cond (and (not (seq? x)) (not (seq? y))) (= x y) 21 | (empty? x) (empty? y) 22 | (empty? y) (empty? x) 23 | :else (and (equal? (first x) (first y)) 24 | (equal? (rest x) (rest y))))) 25 | 26 | (run-tests) 27 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_55.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.55 2 | ; 3 | ; Eva Lu Ator types the following 4 | ; (car ''abracadarbra) 5 | ; 6 | ; A quote is printed back. Why? 7 | ; 8 | ; (car (quote (quote abracadabra))) 9 | ; 10 | ; A quote is printed back because abracadabra has two single 11 | ; quotes in front of it. The first quote 12 | ; is quoting the second, causing it not to be evaluated. 13 | ; This results in the word quote being printed to the screen. 14 | 15 | (println (first ''abracadabra)) 16 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_59.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.59 2 | ; 3 | ; Write a procedure union-set which does a union 4 | ; of two sets where the sets are represented 5 | ; by unique lists 6 | 7 | (use 'clojure.test) 8 | 9 | (defn element-of-set? [x s] 10 | (cond (empty? s) false 11 | (= x (first s)) true 12 | :else (element-of-set? x (rest s)))) 13 | 14 | (deftest element-of-set?-works 15 | (is (element-of-set? 1 '(1 2 3))) 16 | (is (not (element-of-set? 4 '(1 2 3))))) 17 | 18 | (defn union-set [set1 set2] 19 | (cond (or (empty? set1) (empty? set2)) set2 20 | (element-of-set? (first set1) set2) 21 | (union-set (rest set1) set2) 22 | :else (cons (first set1) 23 | (union-set (rest set1) set2)))) 24 | 25 | 26 | (deftest should-return-simple-union 27 | (is (= '(3 7 5 1) (union-set '(3 7 5) '(1))))) 28 | 29 | (deftest should-return-same-set 30 | (is (= '(1 2 3) (union-set '(1 4 3) '(1 4 3))))) 31 | 32 | (run-tests) 33 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_60.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.60 2 | ; 3 | ; Suppose we change the representation of sets to be 4 | ; lists which allow duplicate entries. What do element-of-set?, 5 | ; adjoin-set, union-set, and intersection-set look like? 6 | ; How does the efficiency compare? 7 | ; Would you ever want to use this representation 8 | 9 | 10 | 11 | ; element-of-set? does not need to change 12 | (defn adjoin-set [x s] (cons x s)) 13 | (defn union-set [s1 s2] (concat s1 s2)) 14 | ; Intersection can still be the same as the way in the book 15 | 16 | ; Efficiency? 17 | ; element-of-set? is less efficient if searching for an element which is not in the list. 18 | ; Overall it is still O(n) where n is the number of elements in the set though 19 | ; 20 | ; adjoin-set no longer uses element-of-set?, it simply puts the element on the list. 21 | ; Now is O(1) 22 | ; 23 | ; union-set is whatever concat is, hopefully O(n) 24 | ; 25 | ; intersection is the same as it was O(n^2) 26 | ; 27 | ; This representation might be useful if union-set and adjoin-set were the 28 | ; most common operations one was performing. 29 | 30 | 31 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_61.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.61 2 | (use 'clojure.test) 3 | 4 | ; Now use ordered lists to represent sets 5 | 6 | 7 | ; Not using any nice things in Clojure 8 | (defn adjoin-set [x s] 9 | (loop [head '() 10 | tail s] 11 | (cond (empty? tail) (concat head (list x)) 12 | (= x (first tail)) (concat head tail) 13 | (> x (first tail)) (recur (concat head 14 | (list (first tail))) 15 | (rest tail)) 16 | :else (concat head (list x) tail)))) 17 | 18 | (deftest adjoin-set-puts-low-element-at-beginning 19 | (is (= '(1 3 4) (adjoin-set 1 '(3 4))))) 20 | 21 | (deftest adjoin-set-puts-element-in-middle 22 | (is (= '(2 3 4) (adjoin-set 3 '(2 4))))) 23 | 24 | (deftest adjoin-set-puts-large-element-at-end 25 | (is (= '(1 3 4 5) (adjoin-set 5 '(1 3 4))))) 26 | 27 | (run-tests) 28 | 29 | (defn element-of-set? [x s] 30 | (cond (empty? s) false 31 | (= x (rest s)) true 32 | (< x (first s)) false 33 | :else (element-of-set? x (rest s)))) 34 | 35 | ; Somewhat cheating 36 | (defn adjoin-set [x s] 37 | (if (element-of-set? x s) s 38 | (sort (cons x s)))) 39 | 40 | (run-tests) 41 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_62.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.62 2 | ; Give an O(n) implementation of union-set 3 | ; representing sets as ordered lists 4 | 5 | (use 'clojure.test) 6 | 7 | (defn union-set [s1 s2] 8 | (cond (empty? s1) s2 9 | (empty? s2) s1 10 | :else 11 | (let [x1 (first s1) 12 | x2 (first s2)] 13 | (cond (= x1 x2) (cons x1 (union-set (rest s1) (rest s2))) 14 | (< x1 x2) (cons x1 (union-set (rest s1) s2)) 15 | (< x2 x1) (cons x2 (union-set s1 (rest s2))))))) 16 | 17 | 18 | (deftest should-return-input-on-matching-inputs 19 | (is (= '(1 2 3) (union-set '(1 2 3) '(1 2 3))))) 20 | 21 | (deftest should-handle-one-set-always-smaller 22 | (is (= '(1 2 3 4 5 6) (union-set '(1 2 3) '(4 5 6))))) 23 | 24 | (deftest should-handle-sets-flip-flopping-size 25 | (is (= '(1 2 3 4 5 6 7) (union-set '(1 3 5 7) '(2 4 6))))) 26 | 27 | 28 | (run-tests) 29 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_63.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.63 2 | 3 | 4 | (defn entry [tree] (first tree)) 5 | (defn left-branch [tree] (second tree)) 6 | (defn right-branch [tree] (nth tree 2)) 7 | (defn make-tree [entry left right] 8 | (list entry left right)) 9 | 10 | (defn tree->list-1 [tree] 11 | (if (empty? tree) 12 | '() 13 | (concat (tree->list-1 (left-branch tree)) 14 | (cons (entry tree) 15 | (tree->list-1 (right-branch tree)))))) 16 | 17 | (defn tree->list-2 [tree] 18 | (letfn [(copy-to-list [tree result-list] 19 | (if (empty? tree) 20 | result-list 21 | (copy-to-list (left-branch tree) 22 | (cons (entry tree) 23 | (copy-to-list (right-branch tree) 24 | result-list)))))] 25 | (copy-to-list tree '()))) 26 | ; 27 | ;A) Question: 28 | ; Do the two procedures produce the same result for every tree? 29 | ; If not, how do the results differ? 30 | ; What lists do the two procedures produce for the trees in figure 2.16? 31 | ; 32 | ; Answer: 33 | ; The same result is returned for every tree. An in order list 34 | ; is the result. 35 | ; The result is '(1 3 5 7 9 11) 36 | ; 37 | ; 38 | ;B) Question: 39 | ; Do the two procedures have the same order of growth 40 | ; in the number of steps required to convert a balanced 41 | ; tree with n elements to a list? 42 | ; If not, which one grows more slowly? 43 | ; 44 | ; Answer: 45 | ; There is no difference. Both O(n) 46 | 47 | (def fig216a (make-tree 7 48 | (make-tree 3 49 | (make-tree 1 '() '()) 50 | (make-tree 5 '() '())) 51 | (make-tree 9 52 | '() 53 | (make-tree 11 '() '())))) 54 | 55 | (def fig216b (make-tree 3 56 | (make-tree 1 '() '()) 57 | (make-tree 7 58 | (make-tree 5 '() '()) 59 | (make-tree 9 '() (make-tree 11 '() '()))))) 60 | 61 | (def fig216c (make-tree 5 62 | (make-tree 3 63 | (make-tree 1 '() '()) 64 | '()) 65 | (make-tree 9 66 | (make-tree 7 '() '()) 67 | (make-tree 11 '() '())))) 68 | (println (tree->list-1 fig216a)) 69 | (println (tree->list-2 fig216a)) 70 | (println (tree->list-1 fig216b)) 71 | (println (tree->list-2 fig216b)) 72 | (println (tree->list-1 fig216c)) 73 | (println (tree->list-2 fig216c)) 74 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_64.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.64 2 | ; 3 | 4 | (defn entry [tree] (first tree)) 5 | (defn left-branch [tree] (second tree)) 6 | (defn right-branch [tree] (nth tree 2)) 7 | (defn make-tree [entry left right] 8 | (list entry left right)) 9 | 10 | (defn quotient [x y] 11 | (int (/ x y))) 12 | 13 | (defn partial-tree [elts n] 14 | (if (= n 0) 15 | (cons '() elts) 16 | (let [left-size (quotient (- n 1) 2) 17 | left-result (partial-tree elts left-size) 18 | left-tree (first left-result) 19 | non-left-elts (rest left-result) 20 | right-size (- n (+ left-size 1)) 21 | this-entry (first non-left-elts) 22 | right-result (partial-tree (rest non-left-elts) right-size) 23 | right-tree (first right-result) 24 | remaining-elts (rest right-result)] 25 | (cons (make-tree this-entry left-tree right-tree) 26 | remaining-elts)))) 27 | 28 | (defn list->tree [elements] 29 | (first (partial-tree elements (count elements)))) 30 | 31 | 32 | ; A) 33 | ; Question: 34 | ; Write a short paragraph explaining as clearly 35 | ; as you can how partial-tree works. Draw the 36 | ; tree produced by list->tree for the list (1 3 5 7 9 11). 37 | ; 38 | ; Answer: 39 | ; partial-tree divides the input list into two sub lists, a left 40 | ; and right list. Then it calls itself and keeps dividing lists 41 | ; into left and right elements. It uses these sublists to build 42 | ; sub trees which are all combined to create overall tree 43 | ; 5 44 | ; / \ 45 | ; 1 9 46 | ; \ / \ 47 | ; 3 7 11 48 | ; B) Question: 49 | ; What is the order of growth in the number of steps 50 | ; required by list->tree to convert a list of n elements? 51 | ; 52 | ; Answer: 53 | ; O(n) 54 | 55 | (println (list->tree '(1 3 5 7 9 11))) 56 | -------------------------------------------------------------------------------- /clojure/section2.3/ex2_66.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.66 2 | ; 3 | ; Implement a lookup procedure which works on binary trees 4 | ; 5 | 6 | (defn make-record [k v] 7 | (list k v)) 8 | (defn get-key [record] 9 | (first record)) 10 | (defn get-value [record] 11 | (second record)) 12 | 13 | (defn entry [tree] (first tree)) 14 | (defn left-branch [tree] (second tree)) 15 | (defn right-branch [tree] (nth tree 2)) 16 | (defn make-tree [entry left right] 17 | (list entry left right)) 18 | 19 | (defn lookup [given-key tree-of-records] 20 | (if (empty? tree-of-records) false 21 | (let [actual-key (get-key (entry tree-of-records))] 22 | (cond (= given-key actual-key) true 23 | (< given-key actual-key) 24 | (lookup given-key (left-branch tree-of-records)) 25 | (> given-key actual-key) 26 | (lookup given-key (right-branch tree-of-records)))))) 27 | 28 | ; lookup is the same as element-of-set? for 29 | ; binary trees 30 | -------------------------------------------------------------------------------- /clojure/section2.4/ex2_73_multimethods.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.73 done with multimethods 2 | 3 | (use 'clojure.test) 4 | 5 | ;{{{Needed functions for deriv example 6 | (defn variable? [e] (symbol? e)) 7 | 8 | (defn same-variable? [v1 v2] 9 | (and (variable? v1) (variable? v2) (= v1 v2))) 10 | 11 | (defn =number? [x n] 12 | (and (number? x) (= x n))) 13 | ;}}} 14 | 15 | ;{{{ Constructor and selectors for sums 16 | (defn make-sum [a1 a2] 17 | (cond (=number? a1 0) a2 18 | (=number? a2 0) a1 19 | (and (number? a1) (number? a2)) (+ a1 a2) 20 | :else (list '+ a1 a2))) 21 | 22 | (defn addend [s] (second s)) 23 | 24 | (defn augend [s] (first (rest (rest s)))) 25 | ;}}} 26 | 27 | ;{{{ Constructors and selectors for products 28 | (defn make-product [m1 m2] 29 | (cond (or (=number? m1 0) (=number? m2 0)) 0 30 | (=number? m1 1) m2 31 | (=number? m2 1) m1 32 | (and (number? m1) (number? m2)) (* m1 m2) 33 | :else (list '* m1 m2))) 34 | 35 | (defn multiplier [p] (second p)) 36 | 37 | (defn multiplicand [p] (first (rest (rest p)))) 38 | ;}}} 39 | 40 | (defn operator [exp] (first exp)) 41 | (defn operands [exp] (rest exp)) 42 | 43 | ; Define multimethod for taking derivatives 44 | (defmulti do-deriv (fn [exp v] (operator exp))) 45 | 46 | (defmethod do-deriv '+ 47 | [exp v] 48 | (make-sum (deriv (addend exp) v) 49 | (deriv (augend exp) v))) 50 | 51 | (defmethod do-deriv '* 52 | [exp v] 53 | (make-sum 54 | (make-product (multiplier exp) 55 | (deriv (multiplicand exp) v)) 56 | (make-product (deriv (multiplier exp) v) 57 | (multiplicand exp)))) 58 | 59 | (defn deriv [exp v] 60 | (cond (number? exp) 0 61 | (variable? exp) (if (same-variable? exp v) 1 0) 62 | :else (do-deriv exp v))) 63 | 64 | (deftest can-deriv-using-functions-from-table 65 | (is (= 1 (do-deriv '(+ x 3) 'x))) 66 | (is (= 3 (do-deriv '(* x 3) 'x)))) 67 | 68 | (deftest can-call-deriv-directly 69 | (is (= 1 (deriv '(+ x 3) 'x))) 70 | (is (= 'y (deriv '(* x y) 'x))) 71 | (is (= 4 (deriv '(+ (* x 3) x) 'x)))) 72 | 73 | (run-tests) 74 | 75 | ; vim: set foldmethod=marker: 76 | -------------------------------------------------------------------------------- /clojure/section2.4/ex2_75.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.75 2 | ; 3 | ; Implement the constructor make-from-mag-ang in message 4 | ; passing style. 5 | 6 | (defn make-from-mag-ang [mag ang] 7 | (fn [op] (cond (= op 'real-part) (* mag (Math/cos ang)) 8 | (= op 'imag-part) (* mag (Math/sin ang)) 9 | (= op 'magnitude) mag 10 | (= op 'angle) ang 11 | :else (Error. (str "Unknown op -- MAKE-FROM-MAG-ANG " op))))) 12 | -------------------------------------------------------------------------------- /clojure/section2.4/ex2_76.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.76 2 | ; 3 | ; For each of the below strategies, describe the changes 4 | ; that must be made to a system in order to add new types 5 | ; or new operations. Which organizaion would be the most 6 | ; appropriate for aa system in which new types must be often 7 | ; added? Which would be the most appropriate for a system 8 | ; in which new operations must often be added? 9 | ; 10 | ;1) generic operations with explicit dispatch 11 | ; - Hard to add new types, need to go and 12 | ; modify each procedure. Every procedure 13 | ; knows about every type. 14 | ; 15 | ;2) data-directed style 16 | ; - All types isolated from other types. 17 | ; - Need to write generic procedure which looks up 18 | ; what procedure should actually be called based 19 | ; on arguments. 20 | ; 21 | ;3) message-passing style 22 | ; - Need to just add a new object which 23 | ; knows how to handle different messages. 24 | ; 25 | ; Strategy 1 is a lot of work for adding new types and new operations. 26 | ; Strategy 2 you need to install the new type still. Nothing else has to change. 27 | ; Strat 3 you only create the new type. You don't need to do anything else. 28 | ; 29 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_77.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.77 2 | 3 | ; This works because magintude looks at its argument 4 | ; and figures out based on the type of the argument what 5 | ; selector should be called. 6 | ; 7 | ; First apply-generic is used to get into the 'complex 8 | ; package. Then another apply-generic brings us into 9 | ; the rectangular package which is where the correct magnitude 10 | ; would be invoked. 11 | ; 12 | ; apply-generic is called twice. 13 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_78.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.78 2 | 3 | ; Modify below attach-tag, type-tag, and contents from section 2.4.2 4 | ; to work without having to tag our 'scheme-number type with 'scheme-number. 5 | ; Use built-in functions to identify numbers instead. 6 | 7 | (use 'clojure.test) 8 | 9 | (defn attach-tag [tt contents] 10 | (if (number? contents) contents 11 | (cons tt contents))) 12 | 13 | (defn type-tag [datum] 14 | (cond (number? datum) 'scheme-number 15 | (seq? datum) (first datum) 16 | :else (Error. (str "Bad tagged datum -- TYPE-TAG " datum)))) 17 | 18 | (defn contents [datum] 19 | (cond (number? datum) datum 20 | (seq? datum) (rest datum) 21 | :else (Error. (str "Bag tagged datum -- CONTENTS " datum)))) 22 | 23 | (deftest test-attach-tag 24 | (is (= 4 (attach-tag 'scheme-number 4))) 25 | (is (= '(rational 3 5) (attach-tag 'rational '(3 5))))) 26 | 27 | (deftest test-type-tag 28 | (is (= 'scheme-number (type-tag 4))) 29 | (is (= 'rational (type-tag '(rational 3 5))))) 30 | 31 | (deftest test-contents 32 | (is (= 4 (contents 4))) 33 | (is (= '(3 5) (contents '(rational 3 5))))) 34 | 35 | (run-tests) 36 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_79.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.79 2 | ; 3 | ; The below code wont run. Have not acctually defined all of the 4 | ; procedures used by the below code. I am treating this as 5 | ; more of a thought exercise with some example code. 6 | 7 | (defn equ? [x y] 8 | (apply-generic 'equ? x y)) 9 | 10 | ; Put this with the scheme-number installers 11 | (put 'equ? '(scheme-number scheme-number) 12 | (fn [x y] (= x y))) 13 | 14 | ; Put this with the rational package installers 15 | (put 'equ? '(rational rational) 16 | (fn [x y] (= (* (numer x) (denom y)) 17 | (* (numer y) (numer x))))) 18 | 19 | ; Put in complex installers 20 | (put 'equ? '(complex complex) 21 | (fn [x y] (and (= (real-part x) (real-part y)) 22 | (= (imag-part x) (imag-part y))))) 23 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_80.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.80 2 | ; 3 | ; The below code wont run. Have not acctually defined all of the 4 | ; procedures used by the below code. I am treating this as 5 | ; more of a thought exercise with some example code. 6 | 7 | (defn my-zero? [x] 8 | (apply-generic 'my-zero? x)) 9 | 10 | ; Install for orginary numbers 11 | (put 'my-zero? '(scheme-number) 12 | (zero?)) 13 | 14 | ; install for rational numbers 15 | (put 'my-zero? '(rational) 16 | (fn [x] (zero? (numer x)))) 17 | 18 | ; install for complex numbers 19 | (put 'my-zero? '(complex) 20 | (fn [x] (and (zero? (real-part complex)) 21 | (zero? (imag-part complex))))) 22 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_81.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.81 2 | 3 | ;******************************************************* 4 | ; I made no attempt at getting code to run, treating 5 | ; as a thought exercise 6 | ;******************************************************* 7 | 8 | ; a) 9 | ; In the example given there is a generic 'exp function 10 | ; which has been defined for 'scheme-numbers 11 | ; but not for 'complex numbers. This is important to note. 12 | ; 13 | ; Louis has also added two coercions, one scheme-number->scheme-number 14 | ; and complex->complex. 15 | ; 16 | ; The first step that 'apply-generic tries to do is look up 17 | ; a procedure to apply based off what types the inputs are. 18 | ; - If it finds a procedure it then applys it. 19 | ; - If it does not find a procedure then it attemps to convert 20 | ; the arguments to each others types, and if the conversion works 21 | ; calls 'apply-generic with the newly convereted argument. 22 | ; 23 | ; With Louis added coercions when the generic 'exp procedure 24 | ; is called with two 'complex numbers, it will then call 'apply-generic. 25 | ; 'apply-generic will fail looking up a specific 'exp function 26 | ; for inputs of 'complex type (this operation has only been defined 27 | ; for 'scheme-numbers). 'apply-generic will then look to see 28 | ; if it can convert either 'complex number into the other arguments type 29 | ; (in this case another 'complex number). 'apply-generic will see that 30 | ; it can, will then perform the conversion and call itself with 31 | ; the newly converted argument. Then this loop will start over again. 32 | ; 33 | 34 | 35 | ; b) 36 | ; Nothing needed to be done. If there were not coercions defined 37 | ; between to go from type-x->type-x then 'apply-generic would 38 | ; work as expected 39 | ; 40 | ; c) Give an 'apply-generic that does not try to coerce 41 | ; if two arguments are the same type. 42 | 43 | (defn apply-generic [op & args] 44 | (let [type-tags (map type-tag args) 45 | no-method-error #(Error. (str "No method for these types " (list op type-tags))) 46 | proc (get op type-tags)] 47 | (if proc 48 | (apply proc (map contents args)) 49 | (if (= (count args) 2) 50 | (let [type1 (first type-tags) 51 | type2 (second type-tags) 52 | a1 (first args) 53 | a2 (second args) 54 | t1->t2 (get-coercion type1 type2) 55 | t2->t1 (get-coercion type2 type1)] 56 | (cond (= type1 type2) (no-method-error) 57 | t1->t2 (apply-generic op (t1->t2 a1) a2) 58 | t2->t1 (apply-generic op a1 (t2->t1) a2) 59 | :else (Error. (str "No method for these types " (list op type-tags))))) 60 | (no-method-error))))) 61 | 62 | 63 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_82.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.82 2 | 3 | ; predef some functions just to be get ride of errors 4 | (def get-coercion) 5 | (def type-tag) 6 | (def contents) 7 | 8 | 9 | ; This solution is flawed. It only trys to convert to the FIRST 10 | ; type to which all arguments can be coerced. There is a possibility 11 | ; that an operation might not be defined for that FIRST type 12 | ; and there may be a later type which all args can be converted to 13 | ; where the operation is defined. 14 | 15 | (defn all-can-convert-to? [target types] 16 | "Checks to see if all types can be converted to target type" 17 | (every? true? 18 | ((map (fn [t] (or (= t target) 19 | (get-coercion t target)))) 20 | types))) 21 | 22 | (defn find-a-common-type [types] 23 | "Takes a list of types and finds a single type they can 24 | all be converted into" 25 | (letfn [(first-true [bs ts] 26 | (cond (zero? (count bs)) nil 27 | (true? (first bs)) (first ts) 28 | :else (recur (rest bs) (rest ts))))] 29 | (map (fn [target] (all-can-convert-to? target types)) 30 | types))) 31 | 32 | (defn convert-all-to [desired-type args] 33 | "Converts all args to desired type" 34 | (map (fn [a] 35 | (let [current-type (type-tag a)] 36 | (if (= desired-type current-type) 37 | a 38 | ((get-coercion current-type desired-type) a)))) 39 | args)) 40 | 41 | (defn apply-generic [op & args] 42 | (let [type-tags (map type-tag args) 43 | no-method-error #(Error. (str "No method for these types " (list op type-tags))) 44 | proc (get op type-tags)] 45 | (if proc 46 | (apply proc (map contents args)) 47 | (let [common-type (find-a-common-type type-tags)] 48 | (if common-type 49 | (apply 50 | (apply-generic 51 | (list* op 52 | (convert-all-to common-type args))))) 53 | (no-method-error))))) 54 | 55 | ; Question: Give an example of when this (and the previous 2 arg version) fail 56 | ; 57 | ; Neither this nor the two argument version take into account if there is 58 | ; a type to which all arguments can be converted to but is not a 59 | ; type of the arguments. 60 | ; 61 | ; An two argument example. 62 | ; arg1 type is square 63 | ; arg2 type is circle 64 | ; operation is (sum-areas) 65 | ; 66 | ; A circle can't be converted to a square and a square cannot be converted to 67 | ; a circle. They could both be converted to shape. sum-areas could be defined 68 | ; for shapes 69 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_83.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.83 2 | 3 | ; write functions to coerce integer -> rational -> real -> complex 4 | ; Leaving this as more of a thought exercise, code clearly 5 | ; does not work. 6 | 7 | ; Put in integer package 8 | (defn integer->rational [x] 9 | (make-rational x 1)) 10 | 11 | (put 'raise '(integer) #(integer->rational %)) 12 | 13 | ; Put in rational package 14 | (defn rational->real [x] 15 | (make-real (double (/ (numer x) (denom x))))) 16 | 17 | (put 'raise '(rational) #(rational->real %)) 18 | 19 | ; Put in real package 20 | (defn real->complex [x] 21 | (make-from-real-imag x 0)) 22 | 23 | (put 'raise '(real) #(real->complex %)) 24 | 25 | (defn raise [x] 26 | ((get 'raise (type-tag x)) x)) 27 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_84.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.84 2 | 3 | ; Going to use only two argument version of apply-generic 4 | ; for simplicity 5 | 6 | ; defs to get it to not give errors when parsing. 7 | (def type-tag) 8 | (def contents) 9 | (def get-coercion) 10 | 11 | (defn apply-generic [op & args] 12 | (letfn [(multi-raise [begin target] 13 | "recursivly tries to coerce begin to be same type as target" 14 | (let [begin-type (type-tag begin) 15 | target-type (type-tag target)] 16 | (cond (= begin-type target-type) begin 17 | (get 'raise (list begin-type)) 18 | (multi-raise ((get 'raise (list begin-type)) begin target))) 19 | :else nil)) 20 | (no-method-error [tags] 21 | (Error. (str "No method for these types " (list op tags))))] 22 | (let [type-tags (map type-tag args) 23 | proc (get op type-tags)] 24 | (if proc 25 | (apply proc (map contents args)) 26 | (if (= (count args) 2) 27 | (let [type1 (first type-tags) 28 | type2 (second type-tags) 29 | a1 (first args) 30 | a2 (second args) 31 | t1->t2 (get-coercion type1 type2) 32 | t2->t1 (get-coercion type2 type1)] 33 | (cond (= type1 type2) (no-method-error type-tags) 34 | (multi-raise a1 a2) (apply-generic op (multi-raise a1 a2) a2) 35 | (multi-raise a2 a1) (apply-generic op a1 (multi-raise a2 a1)) 36 | :else (Error. (str "No method for these types " (list op type-tags))))) 37 | (no-method-error type-tags)))))) 38 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_85.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.85 2 | ; 3 | ; Write a generic 'drop (I called it drop-type) procedure which 4 | ; simplifies numeric types to simpler types if possible 5 | ; 6 | ; Basically the opposite of 'raise 7 | 8 | (use 'clojure.contrib.math) 9 | 10 | (def type-tag) 11 | (def contents) 12 | (def get-coercion) 13 | (def raise) 14 | (defn put-op [x y z]) 15 | (def make-real) 16 | (def make-rational) 17 | (def make-scheme-number) 18 | (def real-part) 19 | (def imag-part) 20 | (def numer) 21 | (def denom) 22 | 23 | ; Functions for dropping types 24 | ; complex -> real -> rational -> integer 25 | 26 | (put-op 'project '(complex) 27 | (fn [x] (make-real (real-part x)))) 28 | 29 | ; Not really sure what to do for this one 30 | ; and I don't feel like thinking too hard about it 31 | ; so skipping 32 | ;(put-op 'project '(real) 33 | ; (fn [x] 34 | ; (make-rational))) 35 | 36 | (put-op 'project '(rational) 37 | (fn [x] (make-scheme-number 38 | (round (/ (numer x) 39 | (denom x)))))) 40 | 41 | ; Calling drop-type since drop is keyword in Clojure 42 | (defn drop-type [higher] 43 | "Takes numeric type higher and tries to lower it to a subtype" 44 | (let [project-func (get 'project (type-tag higher))] 45 | (if project-func 46 | (let [lower (project-func higher)] 47 | (if (= lower (raise lower)) 48 | (recur lower) 49 | higher)) 50 | higher))) 51 | 52 | (defn apply-generic [op & args] 53 | (letfn [(multi-raise [begin target] 54 | "recursivly tries to coerce begin to be same type as target" 55 | (let [begin-type (type-tag begin) 56 | target-type (type-tag target)] 57 | (cond (= begin-type target-type) begin 58 | (get 'raise (list begin-type)) 59 | (multi-raise ((get 'raise (list begin-type)) begin target))) 60 | :else nil)) 61 | (no-method-error [tags] 62 | (Error. (str "No method for these types " (list op tags))))] 63 | (let [type-tags (map type-tag args) 64 | proc (get op type-tags)] 65 | (if proc 66 | (drop-type (apply proc (map contents args))) ; Only line that needed to change to get types to be lowered 67 | (if (= (count args) 2) 68 | (let [type1 (first type-tags) 69 | type2 (second type-tags) 70 | a1 (first args) 71 | a2 (second args) 72 | t1->t2 (get-coercion type1 type2) 73 | t2->t1 (get-coercion type2 type1)] 74 | (cond (= type1 type2) (no-method-error type-tags) 75 | (multi-raise a1 a2) (apply-generic op (multi-raise a1 a2) a2) 76 | (multi-raise a2 a1) (apply-generic op a1 (multi-raise a2 a1)) 77 | :else (Error. (str "No method for these types " (list op type-tags))))) 78 | (no-method-error type-tags)))))) 79 | -------------------------------------------------------------------------------- /clojure/section2.5/ex2_86.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 2.86 2 | 3 | ; Complex numbers have two representations, rectangular and polar. 4 | ; If we do work at that level of abstraction then code which uses 5 | ; complex numbers will simply work. 6 | ; 7 | ; Methods called at the rectangular/polar accessor level are 8 | ; cos, sin, square, atan. This means we would need to implement 9 | ; a generic version of each of those four functions. 10 | ; 11 | ; Then whatever number types we wanted to allow to be part of 12 | ; a complex number would need to implement a specific version 13 | ; of those four functions in order to work properly in our 14 | ; system. 15 | -------------------------------------------------------------------------------- /clojure/section3.1/ex3_1.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.1 2 | 3 | (use 'clojure.test) 4 | 5 | ; Should this be doing using refs instead? 6 | (defn make-accumulator [starting-value] 7 | (let [initial (atom starting-value)] 8 | (fn [additional] (swap! initial (partial + additional))))) 9 | 10 | 11 | (deftest accumulator-accumulates 12 | (let [accum (make-accumulator 10) 13 | other (make-accumulator 5)] 14 | (is (= 15 (accum 5))) 15 | (is (= 25 (accum 10))) 16 | (is (= 6 (other 1))))) 17 | 18 | (run-tests) 19 | -------------------------------------------------------------------------------- /clojure/section3.1/ex3_2.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.2 2 | 3 | (use 'clojure.test) 4 | 5 | (defn make-monitored [f] 6 | (let [num-calls (atom 0)] 7 | (fn [x] 8 | (cond (= x 'how-many-calls?) @num-calls 9 | (= x 'reset-calls) (swap! num-calls (fn [x] 0)) 10 | :else (do 11 | (swap! num-calls inc) 12 | (f x)))))) 13 | 14 | (deftest test-make-monitored 15 | (let [m-inc (make-monitored inc)] 16 | (is (= 1 (m-inc 0))) 17 | (is (= 5 (m-inc 4))) 18 | (is (= 2 (m-inc 'how-many-calls?))) 19 | (m-inc 'reset-calls) 20 | (is (= 0 (m-inc 'how-many-calls?))))) 21 | 22 | (run-tests) 23 | -------------------------------------------------------------------------------- /clojure/section3.1/ex3_3.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.3 2 | 3 | (use 'clojure.test) 4 | 5 | (defn make-account [starting-balance password] 6 | (let [balance (atom starting-balance)] 7 | (letfn [(withdraw [amount] 8 | (if (>= @balance amount) 9 | (do (swap! balance #(- % amount)) 10 | @balance) 11 | "insufficient funds")) 12 | (deposit [amount] 13 | (swap! balance #(+ % amount)) 14 | @balance) 15 | (dispatch [supplied-pw action] 16 | (if (= supplied-pw password) 17 | (cond (= action 'withdraw) withdraw 18 | (= action 'deposit) deposit 19 | :else (Error. (str "Unknown request -- MAKE-ACCOUNT " action))) 20 | (fn [x] "incorrect password")))] 21 | dispatch))) 22 | 23 | (deftest test-with-correct-password 24 | (let [acc (make-account 100 'secret-password)] 25 | (is (= 60 ((acc 'secret-password 'withdraw) 40))) 26 | (is (= "insufficient funds" ((acc 'secret-password 'withdraw) 400))) 27 | (is (= 100 ((acc 'secret-password 'deposit) 40))))) 28 | 29 | (deftest test-with-incorrect-password 30 | (let [acc (make-account 100 'secret-password)] 31 | (is (= "incorrect password" ((acc 'wrong-pw 'deposit) 50))))) 32 | 33 | (run-tests) 34 | -------------------------------------------------------------------------------- /clojure/section3.1/ex3_4.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.4 2 | 3 | (use 'clojure.test) 4 | 5 | (defn make-account [starting-balance password] 6 | (let [balance (atom starting-balance) 7 | attempts (atom 0)] 8 | (letfn [(withdraw [amount] 9 | (if (>= @balance amount) 10 | (do (swap! balance #(- % amount)) 11 | @balance) 12 | "insufficient funds")) 13 | (deposit [amount] 14 | (swap! balance #(+ % amount)) 15 | @balance) 16 | (dispatch [supplied-pw action] 17 | (if (= supplied-pw password) 18 | (do 19 | (swap! attempts (fn [x] 0)) 20 | (cond (= action 'withdraw) withdraw 21 | (= action 'deposit) deposit 22 | :else (Error. (str "Unknown request -- MAKE-ACCOUNT " action)))) 23 | (do 24 | (swap! attempts inc) 25 | (if (> @attempts 7) 26 | (fn [x] "SIREN SIREN - cops called sucka!") 27 | (fn [x] "incorrect password")))))] 28 | dispatch))) 29 | 30 | (deftest test-with-correct-password 31 | (let [acc (make-account 100 'secret-password)] 32 | (is (= 60 ((acc 'secret-password 'withdraw) 40))) 33 | (is (= "insufficient funds" ((acc 'secret-password 'withdraw) 400))) 34 | (is (= 100 ((acc 'secret-password 'deposit) 40))))) 35 | 36 | (deftest should-call-cops-after-seven-bad-passwords 37 | (let [acc (make-account 100 'secret-password)] 38 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 39 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 40 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 41 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 42 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 43 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 44 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 45 | (is (= "SIREN SIREN - cops called sucka!" ((acc 'wrong-pw 'withdraw) 10))))) 46 | 47 | (deftest should-reset-cop-call-after-correct-password 48 | (let [acc (make-account 100 'secret-password)] 49 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 50 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 51 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 52 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 53 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 54 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 55 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))) 56 | (is (= 80 ((acc 'secret-password 'withdraw) 20))) 57 | (is (= "incorrect password" ((acc 'wrong-pw 'withdraw) 10))))) 58 | 59 | (run-tests) 60 | 61 | -------------------------------------------------------------------------------- /clojure/section3.1/ex3_5.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.5 2 | 3 | (use 'clojure.contrib.math) 4 | 5 | (defn monte-carlo [trials experiment] 6 | (loop [trials-remaining trials 7 | trials-passed 0] 8 | (cond (= trials-remaining 0) (/ trials-passed trials) 9 | (experiment) (recur (dec trials-remaining) (inc trials-passed)) 10 | :else (recur (dec trials-remaining) trials-passed)))) 11 | 12 | (defn random-in-range [low high] 13 | (+ low (rand (- high low)))) 14 | 15 | (defn rectangle-area [x1 x2 y1 y2] 16 | (abs (* (- x2 x1) (- y2 y1)))) 17 | 18 | (defn estimate-integral [p x1 x2 y1 y2 trials] 19 | (letfn 20 | [(experiment [] 21 | (let [x (random-in-range x1 x2) 22 | y (random-in-range y1 y2)] 23 | (p x y)))] 24 | (* (rectangle-area x1 x2 y1 y2) 25 | (monte-carlo trials experiment)))) 26 | 27 | (defn square [x] (expt x 2)) 28 | 29 | (defn estimate-pi-using-area-unit-circle [] 30 | (letfn [(unit-circle-predicate [x y] 31 | (<= (+ (square x) (square y)) 1))] 32 | (double 33 | (estimate-integral 34 | unit-circle-predicate -1.0 1.0 -1.0 1.0 10000)))) 35 | 36 | 37 | (time (dotimes [i 5] 38 | (println "Pi estimate =" (estimate-pi-using-area-unit-circle)))) 39 | -------------------------------------------------------------------------------- /clojure/section3.1/ex3_6.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.6 2 | ; 3 | ; Create a random function which generates a psuedo-random 4 | ; sequence which can be reset 5 | 6 | (use 'clojure.test) 7 | 8 | (defn- rand-update [x] 9 | (let [a 5.2 b 3.1 m 1.5] 10 | (mod (+ (* a x) b) m))) 11 | 12 | ;(def #^{:private true} current-random (atom 5.0)) 13 | (def my-rand 14 | (let [current-random (atom 5.0)] 15 | (fn 16 | ([] 17 | (swap! current-random rand-update) 18 | @current-random) 19 | ([action] 20 | (if (= action :generate) (my-rand))) 21 | ([action seed] 22 | (if (= action :reset) (swap! current-random (fn [x] seed))))))) 23 | 24 | 25 | (deftest test-reset-random-sequence 26 | (my-rand :reset 6.0) 27 | (let [orig (list (my-rand :generate) 28 | (my-rand :generate) 29 | (my-rand :generate))] 30 | (my-rand :reset 6.0) 31 | (let [after-reset (list (my-rand :generate) 32 | (my-rand :generate) 33 | (my-rand :generate))] 34 | (is (= orig after-reset))))) 35 | 36 | (run-tests) 37 | -------------------------------------------------------------------------------- /clojure/section3.1/ex3_7.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.7 2 | ; Add the ability to have joint bank accounts to exercise 3.3. 3 | 4 | (use 'clojure.test) 5 | 6 | ;{{{ make-account from exercise 3.3 7 | (defn make-account [starting-balance password] 8 | (let [balance (atom starting-balance)] 9 | (letfn [(withdraw [amount] 10 | (if (>= @balance amount) 11 | (do (swap! balance #(- % amount)) 12 | @balance) 13 | "insufficient funds")) 14 | (deposit [amount] 15 | (swap! balance #(+ % amount)) 16 | @balance) 17 | (dispatch [supplied-pw action] 18 | (if (= supplied-pw password) 19 | (cond (= action 'withdraw) withdraw 20 | (= action 'deposit) deposit 21 | :else (Error. (str "Unknown request -- MAKE-ACCOUNT " action))) 22 | (fn [x] "incorrect password")))] 23 | dispatch))) 24 | ;}}} 25 | 26 | 27 | (defn make-joint 28 | "Makes a bank account jointly owned" 29 | [account owners-pw joint-pw] 30 | (fn [password action] 31 | (if (= joint-pw password) (account owners-pw action) 32 | (Error. (str "BAD JOINT PASSWORD -- " password))))) 33 | 34 | (deftest can-make-joint-account 35 | (let [orig-acc (make-account 100 :password) 36 | joint-acc (make-joint orig-acc :password :joint)] 37 | (is (= 91 ((orig-acc :password 'withdraw) 9))) 38 | (is (= 80 ((joint-acc :joint 'withdraw) 11))))) 39 | 40 | (run-tests) 41 | 42 | ; vim:set foldmethod=marker 43 | -------------------------------------------------------------------------------- /clojure/section3.1/ex3_8.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.8 2 | ; 3 | ; Design a function which will show order arguments are evaluated 4 | 5 | ; First pass, this does work 6 | (def #^{:private true} flag (atom 5)) 7 | (defn f [x] 8 | (if (compare-and-set! flag 5 x) 0 9 | (if (= 0 @flag) 0 10 | 1))) 11 | 12 | ; Prints 0 if arguments evaluated left to right 13 | ; and 1 if arguments evaluated right to left 14 | (println (+ (f 0) (f 1))) 15 | 16 | 17 | ; Second shot 18 | (def f 19 | (let [check (atom 1)] 20 | (fn [x] 21 | (swap! flag #(* % x)) 22 | @flag))) 23 | (println (+ (f 0) (f 1))) 24 | -------------------------------------------------------------------------------- /clojure/section3.3/.gitignore: -------------------------------------------------------------------------------- 1 | classes 2 | lib 3 | *.clj~ 4 | -------------------------------------------------------------------------------- /clojure/section3.3/project.clj: -------------------------------------------------------------------------------- 1 | (defproject SICP-section3-5 "1.0.0-SNAPSHOT" 2 | :description "Solutions to section 3.5 of SICP" 3 | :dependencies [[org.clojure/clojure "1.2.0-master-SNAPSHOT"] 4 | [org.clojure/clojure-contrib "1.2.0-master-SNAPSHOT"]] 5 | :dev-dependencies [[swank-clojure "1.2.1"]]) 6 | -------------------------------------------------------------------------------- /clojure/section3.3/src/agenda.clj: -------------------------------------------------------------------------------- 1 | ; Agenda for circuit simulator 2 | 3 | ; I didn't actually do this in a similar fashion as in the book. 4 | ; The order actions are added to the agenda is not the order things 5 | ; at the same time get executed. 6 | (ns agenda) 7 | (def inverter-delay 2) 8 | (def and-gate-delay 3) 9 | (def or-gate-delay 5) 10 | 11 | (defn make-agenda [] 12 | (atom {:cur-time 0 :items '()})) 13 | 14 | (def the-agenda (make-agenda)) 15 | 16 | (defn current-time [agenda] 17 | (:cur-time @agenda)) 18 | 19 | (defn set-current-time! [agenda time] 20 | (swap! agenda #(assoc % :cur-time time))) 21 | 22 | (defn segments [agenda] 23 | (:items @agenda)) 24 | 25 | (defn set-segments! [agenda segments] 26 | (swap! agenda #(assoc % :items segments))) 27 | 28 | (defn first-segment [agenda] 29 | (first (segments agenda))) 30 | 31 | (defn rest-segments [agenda] 32 | (rest (segments agenda))) 33 | 34 | (defn empty-agenda? [agenda] 35 | (empty? (segments agenda))) 36 | 37 | (defn make-time-segment [time action] 38 | {:time time :action action}) 39 | (defn segment-time [s] (:time s)) 40 | (defn segment-action [s] (:action s)) 41 | 42 | (defn add-to-agenda! [time action agenda] 43 | (letfn [(add-to-segments 44 | ([segments] 45 | (let [item (make-time-segment time action)] 46 | (sort-by :time (cons item segments)))))] 47 | (set-segments! agenda 48 | (add-to-segments (segments agenda))))) 49 | 50 | (defn after-delay 51 | [delay action] 52 | (add-to-agenda! (+ delay (current-time the-agenda)) 53 | action 54 | the-agenda)) 55 | 56 | (defn remove-first-agenda-item! [agenda] 57 | (set-segments! agenda (rest-segments agenda))) 58 | 59 | (defn first-agenda-item [agenda] 60 | (if (empty-agenda? agenda) 61 | (Error. "Agenda is empty -- FIRST-AGENDA-ITEM") 62 | (let [first-seg (first-segment agenda)] 63 | (set-current-time! agenda (segment-time first-seg)) 64 | (segment-action first-seg)))) 65 | 66 | (defn propagate 67 | [] 68 | (if (empty-agenda? the-agenda) 69 | :done 70 | (let [first-item (first-agenda-item the-agenda)] 71 | (first-item) 72 | (remove-first-agenda-item! the-agenda) 73 | (recur)))) 74 | -------------------------------------------------------------------------------- /clojure/section3.3/src/deque.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.23 2 | (ns deque) 3 | 4 | (declare make-deque 5 | empty-deque? 6 | front-deque 7 | rear-deque 8 | front-insert-deque! 9 | rear-insert-deque! 10 | front-delete-deque! 11 | rear-delete-deque!) 12 | 13 | (defn make-deque [] 14 | (atom {:front :empty :rear :empty})) 15 | 16 | (defn empty-deque? [d] 17 | (and (= :empty (:front @d)) 18 | (= :empty (:rear @d)))) 19 | 20 | (defn set-front [d e] 21 | (swap! d assoc :front e)) 22 | 23 | (defn set-rear [d e] 24 | (swap! d assoc :rear e)) 25 | 26 | (defn rear [d] 27 | (:rear @d)) 28 | (defn front [d] 29 | (:front @d)) 30 | 31 | (defn set-prev [n e] 32 | (swap! n assoc :prev e)) 33 | 34 | (defn set-next [n e] 35 | (swap! n assoc :next e)) 36 | 37 | (defn make-neighbors 38 | [prev next] 39 | (set-prev next prev) 40 | (set-next prev next)) 41 | 42 | (defn get-elem [n] 43 | (:elem @n)) 44 | (defn get-next [n] 45 | (:next @n)) 46 | (defn get-prev [n] 47 | (:prev @n)) 48 | 49 | (defn make-node [e] 50 | (atom {:elem e :prev nil :next nil})) 51 | 52 | (defn add-first-elem [d e] 53 | (let [node (make-node e)] 54 | (set-front d node) 55 | (set-rear d node))) 56 | 57 | (defn rear-deque [d] 58 | (if (empty-deque? d) (Error. "REAR-DEQUE called on empty queue") 59 | (get-elem (rear d)))) 60 | 61 | (defn front-deque [d] 62 | (if (empty-deque? d) (Error. "FRONT-DEQUE called on empty queue") 63 | (get-elem (front d)))) 64 | 65 | (defn front-insert-deque! [d e] 66 | (if (empty-deque? d) (add-first-elem d e) 67 | (let [node (make-node e) 68 | prev-front (front d)] 69 | (make-neighbors node prev-front) 70 | (set-front d node))) 71 | d) 72 | 73 | (defn rear-insert-deque! [d e] 74 | (if (empty-deque? d) (add-first-elem d e) 75 | (let [node (make-node e) 76 | prev-rear (rear d)] 77 | (make-neighbors prev-rear node) 78 | (set-rear d node))) 79 | d) 80 | 81 | (defn empty! [d] 82 | (set-front d :empty) 83 | (set-rear d :empty)) 84 | 85 | (defn front-delete-deque! [d] 86 | (cond (empty-deque? d) (Error. "Already empty") 87 | (= (front d) (rear d)) (empty! d) 88 | :else (set-front d (get-next (front d))))) 89 | 90 | (defn rear-delete-deque! [d] 91 | (cond (empty-deque? d) (Error. "Already empty") 92 | (= (front d) (rear d)) (empty! d) 93 | :else (set-rear d (get-prev (rear d))))) 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_12.clj: -------------------------------------------------------------------------------- 1 | ;Exercise 3.12 2 | ;First response is 'b 3 | ; 4 | ;Second response is '(b c d) 5 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_13.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.13 2 | 3 | ; Dummy clojure function 4 | (defn make-cycle [x] 5 | (set-cdr! (last-pair x) x) 6 | x) 7 | 8 | ; Draw a box on pointer diagram for the structure z created by 9 | (def z (make-cycle (list 'a 'b 'c))) 10 | 11 | 12 | ; z --> * * * * * * * * * * * * * * * 13 | ; * a * *-->* b * *-->* c * *--| 14 | ; * * * * * * * * * * * * * * * | 15 | ; ^ | 16 | ; |--------------------------------- 17 | 18 | ; Q) What happens if we try to compute (last-pair z)? 19 | ; 20 | ; A) Infinate loop 21 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_14.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.14 2 | ; 3 | ; The following procedure is a mystery. What does it do? 4 | 5 | (defn mystery [x] 6 | (loop [x x, y '()] 7 | (if (nil? x) 8 | y 9 | (let [temp (next x)] 10 | (set-cdr! x y) 11 | (recur temp x))))) 12 | 13 | ; The procedure mystery reverses the sequence x and returns it. 14 | ; It also modifies the passed in sequence to simply be a list 15 | ; of its first element 16 | 17 | ; w -->* * * * * * * * * * * * * * * * * * * * 18 | ; * d * *-->* c * *-->* b * *-->* a * *-->nil 19 | ; * * * * * * * * * * * * * * * * * * * * 20 | ; ^ 21 | ; v -----------------------------------------| 22 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_15.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.15 2 | ; 3 | ; Draw box-point-diagrams to explain set-to-wow! behavior 4 | 5 | ; Pretend functions exist 6 | ;(defn set-to-wow! [s] 7 | ; (set-car! (car s) 'wow)) 8 | 9 | ; Prior to set-to-wow! call 10 | ; 11 | ; z1-->* * * * * 12 | ; * * * 13 | ; * | * | * 14 | ; v v 15 | ; * * * * * * * * * * 16 | ; x--->* * --->* * / * 17 | ; * | * * * * | * * * 18 | ; a b 19 | ; 20 | ; 21 | ; z2-->* * * * * * * * * * * * * * * 22 | ; * * --->* * --->* * / * 23 | ; * | * * * * | * * * * | * * * 24 | ; | a b 25 | ; | * | * * * * | * * * 26 | ; --------->* * --->* * / * 27 | ; * * * * * * * * * * 28 | ; 29 | ; After set-to-wow! call 30 | ; 31 | ; z1-->* * * * * 32 | ; * * * 33 | ; * | * | * 34 | ; v v 35 | ; * * * * * * * * * * 36 | ; x--->* * --->* * / * 37 | ; * | * * * * | * * * 38 | ; wow b 39 | ; 40 | ; 41 | ; z2-->* * * * * * * * * * * * * * * 42 | ; * * --->* * --->* * / * 43 | ; * | * * * * | * * * * | * * * 44 | ; | a b 45 | ; | * * * * * * | * * * 46 | ; --------->* * --->* * / * 47 | ; * | * * * * * * * * 48 | ; wow 49 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_16.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.16 2 | ; 3 | ; 4 | ; Show that Ben Bitdiddle's procedure to count pairs is flawed. 5 | ; 6 | ;(define (count-pairs x) 7 | ; (if (not (pair? x)) 8 | ; 0 9 | ; (+ (count-pairs (car x)) 10 | ; (count-pairs (cdr x)) 11 | ; 1))) 12 | ; 13 | ; Give example of 3 pair box-and-pointers that return 3, 4, 7, and 14 | ; never return. 15 | ; 16 | ; 17 | ; Returns 3 18 | ; 19 | ; z-->* * * * * * * * * * * * * * * 20 | ; * a * *->* b * *->* c * / * 21 | ; * * * * * * * * * * * * * * * 22 | ; 23 | ; Returns 4 24 | ; 25 | ; z-->* * * * * * * * * * * * * * * 26 | ; * a * *->* * *->* c * / * 27 | ; * * * * * * | * * * * * * * * 28 | ; | ^ 29 | ; -----------| 30 | ; Returns 7 31 | ; 32 | ; z-->* * * * * * * * * * * * * * * 33 | ; * * *->* * *->* c * / * 34 | ; * | * * * * * * * * * * * * * 35 | ; | ^ \ ^ 36 | ; ---------/ --------/ 37 | ; 38 | ; Never return 39 | ; 40 | ; z-->* * * * * * * * * * * * * * * 41 | ; * a * *->* b * *->* c * * 42 | ; * * * * * * * * * * * * * * * 43 | ; ^ | 44 | ; |-------------------------- 45 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_17.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.17 2 | ; 3 | ; Create a correct version of count-pairs from 3.16 4 | 5 | (ns ex3_17 6 | (:use mypair)) 7 | 8 | (defn has? [x es] 9 | (some #(= % x) es)) 10 | 11 | (defn atom? [x] 12 | (= clojure.lang.Atom (type x))) 13 | 14 | (defn count-pairs [x] 15 | (let 16 | [visited (atom '()) 17 | iter (fn iter [s] 18 | (cond (not (atom? s)) 0 19 | (has? s @visited) 0 20 | :else (do 21 | (swap! visited #(cons s %)) 22 | (+ 1 23 | (iter (cdr s)) 24 | (iter (car s))))))] 25 | 26 | (iter x))) 27 | 28 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_18.clj: -------------------------------------------------------------------------------- 1 | (ns ex3_18 2 | (:use mypair)) 3 | 4 | (defn has? [x es] 5 | (some #(= % x) es)) 6 | 7 | (defn cycles? [s] 8 | (loop [curr s, visited '()] 9 | (cond (has? curr visited) true 10 | (= nil (cdr curr)) false 11 | :else (recur 12 | (cdr curr) 13 | (cons curr visited))))) 14 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_19.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.19 2 | 3 | ; Keep traversing list, keep two pointers. 4 | ; advance once two spots, advance other one. 5 | ; If they ever match up you have a cycle. 6 | 7 | (ns ex3_19 8 | (:use mypair)) 9 | 10 | (defn cycles? [s] 11 | (loop [one s, two (cdr s)] 12 | (cond (= one two) true 13 | (or (= nil one) (= nil two)) false 14 | (= nil (cdr two)) false 15 | :else (recur (cdr one) (cdr (cdr two)))))) 16 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_22.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.22 2 | (ns ex3_22 3 | (:use mypair)) 4 | 5 | (defn make-queue [] 6 | (let [front-ptr (atom :empty) 7 | rear-ptr (atom :empty)] 8 | (letfn [(set-front-ptr! [x] (swap! front-ptr (fn [y] x))) 9 | (set-rear-ptr! [x] (swap! rear-ptr (fn [y] x))) 10 | (set-front-and-rear-ptr! [x] 11 | (set-front-ptr! x) 12 | (set-rear-ptr! x)) 13 | (empty-queue? [] 14 | (and (= :empty @front-ptr) (= :empty @rear-ptr))) 15 | (front [] 16 | (if (empty-queue?) (Error. "FRONT called with empty queue") 17 | (car @front-ptr))) 18 | (insert! [x] 19 | (let [e (make-pair x)] 20 | (if (empty-queue?) 21 | (do (set-front-and-rear-ptr! e) dispatch) 22 | (do (set-cdr! @rear-ptr e) 23 | (set-rear-ptr! e) 24 | dispatch)))) 25 | (delete! [] 26 | (if (empty-queue?) 27 | (Error. "DELETE! called with empty queue") 28 | (if (= @front-ptr @rear-ptr) 29 | (do (set-front-and-rear-ptr! :empty) dispatch) 30 | (do (set-front-ptr! (cdr @front-ptr)) dispatch)))) 31 | (dispatch 32 | ([action] 33 | (cond (= action :front) (front) 34 | (= action :delete!) (delete!) 35 | (= action :empty?) (empty-queue?) 36 | :else (Error. (str action "is not supported")))) 37 | ([action e] 38 | (cond (= action :insert!) (insert! e) 39 | :else (Error. (str action "is not supported")))))] 40 | dispatch))) 41 | 42 | ; Look at test/test_ex3_22 for examples of how to use 43 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_24.clj: -------------------------------------------------------------------------------- 1 | ; Solution to exercise 3.24 is in localtable.clj and 2 | ; is exercised in tests in test_localtable.clj 3 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_25.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.25 2 | 3 | (ns ex3_25 4 | (:require [localtable :as lt])) 5 | 6 | ; Simply wrap version of table which takes two keys and pass in 7 | ; list as first key and dummy value as second. 8 | 9 | (defn make-table [] 10 | (let [local-table (lt/make-table)] 11 | (letfn [(lookup [kees] ((local-table :lookup-proc) kees :zzz)) 12 | (insert [kees value] ((local-table :insert-proc!) kees :zzz value))] 13 | (fn [m] 14 | (cond (= m :lookup-proc) lookup 15 | (= m :insert-proc!) insert 16 | :else (Error. "Unknown operation -- TABLE" m)))))) 17 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_26.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.26 2 | ; 3 | ; Describe how you could define tables using a binary tree 4 | ; 5 | ; 6 | ; Answer: 7 | ; One way to do this would be to take the keys 8 | ; and combine them into a single key. Then use 9 | ; the single key to decide where to place the key 10 | ; and value in the binary tree. Each node of the 11 | ; binary tree would be a pair of combined keys and 12 | ; value. 13 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_27.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.27 2 | ; 3 | 4 | 5 | ; Q: Draw an environment diagram to analyze computation of (memo-fib 3) 6 | ; A: Not drawing it. 7 | 8 | ; Q: Explain why memo-fib computes nth Fibonacci number in number of steps 9 | ; proportional to n. 10 | ; 11 | ; A: Solutions are cached for each call to memo-fib. For example 12 | ; if (memo-fib 3) is calculated, then next time (memo-fib 3) is 13 | ; called the only work done is to look up in a table the key 3, 14 | ; which then returns the solution. 15 | ; 16 | ; This caching allows the recursive procedure for finding 17 | ; Fibonacci numbers to run proportinal to n. It does not 18 | ; duplicate any work. This is much better than the non-memoized version. 19 | ; 20 | ; Q: Could we have just done (memoize fib)? 21 | ; A: No. Then the recursive calls would not be caching their solutions 22 | ; or looking up in the table to see if the solution has already been 23 | ; calculated for the input. 24 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_28.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.28 2 | 3 | ; Look in circuit_building_blocks.clj for implementation 4 | ; of or-gate and logical-or 5 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_29.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.29 2 | 3 | (ns ex3_29 4 | (:use circuit-building-blocks) 5 | 6 | (defn or-gate [a1 a2 output] 7 | (let [a (make-wire) 8 | b (make-wire) 9 | c (make-wire)] 10 | (inverter a1 a) 11 | (inverter a2 b) 12 | (and-gate a b c) 13 | (inverter c output)) 14 | :ok) 15 | 16 | ; Delay is 3 interter delays + 1 and-gate delay. 17 | ; Compare to exercise 3.28 which only had one or-gate delay 18 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_30.clj: -------------------------------------------------------------------------------- 1 | ; Exericse 3.30 2 | 3 | (ns ex3_30 4 | (:use circuit-building-blocks)) 5 | 6 | (defn sandwich-list 7 | [start middle end] 8 | (reverse 9 | (list* end 10 | (reverse (list* start middle))))) 11 | 12 | (defn ripple-carry-adder 13 | [As Bs Ss C] 14 | (let [n (count As) 15 | Cs (sandwich-list C (make-wires (- n 1)) 0)] 16 | (loop [as As, bs Bs, cs Cs, ss Ss] 17 | (if (nil? as) :ok) 18 | (full-adder (first as) 19 | (first bs) 20 | (second cs) 21 | (first ss) 22 | (first cs)) 23 | (recur (next as) 24 | (next bs) 25 | (next cs) 26 | (next ss))))) 27 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_31.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.31 2 | 3 | ; Q. Why is is necessary that accept-action-procedure! in make-wire 4 | ; specifies that the added procedure is immediately run? 5 | 6 | ; A. The procedure needs to be immediately run so that the inputs get 7 | ; captured at the time the unit (or, and, or inverter, etc) is added 8 | ; to the circuit. It is also the action-procedures which actually 9 | ; adds the action to the agenda after the correct time. 10 | 11 | ; If this didn't happen then the initial values of signals would not 12 | ; go through the logic gates. -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_32.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.32 2 | 3 | ; I'm having a hard time seeing how it matters. I can see from their example 4 | ; in the book that the output signal would switch to 1 when it really should not. 5 | 6 | ; Unfortunately I'm having a difficult time seeing how if instead of going from 7 | ; 0,1 to 1,0 if the inputs changed from 1,0 to 0,1 how the same problem wouldn't 8 | ; happen with the first in, first out behavior of using queues. 9 | 10 | ; Unless there is a way to make every action happen at the same time, I have a hard 11 | ; time seeing how this type of race condition is fixable. (that may be whiskey talking) -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_33.clj: -------------------------------------------------------------------------------- 1 | ; Look at ../test/test_ex3_33.clj for solution -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_34.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.34 2 | 3 | ; Q. 4 | ; What is flawed about doing the following to make a squarer? 5 | ; (defn squarer [a b] 6 | ; (multiplier a a b)) 7 | 8 | ; A. 9 | ; You cannot backout what the value of a is given the value of b 10 | ; with the above setup. The multiplier constraint expects to see 11 | ; two of its connectors with values to back out the third. It was 12 | ; not written to know if two of its connectors are the same. -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_35.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns ex3-35 3 | (:use constraint-system 4 | clojure.contrib.math)) 5 | 6 | ; Going to implement the squarer using similar ways I implemented the 7 | ; other constraints 8 | 9 | (defn square [x] 10 | (* x x)) 11 | 12 | (deftype Squarer [a b] 13 | Constraint 14 | (process-new-value 15 | [this] 16 | (if (has-value? b) 17 | (if (< (get-value b) 0) 18 | (Error. (str "square less than 0 -- SQUARER " (get-value b))) 19 | (set-value! a 20 | (sqrt (get-value b)) 21 | this)) 22 | (when (has-value? a) 23 | (set-value! b 24 | (square (get-value a)) 25 | this)))) 26 | (process-forget-value 27 | [this] 28 | (forget-value! a this) 29 | (forget-value! b this) 30 | (process-new-value this))) 31 | 32 | (defn make-squarer [a b] 33 | (let [squarer (Squarer. a b)] 34 | (connect a squarer) 35 | (connect b squarer) 36 | squarer)) 37 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_36.clj: -------------------------------------------------------------------------------- 1 | ; I'm not going to do this since I've implemented this is a significantly 2 | ; different way than the book. 3 | -------------------------------------------------------------------------------- /clojure/section3.3/src/ex3_37.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns ex3-37 3 | (:use constraint-system)) 4 | 5 | (defn c+ [x y] 6 | (let [z (make-connector)] 7 | (make-adder x y z) 8 | z)) 9 | 10 | (defn c- [x y] 11 | (let [z (make-connector)] 12 | (make-adder y z x) 13 | z)) 14 | 15 | (defn c* [x y] 16 | (let [z (make-connector)] 17 | (make-multiplier x y z) 18 | z)) 19 | 20 | (defn cd [x y] 21 | (let [z (make-connector)] 22 | (make-multiplier y z x) 23 | z)) 24 | 25 | (defn cv [x] 26 | (let [z (make-connector)] 27 | (make-constant x z) 28 | z)) 29 | 30 | -------------------------------------------------------------------------------- /clojure/section3.3/src/localtable.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns localtable 3 | (:use mypair)) 4 | 5 | (defn make-table 6 | ([] (make-table =)) 7 | ([same-key?] 8 | (let [local-table (my-list :*table*)] 9 | (letfn [ 10 | (my-assoc [key1 records] 11 | (cond (nil? records) false 12 | (same-key? key1 (car (car records))) (car records) 13 | :else (my-assoc key1 (cdr records)))) 14 | (lookup [& kys] 15 | (let [subtable (my-assoc (first kys) (cdr local-table))] 16 | (lookup-internal (next kys) subtable))) 17 | (lookup-internal [kys cur] 18 | (cond (and kys cur) 19 | (let [rec (my-assoc (first kys) (cdr cur))] 20 | (lookup-internal (next kys) rec)) 21 | (and (nil? kys) cur) (cdr cur) 22 | (not cur) false)) 23 | (insert! [key-1 key-2 value] 24 | (let [subtable (my-assoc key-1 (cdr local-table))] 25 | (if subtable 26 | (let [record (my-assoc key-2 (cdr subtable))] 27 | (if record 28 | (set-cdr! record value) 29 | (set-cdr! subtable 30 | (make-pair (make-pair key-2 value) 31 | (cdr subtable))))) 32 | (set-cdr! local-table 33 | (make-pair (my-list key-1 34 | (make-pair key-2 value)) 35 | (cdr local-table))))) 36 | :ok) 37 | (dispatch [m] 38 | (cond (= m :lookup-proc) lookup 39 | (= m :insert-proc!) insert! 40 | (= m :table) local-table 41 | :else (Error. "Unknown operation -- TABLE" m)))] 42 | dispatch)))) 43 | -------------------------------------------------------------------------------- /clojure/section3.3/src/mypair.clj: -------------------------------------------------------------------------------- 1 | (ns mypair) 2 | 3 | (defstruct pair :car :cdr) 4 | 5 | (defn car [p] 6 | (:car @p)) 7 | 8 | (defn cdr [p] 9 | (:cdr @p)) 10 | 11 | (defn pair? [p] 12 | (and (= clojure.lang.Atom (type p)))) 13 | 14 | 15 | (defn make-pair 16 | ([] (make-pair nil nil)) 17 | ([a] (make-pair a nil)) 18 | ([a b] (atom (struct pair a b)))) 19 | 20 | (defn set-car! [p x] 21 | (swap! p #(assoc % :car x))) 22 | 23 | (defn set-cdr! [p x] 24 | (swap! p #(assoc % :cdr x))) 25 | 26 | 27 | (defn my-cons [p1 p2] 28 | (make-pair 29 | (car p1) 30 | p2)) 31 | 32 | (defn my-list [& elems] 33 | (loop [xs (next (reverse elems)) 34 | res (make-pair (first (reverse elems)))] 35 | (if (nil? xs) res 36 | (recur (next xs) 37 | (my-cons (make-pair (first xs)) 38 | res))))) 39 | 40 | (defn create-visual 41 | ([ps prefix postfix] 42 | (let [carstr (if (pair? (car ps)) 43 | (create-visual (car ps)) 44 | (car ps)) 45 | cdrstr (if (pair? (cdr ps)) 46 | (create-visual (cdr ps) "" "") 47 | (cdr ps))] 48 | (str prefix carstr " " cdrstr postfix))) 49 | ([ps] 50 | (create-visual ps "(" ")"))) 51 | -------------------------------------------------------------------------------- /clojure/section3.3/src/queue.clj: -------------------------------------------------------------------------------- 1 | (ns queue 2 | (:use mypair)) 3 | 4 | (defn make-queue [] 5 | (make-pair :empty :empty)) 6 | 7 | (defn empty-queue? [q] 8 | (and (= (car q) :empty) 9 | (= (cdr q) :empty))) 10 | 11 | (defn front-ptr [q] (car q)) 12 | (defn rear-ptr [q] (cdr q)) 13 | (defn set-front-ptr! [q i] (set-car! q i)) 14 | (defn set-rear-ptr! [q i] (set-cdr! q i)) 15 | 16 | (defn set-front-and-rear-ptr! [q x] 17 | (set-front-ptr! q x) 18 | (set-rear-ptr! q x)) 19 | 20 | (defn front-queue [q] 21 | (if (empty-queue? q) 22 | (Error. "FRONT called with empty queue") 23 | (car (front-ptr q)))) 24 | 25 | (defn insert-queue! 26 | [queue x] 27 | (let [e (make-pair x)] 28 | (if (empty-queue? queue) 29 | (do (set-front-and-rear-ptr! queue e) queue) 30 | (do (set-cdr! (rear-ptr queue) e) 31 | (set-rear-ptr! queue e) 32 | queue)))) 33 | 34 | (defn delete-queue! 35 | [queue] 36 | (if (empty-queue? queue) 37 | (Error. "DELETE! called with empty queue") 38 | (let [front (car queue)] 39 | (if (= front (cdr queue)) 40 | (do (set-front-and-rear-ptr! queue :empty) queue) 41 | (do (set-front-ptr! queue (cdr front)) queue))))) 42 | 43 | ; Exercise 3.21 44 | (defn get-queue-str [queue] 45 | (let [backup (atom @queue), rear (rear-ptr queue)] 46 | (str "(" 47 | (.trim 48 | (loop [middle ""] 49 | (if (empty-queue? backup) middle 50 | (do 51 | (let [m (str middle " " (front-queue backup))] 52 | (delete-queue! backup) 53 | (recur m)))))) 54 | ")"))) 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /clojure/section3.3/test/celsius_fahrenheit_converter.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns celsius-fahrenheit-converter 3 | (:use constraint-system 4 | clojure.test)) 5 | 6 | (defn celsius-fahrenheit-converter 7 | [c f] 8 | (let [u (make-connector) 9 | v (make-connector) 10 | w (make-connector) 11 | x (make-connector) 12 | y (make-connector)] 13 | (make-multiplier c w u) 14 | (make-multiplier v x u) 15 | (make-adder v y f) 16 | (make-constant 9 w) 17 | (make-constant 5 x) 18 | (make-constant 32 y) 19 | :ok)) 20 | 21 | (def C (make-connector)) 22 | (def F (make-connector)) 23 | (celsius-fahrenheit-converter C F) 24 | 25 | (deftest setting-fahrenheit-gives-celsius 26 | (set-value! F 77 :user) 27 | (is (= 25 (get-value C))) 28 | (forget-value! F :user)) 29 | 30 | (deftest setting-celsius-gives-fahrenheit 31 | (set-value! C 100 :user) 32 | (is (= 212 (get-value F))) 33 | (forget-value! C :user)) 34 | 35 | ; Using probes as in book instead of tests 36 | (make-probe "Celsius temp" C) 37 | (make-probe "Fahrenheit temp" F) 38 | (set-value! C 25 :user) 39 | (set-value! F 212 :user) 40 | (forget-value! C :user) 41 | (set-value! F 212 :user) 42 | (forget-value! C :user) 43 | (forget-value! F :user) 44 | 45 | 46 | -------------------------------------------------------------------------------- /clojure/section3.3/test/simple_simulation.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns simple-simulation 3 | (:use circuit-building-blocks 4 | agenda)) 5 | 6 | (defn probe [name wire] 7 | (add-action! wire 8 | (fn [] 9 | (println name (current-time the-agenda) 10 | "New-value=" (get-signal wire))))) 11 | 12 | (def input-1 (make-wire)) 13 | (def input-2 (make-wire)) 14 | (def sum (make-wire)) 15 | (def carry (make-wire)) 16 | (probe :sum sum) 17 | (probe :carry carry) 18 | 19 | (half-adder input-1 input-2 sum carry) 20 | (set-signal! input-1 1) 21 | (propagate) 22 | (set-signal! input-2 1) 23 | (propagate) 24 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_constraints.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns test-constraints 3 | (:use constraint-system 4 | clojure.test)) 5 | 6 | (deftest connectors-with-no-value-has-no-value 7 | (let [connector (make-connector)] 8 | (is (= false (has-value? connector))))) 9 | 10 | (deftest connector-with-value-has-value 11 | (let [connector (make-connector)] 12 | (set-value! connector 100 :user) 13 | (is (= true (has-value? connector))) 14 | (is (= 100 (get-value connector))))) 15 | 16 | (deftest connector-forgets-value 17 | (let [connector (make-connector)] 18 | (set-value! connector 100 :user) 19 | (is (= true (has-value? connector))) 20 | (forget-value! connector :user) 21 | (is (= false (has-value? connector))))) 22 | 23 | (deftest making-adder-has-no-side-affects 24 | (let [a1 (make-connector) 25 | a2 (make-connector) 26 | sum (make-connector) 27 | adder (make-adder a1 a2 sum)] 28 | (is (= false (has-value? a1))) 29 | (is (= false (has-value? a2))) 30 | (is (= false (has-value? sum))))) 31 | 32 | (deftest adder-works 33 | (let [a1 (make-connector) 34 | a2 (make-connector) 35 | sum (make-connector) 36 | adder (make-adder a1 a2 sum)] 37 | (set-value! a1 5 :user) 38 | (set-value! a2 4 :user) 39 | (is (= 9 (get-value sum))) 40 | (forget-value! a1 :user) 41 | (is (= 5 (get-value a1))) 42 | (forget-value! a2 :user) 43 | (is (= 4 (get-value a2))) 44 | (forget-value! sum :user) 45 | (is (= false (has-value? sum))) 46 | (set-value! a2 7 :user) 47 | (set-value! a1 10 :user) 48 | (is (= 17 (get-value sum))))) 49 | 50 | (deftest making-multiplier-has-no-side-affects 51 | (let [m1 (make-connector) 52 | m2 (make-connector) 53 | product (make-connector) 54 | multiplier (make-multiplier m1 m2 product)] 55 | (is (= false (has-value? m1))) 56 | (is (= false (has-value? m2))) 57 | (is (= false (has-value? product))))) 58 | 59 | (deftest multiplier-works 60 | (let [m1 (make-connector) 61 | m2 (make-connector) 62 | product (make-connector) 63 | multiplier (make-multiplier m1 m2 product)] 64 | (set-value! m1 5 :user) 65 | (set-value! m2 4 :user) 66 | (is (= 20 (get-value product))) 67 | (forget-value! m1 :user) 68 | (is (= 5 (get-value m1))) 69 | (forget-value! m2 :user) 70 | (is (= 4 (get-value m2))) 71 | (forget-value! product :user) 72 | (is (= false (has-value? product))) 73 | (set-value! m1 10 :user) 74 | (set-value! m2 7 :user) 75 | (is (= 70 (get-value product))))) 76 | 77 | (deftest constant-always-has-value 78 | (let [constant (make-constant 7 (make-connector))] 79 | (is (= true (has-value? constant))))) 80 | 81 | (deftest can-get-constant-value 82 | (let [constant (make-constant 7 (make-connector))] 83 | (is (= 7 (get-value constant))))) 84 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_deque.clj: -------------------------------------------------------------------------------- 1 | (ns test-deque 2 | (:use clojure.test 3 | deque)) 4 | 5 | (deftest new-qeue-should-be-empty 6 | (is (= true (empty-deque? (make-deque))))) 7 | 8 | (deftest can-insert-single-element-front 9 | (is (= :a (-> (make-deque) 10 | (front-insert-deque! :a) 11 | (front-deque)))) 12 | (is (= :a (-> (make-deque) 13 | (front-insert-deque! :a) 14 | (rear-deque))))) 15 | 16 | (deftest can-insert-single-element-rear 17 | (is (= :a (-> (make-deque) 18 | (rear-insert-deque! :a) 19 | (front-deque)))) 20 | (is (= :a (-> (make-deque) 21 | (rear-insert-deque! :a) 22 | (rear-deque))))) 23 | 24 | (deftest can-insert-multiple-elements 25 | (let [d (-> (make-deque) 26 | (rear-insert-deque! :b) 27 | (front-insert-deque! :a) 28 | (front-insert-deque! :c))] 29 | (is (= :c (front-deque d))) 30 | (is (= :b (rear-deque d))))) 31 | 32 | (deftest can-remove-from-front 33 | (let [d (-> (make-deque) 34 | (front-insert-deque! :b) 35 | (front-insert-deque! :a))] 36 | (front-delete-deque! d) 37 | (is (= :b (front-deque d))) 38 | (front-delete-deque! d) 39 | (is (= true (empty-deque? d))))) 40 | 41 | (deftest can-remove-from-rear 42 | (let [d (-> (make-deque) 43 | (front-insert-deque! :b) 44 | (front-insert-deque! :a))] 45 | (rear-delete-deque! d) 46 | (is (= :a (rear-deque d))) 47 | (rear-delete-deque! d) 48 | (is (= true (empty-deque? d))))) -------------------------------------------------------------------------------- /clojure/section3.3/test/test_ex3_17.clj: -------------------------------------------------------------------------------- 1 | (ns test_ex3_17 2 | (:use ex3_17 3 | mypair 4 | clojure.test)) 5 | 6 | (def simple-three (my-list :a :b :c)) 7 | 8 | (def three-fakes-four 9 | (let [a (make-pair :a) 10 | b (make-pair :b) 11 | c (make-pair :c)] 12 | (set-cdr! a b) 13 | (set-car! b c) 14 | (set-cdr! b c) 15 | a)) 16 | 17 | (def three-fakes-seven 18 | (let [a (make-pair :a) 19 | b (make-pair :b) 20 | c (make-pair :c)] 21 | (set-car! a b) 22 | (set-cdr! a b) 23 | (set-car! b c) 24 | (set-cdr! b c) 25 | a)) 26 | 27 | (deftest should-handle-one 28 | (is (= 1 (count-pairs (make-pair)))) 29 | (is (= 1 (count-pairs (make-pair :a))))) 30 | 31 | (deftest should-all-count-as-three 32 | (is (= 3 (count-pairs simple-three))) 33 | (is (= 3 (count-pairs three-fakes-four))) 34 | (is (= 3 (count-pairs three-fakes-seven)))) 35 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_ex3_18.clj: -------------------------------------------------------------------------------- 1 | (ns test_ex3_18 2 | (:use clojure.test 3 | mypair 4 | ex3_18)) 5 | 6 | (def has-cycle 7 | (let [a (make-pair :a) 8 | b (make-pair :b) 9 | c (make-pair :c)] 10 | (set-cdr! a b) 11 | (set-cdr! b c) 12 | (set-cdr! c a) 13 | a)) 14 | 15 | (def no-cycle 16 | (let [a (make-pair :a) 17 | b (make-pair :b) 18 | c (make-pair :c)] 19 | (set-cdr! a b) 20 | (set-cdr! b c) 21 | a)) 22 | 23 | 24 | (deftest should-detect-cycle 25 | (is (= true (cycles? has-cycle)))) 26 | 27 | (deftest should-not-detect-cycle 28 | (is (= false (cycles? no-cycle)))) 29 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_ex3_19.clj: -------------------------------------------------------------------------------- 1 | (ns test_ex3_19 2 | (:use clojure.test 3 | mypair 4 | ex3_19)) 5 | 6 | (def has-cycle-odd 7 | (let [a (make-pair :a) 8 | b (make-pair :b) 9 | c (make-pair :c)] 10 | (set-cdr! a b) 11 | (set-cdr! b c) 12 | (set-cdr! c a) 13 | a)) 14 | 15 | (def has-cycle-even 16 | (let [a (make-pair :a) 17 | b (make-pair :b) 18 | d (make-pair :d) 19 | c (make-pair :c)] 20 | (set-cdr! a b) 21 | (set-cdr! b c) 22 | (set-cdr! c d) 23 | (set-cdr! d a) 24 | a)) 25 | 26 | (deftest should-detect-cycle 27 | (is (= true (cycles? has-cycle-odd))) 28 | (is (= true (cycles? has-cycle-even)))) 29 | 30 | (deftest should-not-detect-cycle 31 | (is (= false (cycles? (my-list :a :b :c)))) 32 | (is (= false (cycles? (my-list :a :b :c :d))))) 33 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_ex3_22.clj: -------------------------------------------------------------------------------- 1 | (ns test_ex3_22 2 | (:use ex3_22 3 | clojure.test)) 4 | 5 | (deftest should-detect-empty 6 | (= true ((make-queue) :empty?))) 7 | 8 | (deftest can-insert-and-remove 9 | (let [q (make-queue)] 10 | (q :insert! :a) 11 | (is (= :a (q :front))) 12 | (q :delete!) 13 | (is (= true (q :empty?))) 14 | ((q :insert! :b) :insert! :c) 15 | (is (= :b (q :front))) 16 | (q :delete!) 17 | (is (= :c (q :front))))) 18 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_ex3_25.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns test_ex3_25 3 | (:use ex3_25 4 | clojure.test)) 5 | 6 | (deftest can-use-list-as-key 7 | (let [tab (make-table)] 8 | ((tab :insert-proc!) '(:a :b) :jake) 9 | ((tab :insert-proc!) '(:a :b :e) :mike) 10 | (is (= :mike ((tab :lookup-proc) '(:a :b :e)))) 11 | (is (= :jake ((tab :lookup-proc) '(:a :b)))))) 12 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_ex3_33.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.33 2 | 3 | (ns test-ex3-33 4 | (:use constraint-system 5 | clojure.test)) 6 | 7 | (defn averager [a b c] 8 | (let [sum (make-connector) 9 | divisor (make-connector)] 10 | (make-adder a b sum) 11 | (make-constant 2 divisor) 12 | (make-multiplier c divisor sum))) 13 | 14 | (deftest averager-outputs-average 15 | (let [a (make-connector) 16 | b (make-connector) 17 | c (make-connector)] 18 | (averager a b c) 19 | (set-value! a 12 :user) 20 | (set-value! b 18 :user) 21 | (is (= 15 (get-value c))))) 22 | 23 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_ex3_35.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns test-ex3-35 3 | (:use ex3-35 4 | clojure.test 5 | constraint-system)) 6 | 7 | (deftest squarer-squares 8 | (let [a (make-connector) 9 | b (make-connector)] 10 | (make-squarer a b) 11 | (set-value! a 4 :user) 12 | (is (= 16 (get-value b))))) 13 | 14 | (deftest squarer-takes-square-root 15 | (let [a (make-connector) 16 | b (make-connector)] 17 | (make-squarer a b) 18 | (set-value! b 16 :user) 19 | (is (= 4 (get-value a))))) 20 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_ex3_37.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns test-ex3-37 3 | (:use ex3-37 4 | constraint-system 5 | clojure.test)) 6 | 7 | (defn celsius-fahrenheit-converter [x] 8 | (c+ (c* (cd (cv 9) (cv 5)) 9 | x) 10 | (cv 32))) 11 | 12 | (def C (make-connector)) 13 | (def F (celsius-fahrenheit-converter C)) 14 | 15 | (deftest can-convert-celius-to-fahrenheit 16 | (set-value! C 100 :user) 17 | (is (= 212 (get-value F)))) 18 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_localtable.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns test_localtable 3 | (:use localtable 4 | clojure.test)) 5 | 6 | (deftest false-for-keys-not-found 7 | (let [tab (make-table)] 8 | (is (= false ((tab :lookup-proc) :a :b))))) 9 | 10 | (deftest can-insert-and-find-one 11 | (let [tab (make-table)] 12 | ((tab :insert-proc!) :a :b :jake) 13 | (is (= :jake ((tab :lookup-proc) :a :b))))) 14 | 15 | (deftest can-overwrite-entries 16 | (let [tab (make-table)] 17 | ((tab :insert-proc!) :a :b :jake) 18 | ((tab :insert-proc!) :a :b :mike) 19 | (is (= :mike ((tab :lookup-proc) :a :b))))) 20 | 21 | (deftest table-supports-multiple-entries 22 | (let [tab (make-table)] 23 | ((tab :insert-proc!) :a :b :jake) 24 | ((tab :insert-proc!) :a :c :mccrary) 25 | ((tab :insert-proc!) :b :a :ekaj) 26 | (is (= :jake ((tab :lookup-proc) :a :b))) 27 | (is (= :mccrary ((tab :lookup-proc) :a :c))) 28 | (is (= :ekaj ((tab :lookup-proc) :b :a))))) 29 | 30 | (deftest can-supply-own-key-compare 31 | (let [tab (make-table (fn [x y] true))] 32 | ((tab :insert-proc!) :a :b :jake) 33 | (is (= :jake) ((tab :lookup-proc) :not :keys)))) 34 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_mypair.clj: -------------------------------------------------------------------------------- 1 | (ns test-mypair 2 | (:use clojure.test 3 | mypair)) 4 | 5 | (deftest can-make-pair 6 | (let [default (make-pair) 7 | specified (make-pair :a :b)] 8 | (is (= nil (car default))) 9 | (is (= nil (cdr default))) 10 | (is (= :a (car specified))) 11 | (is (= :b (cdr specified))))) 12 | 13 | (deftest can-change-car 14 | (let [pair (make-pair)] 15 | (set-car! pair 4) 16 | (is (= 4 (car pair))))) 17 | 18 | (deftest can-change-cdr 19 | (let [pair (make-pair)] 20 | (set-cdr! pair 4) 21 | (is (= 4 (cdr pair))))) 22 | 23 | (deftest can-cons-pairs-together 24 | (let [a (make-pair :a nil) 25 | b (make-pair :b nil) 26 | c (my-cons a b)] 27 | (is (= :a (car c))) 28 | (is (= b (cdr c))) 29 | (is (= :b (car (cdr c)))))) 30 | 31 | (deftest can-print-my-pairs 32 | (let [a (make-pair :a nil) 33 | b (make-pair :b nil) 34 | c (my-cons a b)] 35 | (is (= "(:a :b )" (create-visual c))) 36 | (is (= "((:a ) :b )" 37 | (create-visual 38 | (my-cons (make-pair a nil) b)))))) 39 | 40 | (deftest can-make-list-using-pairs 41 | (is (= nil (car (my-list nil)))) 42 | (is (= :a (car (my-list :a)))) 43 | (is (= :b (car (cdr (my-list :a :b))))) 44 | (is (= nil (cdr (cdr (my-list :a :b))))) 45 | (is (= :c (car (cdr (cdr (my-list :a :b :c))))))) 46 | 47 | -------------------------------------------------------------------------------- /clojure/section3.3/test/test_queue.clj: -------------------------------------------------------------------------------- 1 | (ns test_queue 2 | (:use queue 3 | clojure.test)) 4 | 5 | (deftest should-detect-empty 6 | (= true (empty-queue? (make-queue)))) 7 | 8 | (deftest can-insert-and-remove 9 | (let [q (make-queue)] 10 | (insert-queue! q :a) 11 | (is (= :a (front-queue q))) 12 | (delete-queue! q) 13 | (is (= true (empty-queue? q))) 14 | (insert-queue! (insert-queue! q :b) :c) 15 | (is (= :b (front-queue q))) 16 | (delete-queue! q) 17 | (is (= :c (front-queue q))))) 18 | 19 | ; Exercise 3.21 20 | (deftest can-print-empty-queue 21 | (is (= "()" (get-queue-str (make-queue))))) 22 | 23 | (deftest can-print-queue 24 | (is (= "(:a :b :c)" (-> (make-queue) 25 | (insert-queue! :a) 26 | (insert-queue! :b) 27 | (insert-queue! :c) 28 | get-queue-str)))) 29 | 30 | (deftest after-printing-queue-still-intact 31 | (let [q (-> (make-queue) (insert-queue! :a) (insert-queue! :b))] 32 | (get-queue-str q) 33 | (is (= :a (front-queue q))) 34 | (delete-queue! q) 35 | (is (= :b (front-queue q))))) 36 | -------------------------------------------------------------------------------- /clojure/section3.4/ex3_38.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.38 2 | 3 | ; Bank account starts with $100. 4 | ; The following three transactions have to run, 5 | ; Peter: (set! balance (+ balance 10)) 6 | ; Paul: (set! balance (- balance 20)) 7 | ; Mary: (set! balance (- balance (/ balance 2))) 8 | 9 | ; a. List the different possible values for balance assuming system forces 10 | ; the three to run sequentially in some order. 11 | ; 12 | ; [peter, paul, mary] = 45 13 | ; [peter, mary, paul] = 35 14 | ; [paul, peter, mary] = 45 15 | ; [paul, mary, peter] = 50 16 | ; [mary, peter, paul] = 40 17 | ; [mary, paul, peter] = 40 18 | 19 | ; b. What other values could be produced if system allows process to be interleaved 20 | ; 21 | ; One example: Peter reads in balance as 100 and adds 10, before he can set 22 | ; balance Peter reads in balance as 100. Paul then sets balance to 23 | ; 110. Mary reads in 110 and figures out she should withdraw 55. 24 | ; Peter finishes his transaction and subracts 20 from 100 setting balance 25 | ; to 80. Mary then reads in 80 for balance and subtracts 55 and sets 26 | ; balance to 25. 27 | ; 28 | -------------------------------------------------------------------------------- /clojure/section3.4/ex3_39.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.39 2 | 3 | ; Potential before change: 101, 121, 110, 11, 100 4 | 5 | ; Which of the above 5 remain after code change? 6 | 7 | ; 101 -> first lambda sets x to 100, second increments by 1 8 | ; 121 -> second lambda sets x to 11, first squares to get 121. 9 | ; 100 -> first lambda squares x, but before it sets it other lambda 10 | ; does its work, which is then lost when first lambda sets to 100 11 | -------------------------------------------------------------------------------- /clojure/section3.4/ex3_40.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.40 2 | 3 | ; Give all possible values of x that can result from: 4 | 5 | ; (define x 10) 6 | ; (parallel-execute (lambda () (set! x (* x x))) 7 | ; (lambda () (set! x (* x x x)))) 8 | 9 | ; Potentials 10 | ; 1000000 -> P1 runs to completion then P2 11 | ; 1000000 -> P2 then P1 12 | ; 100 -> P2 reads 10 for x but no set, P1 reads 10 for x but no set, P2 sets, P1 sets 13 | ; 1000 -> P1 reads 10 for x but no set, P2 reads 10 for x but no set, P1 sets, P2 sets 14 | 15 | 16 | ; If it gets changed to: 17 | ; (define x 10) 18 | ; (define s (make-serializer)) 19 | ; (parallel-execute (s (lambda () (set! x (* x x)))) 20 | ; (s (lambda () (set! x (* x x x))))) 21 | 22 | ; Now P1 and P2 are serialized, once one starts it can't be stopped by the other one. 23 | ; Hence only answer is 1000000. 24 | -------------------------------------------------------------------------------- /clojure/section3.4/ex3_41.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.41 2 | 3 | ; I disagree with Ben Bitdiddle. 4 | ; I believe that allowing any one to look at the balance at anytime through 5 | ; the dispatch function while a deposit or withdraw is going on is alright. 6 | ; The potential to screw up the actual value in the account does not exist 7 | ; as viewing the balance is only viewing. Sure you may view in the middle 8 | ; of a transaction but that is not wrong, in that instant the account has 9 | ; that amount of money. -------------------------------------------------------------------------------- /clojure/section3.4/ex3_42.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.42 2 | 3 | ; This is a safe change to make. -------------------------------------------------------------------------------- /clojure/section3.4/ex3_43.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.43 2 | 3 | ; Exchanging money between accounts has been serialized in a way 4 | ; where the entire transaction has to happen before anything else 5 | ; can be done to either account. Because of this the final results 6 | ; will be 10, 20, and 30 in order since anytime an exchange happens between 7 | ; any of those accounts the same balances (10, 20, 30) are still found. 8 | 9 | ; In the first version the sum of the balances of the two accounts 10 | ; doing the exchange is preserved since the whatever sum is taken from 11 | ; one is put into the other. Because of this even if exchanges are allowed 12 | ; to be interleaved as the first example would allow the total of all accounts 13 | ; will remain the same though the balances could be something like 10, 10, 40. 14 | -------------------------------------------------------------------------------- /clojure/section3.4/ex3_44.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.44 2 | 3 | ; Ben's suggestion will work. 4 | ; The difference is that in the exchange problem there is copmutation of 5 | ; the difference between the accounts. This allows there to be inconsistant 6 | ; states of the balance of the accounts. 7 | 8 | ; With transfer, the amount to transfer is already known. As long as all calls 9 | ; to transfer are given time to finish then whatever amount is owed (or owed by) 10 | ; an account will eventually get deposited (or withdrawn). -------------------------------------------------------------------------------- /clojure/section3.4/ex3_45.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.45 2 | 3 | ; By exposing the serializer and seralizing internally deadlock will occur 4 | ; if serialized-exchange is called. -------------------------------------------------------------------------------- /clojure/section3.4/ex3_46.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.46. 2 | 3 | ; Explain why: 4 | ;1 (define (test-and-set! cell) 5 | ;2 (if (car cell) 6 | ;3 true 7 | ;4 (begin (set-car! cell true) 8 | ;5 false))) 9 | ; has issues if there is no attempt in making test-and-set! atomic. 10 | 11 | ; Two process could call test-and-set! with the saem cell. 12 | ; P1 executes line 2 and sees that the cell hasn't been taken yet but 13 | ; before it can set it to true P2 interupts and also executes line 2. 14 | ; Now both proess think they can aquire the mutex and they both do 15 | ; causing catasrophe. -------------------------------------------------------------------------------- /clojure/section3.4/ex3_47.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.47. 2 | 3 | ; a) Write a semaphore in terms of mutex defined in book. 4 | 5 | (defn test-and-set! 6 | [cell] 7 | (if @cell 8 | true 9 | (do (swap! cell (fn [x] true)) 10 | false))) 11 | 12 | (defn clear! [cell] 13 | (swap! cell (fn [x] false))) 14 | 15 | (defn make-mutex 16 | [] 17 | (let [cell (atom false) 18 | (fn the-mutex [m] 19 | (cond (= m :aquire) 20 | (if (test-and-set! cell) 21 | (recur :aquire)) 22 | (= m :release) (clear! cell)))] 23 | the-mutex)) 24 | 25 | (defn make-semaphore 26 | [n] 27 | (let [count (atom n) 28 | mutex (make-mutex)] 29 | (letfn [ 30 | (fn aquire [] 31 | (loop [still-need true] 32 | (mutex :release) 33 | (while still-need 34 | (mutex :aquire) 35 | (if (> 0 @count) 36 | (do (swap! count dec) 37 | (recur false)) 38 | (recur true))))) 39 | (fn release [] 40 | (mutex :aquire) 41 | (if (< n @count) (swap! count inc)) 42 | (mutex :release)) 43 | (fn dispatch [m] 44 | (cond (= m :aquire) (aquire) 45 | (= m :release) (release)))] 46 | dispatch))) 47 | 48 | ; b) Do it using test-and-set! 49 | 50 | (defn loop-test-and-set! 51 | [cell] 52 | (if (test-and-set! cell) 53 | (recur cell))) 54 | 55 | (defn make-semaphore 56 | [n] 57 | (let [count (atom n) 58 | cell (atom false)] 59 | (letfn [(fn aquire [] 60 | (loop [still-need true] 61 | (clear! cell) 62 | (while still-need 63 | (loop-test-and-set! cell) 64 | (if (> 0 @count) 65 | (do (swap! count dec) 66 | (recur false)) 67 | (recur true))))) 68 | (fn release [] 69 | (loop-test-and-set! cell) 70 | (if (< n @count) (swap! count inc)) 71 | (clear! cell)) 72 | (fn dispatch [m] 73 | (cond (= m :aquire) (aquire) 74 | (= m :release) (release)))] 75 | dispatch))) -------------------------------------------------------------------------------- /clojure/section3.4/ex3_48.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.48 2 | 3 | 4 | ; Explain why numbering locks and then trying to aquire the smaller numbered locks 5 | ; prior to the higher number locks avoids deadlock. 6 | 7 | 8 | ; Lets say there are two locks: 1 and 2 9 | ; Lets say there are two processes: A and B 10 | 11 | ; Process: A B 12 | ; First lock: 1 2 13 | ; Second lock: 2 1 14 | 15 | ; If the above happens, (A grabs lock 1, B grabs 2, A trys to get 2 and fails because 16 | ; B has it, B fails to get 1 because A has it) then deadlock happens. 17 | 18 | ; Process: A B 19 | ; First lock: 1 1 20 | ; Second lock: 2 2 21 | 22 | ; The above shows the processes trying to grab the locks in the same order. This means 23 | ; that either A or B will get lock 1 and the other process will be blocked waiting for 24 | ; lock 1. Whatever process gets lock 1 will be able to get lock 2 and finish processing 25 | ; and will eventually release lock 2 and 1, causing the other process to be able to continue. 26 | -------------------------------------------------------------------------------- /clojure/section3.4/ex3_49.clj: -------------------------------------------------------------------------------- 1 | ; Exericse 3.49 2 | 3 | ; Deadlock-avoidance through the numbering of locks and aquiring in 4 | ; an agreed upon order will fail if you don't know all the locks 5 | ; a process will need to acquire at the beginning. This could lead to 6 | ; a process acquiring lock 2, doing some work, and then realizing it needs 7 | ; lock 1 while another process has lock 1 and is waiting on lock 2. -------------------------------------------------------------------------------- /clojure/section3.5/.gitignore: -------------------------------------------------------------------------------- 1 | classes 2 | lib 3 | *.clj~ 4 | -------------------------------------------------------------------------------- /clojure/section3.5/project.clj: -------------------------------------------------------------------------------- 1 | (defproject SICP-section3-5 "1.0.0-SNAPSHOT" 2 | :description "Solutions to section 3.5 of SICP" 3 | :dependencies [[org.clojure/clojure "1.2.0-master-SNAPSHOT"] 4 | [org.clojure/clojure-contrib "1.2.0-master-SNAPSHOT"]] 5 | :dev-dependencies [[swank-clojure "1.2.1"]]) 6 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_50.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.50 2 | 3 | 4 | ; Just going to keep this one in scheme. 5 | 6 | ; (define (stream-map proc . argstreams) 7 | ; (if (stream-null? (car argstreams)) 8 | ; the-empty-stream 9 | ; (stream-cons 10 | ; (apply proc (map stream-car argstreams)) 11 | ; (apply stream-map 12 | ; (cons proc (map stream-cdr argstreams)))))) -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_51.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.51 2 | 3 | ; Going to rewrite example in Clojure. 4 | 5 | (defn show [x] 6 | (println x) 7 | x) 8 | 9 | ; In clojure 'range and 'map are both lazy. 10 | (def x (map show (range 0 10))) 11 | 12 | (nth x 5) 13 | 14 | (nth x 7) 15 | 16 | (comment 17 | "Any place where user> is input at the repl. Because of difficulties 18 | in telling what is printed output and what is returned, I will put a p> 19 | before any output which was printed to the screen instead of being returned" 20 | 21 | "In the book after the first stream-ref (nth here) probably only 0 through 5 were 22 | printed to the screen before 5 was returned. Then after (stream-ref 7) 23 | 6 and 7 would be printed and 7 returned. This doesn't happen in Clojure as 24 | streams are 'chunked'. This means that chunks are evaluated instead of it happening 25 | one at a time" 26 | user> (def x (map show (range 0 10))) 27 | #'user/x 28 | user> (nth x 5) 29 | p>0 30 | p>1 31 | p>2 32 | p>3 33 | p>4 34 | p>5 35 | p>6 36 | p>7 37 | p>8 38 | p>9 39 | 5 40 | user> (nth x 7) 41 | 7 -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_52.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.52 2 | 3 | ; **** WARNING **** 4 | ; Solutions here are going to differ some from solutions to problem in the book. 5 | ; Clojure's lazy streams and the stream implementation done in the book have different 6 | ; ways of evaluating. This will result in differences. 7 | 8 | ; One of those major differences in Clojure's 'chunked' stream concept. Streams are 9 | ; evalulated in chunks in Clojure instead of always one at a time. 10 | 11 | ; Because I'm choosing to do these with native Clojure constructs intead of 12 | ; reimplementing the Scheme style described in SICP the solutions are going to 13 | ; be different. The Scheme style could be easily implemented using Clojure's 'delay and 'force 14 | ; procedures if one was so inclined. 15 | 16 | (defn display-stream [s] 17 | (doseq [x s] 18 | (println x))) 19 | 20 | (def sum (atom 0)) 21 | ; sum is 0 22 | 23 | (defn accum [x] 24 | (swap! sum #(+ x %)) 25 | x) 26 | ; sum is still 0 27 | 28 | (def seqs (map accum (range 1 20))) 29 | ; sum is 0 30 | 31 | (def y (filter even? seqs)) 32 | ; sum is 0 33 | 34 | (def x (filter (fn [x] (zero? (rem x 5))) 35 | seqs)) 36 | ; sum is 0 37 | 38 | (nth y 7) 39 | ; sum is 190, it is this because of chuncked evaluation 40 | ; Result of expression is 16. 41 | 42 | (display-stream x) 43 | ; prints to repl: 44 | ; 5 45 | ; 10 46 | ; 15 47 | ; sum is still 190 48 | 49 | ; The above assumes that delayed evaluation results are cached and only 50 | ; evaluated once. If this were not true then accum would get called with (range 1 7) from 51 | ; the (nth y 7) call and then again with (range 1 20) for the diplay-stream call. This 52 | ; would result in sum being equal to 218. -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_53.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.53 2 | 3 | ; Q. 4 | ; Without running it, describe the elements of 5 | ; (define s (cons-stream 1 (add-streams s s))) 6 | 7 | ; A. 8 | ; s looks like the following 9 | ; '(1 2 4 8 16 ....) 10 | ; The equation f(n) = f(n-1) + f(n-1) describes it. -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_54.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.54 2 | 3 | (defn mul-streams [x y] 4 | (map * x y)) 5 | 6 | (defn integers-starting-from [n] 7 | (iterate inc n)) 8 | 9 | (def factorials 10 | (lazy-seq 11 | (cons 1 (mul-streams factorials (integers-starting-from 2))))) 12 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_55.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.55 2 | 3 | (ns ex3-55) 4 | 5 | (comment "this also worked but I thought it was ugly. Attempt 1." 6 | (defn partial-sum 7 | [s] 8 | ((fn ps [a b] 9 | (cons a (lazy-seq (ps (+ a (first b)) 10 | (rest b))))) 11 | (first s) 12 | (rest s)))) 13 | 14 | (defn partial-sum [s] 15 | (lazy-seq 16 | (cons 17 | (first s) 18 | (map + 19 | (next s) 20 | (partial-sum s))))) 21 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_56.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.56 2 | 3 | (ns ex3-56) 4 | 5 | (defn merge-streams [s1 s2] 6 | (cond (nil? s1) s2 7 | (nil? s2) s1 8 | :else (let [s1car (first s1) 9 | s2car (first s2)] 10 | (cond (< s1car s2car) 11 | (lazy-seq (cons s1car (merge-streams (next s1) s2))) 12 | (> s1car s2car) 13 | (lazy-seq (cons s2car (merge-streams s1 (next s2)))) 14 | :else (lazy-seq (cons s1car 15 | (merge-streams (next s1) 16 | (next s2)))))))) 17 | 18 | (defn scale-stream [stream factor] 19 | (map #(* % factor) stream)) 20 | 21 | (def integers (iterate inc 1)) 22 | 23 | (def S (lazy-seq (cons 1 24 | (merge-streams (scale-stream integers 2) 25 | (merge-streams (scale-stream integers 3) 26 | (scale-stream integers 5)))))) 27 | 28 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_57.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.57 2 | 3 | (ns ex3-57) 4 | 5 | ; Example from book in Scheme 6 | ;(define fibs 7 | ; (cons-stream 0 8 | ; (cons-stream 1 9 | ; (add-streams (stream-cdr fibs) 10 | ; fibs)))) 11 | 12 | (defn add-streams [s1 s2] 13 | (map + s1 s2)) 14 | 15 | (def fibs 16 | (lazy-seq (cons 0 17 | (lazy-seq (cons 1 (add-streams (rest fibs) 18 | fibs)))))) 19 | 20 | 21 | ; With the caching optimization talked about in the book 22 | ; we have done a n-2 addtions where n is the nth fib number 23 | ; we are calculating. So to calculated the 5th fib number 24 | ; we have done 3 additions. 25 | 26 | ; If we don't cache then the call to (rest fibs) will always have already 27 | ; calculated the next number the recursive call to fibs needs. Since it 28 | ; isn't cached then the recursive call to fibs repeats this work. 29 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_58.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.58 2 | 3 | ; Give an interpretation of stream computed by: 4 | ; A: Stream is doing division of num by den in the base of radix. 5 | ; Returns points after decimal with each call. 6 | 7 | ; (define (expand num den radix) 8 | ; (cons-stream 9 | ; (quotient (* num radix) den) 10 | ; (expand (remainder (* num radix) den) den radix))) 11 | 12 | (declare quotient) 13 | 14 | (defn expand [num den radix] 15 | (lazy-seq 16 | (cons 17 | (quotient (* num radix) den) 18 | (expand (rem (* num radix) den) den radix)))) 19 | 20 | (defn quotient [x y] (int (/ x y))) 21 | 22 | ; What is produced by (expand 1 7 10)? 23 | ;user> (take 30 (expand 1 7 10)) 24 | ;(1 4 2 8 5 7 1 4 2 8 5 7 1 4 2 8 5 7 1 4 2 8 5 7 1 4 2 8 5 7) 25 | 26 | ; by (expand 3 8 10)? 27 | ;user> (take 30 (expand 3 8 10)) 28 | ;(3 7 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) 29 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_59.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.59 2 | 3 | (ns ex3-59) 4 | 5 | ; Part A 6 | (defn integrate-series [s] 7 | ((fn iter [strm n] 8 | (lazy-seq 9 | (when-let [s (seq strm)] 10 | (cons (/ (first s) n) 11 | (iter (rest s) (inc n)))))) 12 | s 1)) 13 | 14 | ; Part b 15 | (def exp-series (lazy-seq (cons 1 16 | (integrate-series exp-series)))) 17 | 18 | (declare sine-series cosine-series) 19 | 20 | (defn scale-series [s n] 21 | (map #(* % n) s)) 22 | 23 | (def cosine-series 24 | (lazy-seq (cons 1 (scale-series (integrate-series sine-series) 25 | -1)))) 26 | 27 | (def sine-series 28 | (lazy-seq (cons 0 (integrate-series cosine-series)))) 29 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_60.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns ex3-60) 3 | 4 | (defn scale-series [s n] 5 | (map #(* % n) s)) 6 | 7 | (defn add-streams [s1 s2] 8 | (map + s1 s2)) 9 | 10 | (defn mul-series [s1 s2] 11 | (lazy-seq 12 | (cons (* (first s1) (first s2)) 13 | (add-streams 14 | (scale-series (rest s2) (first s1)) 15 | (mul-series (rest s1) s2))))) 16 | 17 | 18 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_61.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns ex3-61 3 | (:use ex3-60)) 4 | 5 | 6 | (defn invert-unit-series [s] 7 | (lazy-seq 8 | (cons 1 9 | (scale-series 10 | (mul-series 11 | (invert-unit-series s) 12 | (rest s)) 13 | -1)))) 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_62.clj: -------------------------------------------------------------------------------- 1 | ; Exericse 3.62 2 | 3 | (ns ex3-62 4 | (:use ex3-60 5 | ex3-61 6 | [ex3-59 :only (cosine-series sine-series)])) 7 | 8 | (defn div-series [top denom] 9 | (if (zero? (first denom)) (Error. "can't divide by zero")) 10 | (let [c (/ 1 (first denom))] 11 | (scale-series 12 | (mul-series top 13 | (invert-unit-series (scale-series denom c))) 14 | c))) 15 | 16 | (def tanget-series 17 | (div-series sine-series cosine-series)) 18 | 19 | 20 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_63.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.63 2 | 3 | ; Louis Reasoner's sqrt-stream implementation 4 | 5 | ; (define (sqrt-stream x) 6 | ; (cons-stream 1.0 7 | ; (stream-map (lambda (guess) 8 | ; (sqrt-improve guess x)) 9 | ; (sqrt-stream x)))) 10 | 11 | ; Original 12 | ; (define (sqrt-stream x) 13 | ; (define guesses 14 | ; (cons-stream 1.0 15 | ; (stream-map (lambda (guess) 16 | ; (sqrt-improve guess x)) 17 | ; guesses))) 18 | ; guesses) 19 | 20 | ; Loius Reasoner's implementation ends up calling itself recursively. This call 21 | ; is not memoized causing more work to be done. 22 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_64.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.64 2 | 3 | (defn abs [x] (Math/abs x)) 4 | 5 | (defn stream-limit [strm tolerance] 6 | (let [x1 (first strm) 7 | x2 (second strm) 8 | diff (abs (- x2 x1))] 9 | (if (< diff tolerance) 10 | x2 11 | (recur (nnext strm) tolerance)))) 12 | 13 | (defn average [x y] 14 | (/ (+ x y) 2)) 15 | 16 | (defn sqrt-improve [guess x] 17 | (average guess (/ x guess))) 18 | 19 | (defn sqrt-stream [x] 20 | ((fn guesses [] 21 | (lazy-seq 22 | (cons 1.0 23 | (map (fn [guess] (sqrt-improve guess x)) 24 | (guesses))))))) 25 | 26 | (defn sqrt [x tolerance] 27 | (stream-limit (sqrt-stream x) tolerance)) 28 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_65.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.65 2 | 3 | (defn square [x] (* x x)) 4 | 5 | (defn euler-transform [s] 6 | (let [s0 (nth s 0) 7 | s1 (nth s 1) 8 | s2 (nth s 2)] 9 | (lazy-seq 10 | (cons (- s2 (/ (square (- s2 s1)) 11 | (+ s0 (* -2 s1) s2))) 12 | (euler-transform (next s)))))) 13 | 14 | (defn make-tableau [transform s] 15 | (lazy-seq 16 | (cons s 17 | (make-tableau transform 18 | (transform s))))) 19 | 20 | (defn accelerated-sequence [transform s] 21 | (map first (make-tableau transform s))) 22 | 23 | (def ln-2-summands 24 | (map double 25 | (map / 26 | (cycle '(1 -1)) 27 | (iterate inc 1)))) 28 | 29 | (defn partial-sums [s] 30 | (lazy-seq 31 | (cons (first s) (map + (next s) (partial-sums s))))) 32 | 33 | (def ln-2-stream 34 | (partial-sums ln-2-summands)) 35 | 36 | (def euler-ln-2-stream 37 | (euler-transform ln-2-stream)) 38 | 39 | (def accelerated-ln-2-stream 40 | (accelerated-sequence euler-transform ln-2-stream)) 41 | 42 | ;Going to modify stream-limit to return what element it reaches tolerance on 43 | (defn stream-limit [strm tolerance n] 44 | (let [x1 (first strm) 45 | x2 (second strm) 46 | diff (abs (- x2 x1))] 47 | (if (< diff tolerance) 48 | {:elem n :value x2} 49 | (recur (nnext strm) tolerance (inc n))))) 50 | 51 | ; Google says: ln(2) = 0.693147181 52 | ;user> (stream-limit euler-ln-2-stream 0.000000001 0) 53 | ;{:elem 314, :value 0.6931471800635955} 54 | ;user> (stream-limit accelerated-ln-2-stream 0.000000001 0) 55 | ;{:elem 3, :value 0.6931471805599443} 56 | ;user> (stream-limit ln-2-stream 0.000000001 0) 57 | ; Evaluation aborted. (had a stack overflow error) 58 | 59 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_67.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.67 2 | 3 | (ns ex3-67) 4 | 5 | (defn pairs [s t] 6 | (lazy-seq 7 | (cons 8 | (list (first s) (first t)) 9 | (interleave 10 | (map (fn [x] (list (first s) x)) 11 | (next t)) 12 | (interleave 13 | (map (fn [x] (list x (first t))) 14 | (next s)) 15 | (pairs (next s) (next t))))))) 16 | 17 | (def integers (iterate inc 1)) 18 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_68.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.68 2 | 3 | (ns ex3-68) 4 | 5 | 6 | ; Louis Reasoner does this: 7 | (defn pairs [s t] 8 | (interleave 9 | (map (fn [x] (list (first s) x)) 10 | t) 11 | (pairs (next s) (next t)))) 12 | 13 | ; Does this work? Why or why not? 14 | 15 | ; This doesn't work because it lacks lazy evaluation. Interleave goes to evaluate its second 16 | ; paramenter (pairs (next s) (next t)) which then causes it to go into an infinite recursion 17 | ; resulting in a stack overflow. 18 | 19 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_69.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.69 2 | 3 | (ns ex3-69) 4 | 5 | (defn pairs [s t] 6 | (lazy-seq 7 | (cons 8 | (list (first s) (first t)) 9 | (interleave 10 | (map (fn [x] (list (first s) x)) 11 | (next t)) 12 | (pairs (next s) (next t)))))) 13 | 14 | (defn triples [s t u] 15 | (lazy-seq 16 | (cons 17 | (list (first s) (first t) (first u)) 18 | (interleave 19 | (map (fn [x] (list* (first s) x)) 20 | (next (pairs t u))) 21 | (triples (next s) (next t) (next u)))))) 22 | 23 | (defn square [x] (* x x)) 24 | 25 | (defn pythagorean-triples [] 26 | (filter (fn [x] 27 | (let [i (first x), j (second x), k (nth x 2)] 28 | (= (+ (square i) 29 | (square j)) 30 | (square k)))) 31 | (triples (iterate inc 1) 32 | (iterate inc 1) 33 | (iterate inc 1)))) 34 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_70.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.70 2 | 3 | (ns ex3-70) 4 | 5 | (defn pairs [s t] 6 | (lazy-seq 7 | (cons 8 | (list (first s) (first t)) 9 | (interleave 10 | (map (fn [x] (list (first s) x)) 11 | (next t)) 12 | (pairs (next s) (next t)))))) 13 | 14 | (defn merge-weighted [weight s1 s2] 15 | (lazy-seq 16 | (cond (nil? s1) s2 17 | (nil? s2) s1 18 | :else 19 | (let [x1 (first s1), x2 (first s2)] 20 | (if (<= (weight x1) (weight x2)) 21 | (cons x1 (merge-weighted weight (next s1) s2)) 22 | (cons x2 (merge-weighted weight s1 (next s2)))))))) 23 | 24 | (defn weighted-pairs [weight s t] 25 | (lazy-seq 26 | (cons 27 | (list (first s) (first t)) 28 | (merge-weighted weight 29 | (map (fn [x] (list (first s) x)) 30 | (next t)) 31 | (weighted-pairs weight (next s) (next t)))))) 32 | 33 | ; Look in ../test/test_ex3_70 for parts being tested 34 | ; a) 35 | (take 5 (weighted-pairs #(+ (first %) (second %)) (iterate inc 1) (iterate inc 1))) 36 | 37 | ; b) 38 | (def not-divisible 39 | (filter #(not (or (zero? (rem % 2)) 40 | (zero? (rem % 3)) 41 | (zero? (rem % 5)))) 42 | (iterate inc 1))) 43 | 44 | (take 5 (weighted-pairs #(let [i (first %) 45 | j (second %)] 46 | (+ (* 2 i) 47 | (* 3 j) 48 | (* 5 i j))) 49 | not-divisible 50 | not-divisible)) 51 | 52 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_71.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.71 2 | 3 | (ns ex3-71 4 | (:use ex3-70)) 5 | 6 | (defn cube [x] (* x x x)) 7 | 8 | (defn sum-of-cubes-pair [[x y]] 9 | (+ (cube x) (cube y))) 10 | 11 | (defn sum-of-cubes-stream [] 12 | (weighted-pairs sum-of-cubes-pair 13 | (iterate inc 1) 14 | (iterate inc 1))) 15 | 16 | (defn ramanujan-numbers [] 17 | ((fn find-next [s] 18 | (lazy-seq 19 | (let [w1 (sum-of-cubes-pair (first s)) 20 | w2 (sum-of-cubes-pair (second s))] 21 | (if (= w1 w2) 22 | (cons w1 (find-next (next s))) 23 | (find-next (next s)))))) 24 | (sum-of-cubes-stream))) 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_73.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.73 2 | 3 | (ns ex3-73 4 | (:use ex3-56)) 5 | 6 | (defn add-streams [s1 s2] 7 | (map + s1 s2)) 8 | 9 | (defn integral [integrand initial-value dt] 10 | ((fn inte [] 11 | (lazy-seq 12 | (cons initial-value 13 | (add-streams 14 | (scale-stream integrand dt) 15 | (inte))))))) 16 | 17 | 18 | (defn RC [R C dt] 19 | (fn [v0 i] 20 | (add-streams 21 | (scale-stream i R) 22 | (integral 23 | (scale-stream i (/ 1 C)) 24 | v0 25 | dt)))) 26 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_74.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.74 2 | 3 | (ns ex3-74) 4 | 5 | ; Making zero-crossings a function so you can pass 6 | ; any stream into it instead of global sense-data 7 | 8 | (defn sign-change-detector [x y] 9 | (cond (and (neg? x) (pos? y)) 1 10 | (and (pos? x) (neg? y)) -1 11 | :else 0)) 12 | 13 | ; So this divirges from question the book is asking. 14 | ; This change to zero-crossings makes it behave like 15 | ; the original version given before using stream-map. 16 | ; The version before using stream-map had 0 be the initial value 17 | ; and the below accomplishes the same thing 18 | (defn zero-crossings [s] 19 | (map sign-change-detector (cons 0 s) s)) 20 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_75.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.75 2 | 3 | (ns ex3-75 4 | (:use ex3-74)) 5 | 6 | ; Issue is that Reasoner's code is using the last average 7 | ; in computing the next average. He should be using the 8 | ; previous input signal value. 9 | 10 | (defn average [x y] 11 | (/ (+ x y) 2)) 12 | 13 | (defn make-zero-crossing [input-stream last-value last-avpt] 14 | (let [avpt (average (first input-stream) last-value)] 15 | (lazy-seq 16 | (cons (sign-change-detector avpt last-avpt) 17 | (make-zero-crossing (next input-stream) 18 | (first input-stream) 19 | avpt))))) 20 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_76.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.76 2 | 3 | (ns ex3-76 4 | (:use ex3-74)) 5 | 6 | (defn average-every-two [s] 7 | (map #(/ (+ %1 %2) 2) (cons 0 s) s)) 8 | 9 | (defn smoothed-zero-crossings [s smooth] 10 | (map sign-change-detector (cons 0 (smooth s)) (smooth s))) 11 | 12 | (defn smooth-by-averaging [s] 13 | (smoothed-zero-crossings s average-every-two)) 14 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_77.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.77 2 | 3 | (ns ex3-77 4 | (:use ex3-56)) 5 | 6 | (defn integral [delayed-integrand initial-value dt] 7 | (lazy-seq 8 | (cons initial-value 9 | (let [integrand (force delayed-integrand)] 10 | (if (nil? integrand) 11 | nil 12 | (integral 13 | (delay (rest integrand)) 14 | (+ (* dt (first integrand)) 15 | initial-value) 16 | dt)))))) 17 | 18 | (defn solve [f y0 dt] 19 | (letfn [(y [] (integral (delay (dy)) y0 dt)) 20 | (dy [] (map f (y)))] 21 | (y))) 22 | 23 | (comment (defn integral [delayed-integrand initial-value dt] 24 | ((fn int [] 25 | (lazy-seq 26 | (cons initial-value 27 | (let [integrand (force delayed-integrand)] 28 | (map + (scale-stream integrand dt) 29 | (int))))))))) 30 | 31 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_78.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.78 2 | 3 | (ns ex3-78 4 | (:use ex3-77)) 5 | 6 | (defn add-streams [s1 s2] 7 | (map + s1 s2)) 8 | 9 | (defn scale-stream [s x] 10 | (map #(* x %) s)) 11 | 12 | (defn solve-2nd [a b dt y0 dy0] 13 | (letfn [(y [] (integral (delay (dy)) y0 dt)) 14 | (dy [] (integral (delay (ddy)) dy0 dt)) 15 | (ddy [] (add-streams 16 | (scale-stream (dy) a) 17 | (scale-stream (y) b)))] 18 | (y))) -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_79.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.79 2 | 3 | (ns ex3-79 4 | (:use ex3-77)) 5 | 6 | (defn solve-2nd [f dt y0 dy0] 7 | (letfn [(y [] (integral (delay (dy)) y0 dt)) 8 | (dy [] (integral (delay (ddy)) dy0 dt)) 9 | (ddy [] (map f (dy) (y)))] 10 | (y))) 11 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_80.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.80 2 | 3 | (ns ex3-80 4 | (:use ex3-77)) 5 | 6 | (defn add-streams [s1 s2] 7 | (map + s1 s2)) 8 | (defn scale-stream [s x] 9 | (map #(* x %) s)) 10 | 11 | (defn RLC [R L C dt] 12 | (fn [vC0 iL0] 13 | (letfn [(iL [] (integral (delay (diL)) iL0 dt)) 14 | (diL [] (add-streams 15 | (scale-stream (iL) (- (/ R L))) 16 | (scale-stream (vC) (/ 1 L)))) 17 | (vC [] (integral (delay (dvC)) vC0 dt)) 18 | (dvC [] (scale-stream (iL) (/ -1 C)))] 19 | (list (vC) (iL))))) 20 | 21 | 22 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_81.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.81 2 | 3 | (ns ex3-81) 4 | 5 | (defn rand-update [x] 6 | (let [a 5.2 b 3.1 m 1.5] 7 | (mod (+ (* a x) 8 | b) 9 | m))) 10 | 11 | (defn gen-rand [cmds] 12 | ((fn me [next-value s] 13 | (lazy-seq 14 | (when-let [c (seq s)] 15 | (let [cmd (first c)] 16 | (cond (= :generate cmd) 17 | (cons next-value 18 | (me (rand-update next-value) 19 | (rest c))) 20 | (= :reset cmd) 21 | (cons (second c) 22 | (me (rand-update (second c)) 23 | (rest (rest c))))))))) 24 | 0.5 cmds)) 25 | 26 | -------------------------------------------------------------------------------- /clojure/section3.5/src/ex3_82.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 3.82 2 | 3 | (ns ex3-82 4 | (:use clojure.contrib.math)) 5 | 6 | (defn monte-carlo [experiment-stream passed failed] 7 | (letfn [(nxt [passed failed] 8 | (lazy-seq 9 | (cons (/ passed (+ passed failed)) 10 | (monte-carlo 11 | (rest experiment-stream) passed failed))))] 12 | (when (seq experiment-stream) 13 | (if (first experiment-stream) 14 | (nxt (inc passed) failed) 15 | (nxt passed (inc failed)))))) 16 | 17 | (defn random-in-range [low high] 18 | (+ low (rand (- high low)))) 19 | 20 | (defn rectangle-area [x1 x2 y1 y2] 21 | (abs (* (- x2 x1) (- y2 y1)))) 22 | 23 | (defn estimate-integral [p x1 x2 y1 y2] 24 | (map #(* % 25 | (rectangle-area x1 x2 y1 y2)) 26 | (monte-carlo 27 | (map p 28 | (repeatedly #(random-in-range x1 x2)) 29 | (repeatedly #(random-in-range x1 x2))) 30 | 0 0))) 31 | 32 | (defn estimate-pi-using-area-unit-circle [] 33 | (letfn [(square [x] (* x x)) 34 | (unit-circle-predicate 35 | [x y] 36 | (<= (+ (square x) (square y)) 1))] 37 | (estimate-integral 38 | unit-circle-predicate -1.0 1.0 -1.0 1.0))) 39 | 40 | 41 | -------------------------------------------------------------------------------- /clojure/section3.5/test/test_ex3_55.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns test-ex3-55 3 | (:use clojure.test 4 | ex3-55)) 5 | 6 | (def integers (iterate inc 1)) 7 | 8 | (deftest partial-sum-works 9 | (let [sums (partial-sum integers)] 10 | (is (= '(1 3 6 10 15) 11 | (take 5 sums))))) 12 | 13 | 14 | -------------------------------------------------------------------------------- /clojure/section3.5/test/test_ex3_59.clj: -------------------------------------------------------------------------------- 1 | ; Tests for ex3_59 2 | 3 | (ns test-ex3-59 4 | (:use clojure.test 5 | ex3-59)) 6 | 7 | (deftest part-a-works 8 | (is (= '(1 1/2 1/3 1/4) 9 | (take 4 (integrate-series (repeat 1)))))) 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /clojure/section3.5/test/test_ex3_61.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns test-ex3-61 3 | (:use ex3-61 4 | ex3-60 5 | clojure.test)) 6 | 7 | 8 | (deftest returns-inverted-series 9 | (let [s (iterate inc 1) 10 | res (take 5 (mul-series (invert-unit-series s) 11 | s))] 12 | (is (= '(1 0 0 0 0) res)))) 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /clojure/section3.5/test/test_ex3_70.clj: -------------------------------------------------------------------------------- 1 | ; Tess for ex3.70 2 | 3 | (ns test-ex3-70 4 | (:use ex3-70 5 | clojure.test)) 6 | 7 | (deftest test-merge-weighted 8 | (is (= '(1 1 2 2) (merge-weighted identity '(1 1) '(2 2)))) 9 | (is (= '(2 2 1 1) (merge-weighted - '(1 1) '(2 2))))) 10 | 11 | (deftest show-part-a-complete 12 | (is (= '((1 1) (1 2) (1 3) (2 2) (1 4)) 13 | (take 5 (weighted-pairs #(+ (first %) (second %)) 14 | (iterate inc 1) 15 | (iterate inc 1)))))) 16 | 17 | -------------------------------------------------------------------------------- /clojure/section3.5/test/test_ex3_74.clj: -------------------------------------------------------------------------------- 1 | ; Test for ex3.74 2 | 3 | (ns test-ex3-74 4 | (:use ex3-74 5 | clojure.test)) 6 | 7 | 8 | (deftest detects-sign-changes 9 | (is (= '(0 0 -1 0 1 0) 10 | (zero-crossings '(0.01 0.02 -0.01 -0.05 1 1))))) 11 | -------------------------------------------------------------------------------- /clojure/section4.1/.gitignore: -------------------------------------------------------------------------------- 1 | classes 2 | lib 3 | *.clj~ 4 | -------------------------------------------------------------------------------- /clojure/section4.1/project.clj: -------------------------------------------------------------------------------- 1 | (defproject SICP-section3-5 "1.0.0-SNAPSHOT" 2 | :description "Solutions to section 3.5 of SICP" 3 | :dependencies [[org.clojure/clojure "1.2.0-master-SNAPSHOT"] 4 | [org.clojure/clojure-contrib "1.2.0-master-SNAPSHOT"]] 5 | :dev-dependencies [[swank-clojure "1.2.1"]]) 6 | -------------------------------------------------------------------------------- /clojure/section4.1/src/environment.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns environment 3 | (:use scheme-helpers)) 4 | 5 | (defn enclosing-environment [env] (rest env)) 6 | 7 | (defn first-frame [env] (car env)) 8 | 9 | (def the-empty-environment '()) 10 | 11 | (defn make-frame [variables values] 12 | (atom (zipmap variables values))) 13 | 14 | (defn frame-variables [frame] (keys @frame)) 15 | 16 | (defn frame-values [frame] (vals @frame)) 17 | 18 | (defn add-binding-to-frame! [var val frame] 19 | (swap! frame assoc var val)) 20 | 21 | (defn extend-environment [vars vals base-env] 22 | (if (= (count vars) (count vals)) 23 | (cons (make-frame vars vals) base-env) 24 | (if (< (count vars) (count vals)) 25 | (Error. (str "Too many arguments supplied " vars vals)) 26 | (Error. (str "Too few arguments supplied " vars vals))))) 27 | 28 | (defn copy-environment [e] 29 | (doall (map #(atom @%) e))) 30 | 31 | (defn environments-equal? [x y] 32 | (reduce #(and %1 %2) true (map #(= @%1 @%2) x y))) 33 | 34 | (defn lookup-variable-value [variable env] 35 | (letfn [(env-loop [env] 36 | (letfn [(scan [frame] 37 | (if (contains? frame variable) 38 | (let [value (get frame variable)] 39 | (if (= value '*unassigned*) 40 | (Error. (str "Unassigned variable " variable)) 41 | value)) 42 | (env-loop (enclosing-environment env))))] 43 | (if (= env the-empty-environment) 44 | (Error. (str "Unbound variable " variable)) 45 | (let [frame (first-frame env)] 46 | (scan @frame)))))] 47 | (env-loop env))) 48 | 49 | 50 | (defn set-variable-value! [variable value env] 51 | (letfn [(env-loop [env] 52 | (letfn [(scan [frame] 53 | (if (contains? @frame variable) 54 | (swap! frame assoc variable value) 55 | (env-loop (enclosing-environment env))))] 56 | (if (= env the-empty-environment) 57 | (Error. (str "Unbound variable -- SET! " variable)) 58 | (scan (first-frame env)))))] 59 | (env-loop env))) 60 | 61 | (defn define-variable! [variable value env] 62 | (swap! (first-frame env) assoc variable value)) 63 | 64 | (defn unbind-variable! [variable env] 65 | (swap! (first-frame env) dissoc variable)) -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_1.clj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakemcc/sicp-study/3b9e3d6c8cc30ad92b0d9bbcbbbfe36a8413f89d/clojure/section4.1/src/ex4_1.clj -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_11.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.11 2 | 3 | ; Look at environment.clj. Actually used Clojure's maps. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_12.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.12 2 | 3 | ; I'm choosing not do this. I don't think there is enough value is writing up this problem. 4 | -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_13.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.13 2 | 3 | ; Functionality has been added to environment.clj, environment_test.clj, 4 | ; section4.clj and section4_test.clj 5 | 6 | ; I decided to only have the variable become unbound in the current 7 | ; scope (whatever the first frame of the environment is). This seems to make 8 | ; the most sense to me. Being able to traverse all the frames to remove 9 | ; a binding seems like the wrong thing. Especially when you consider that 10 | ; a variable could be bound at different frames. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_14.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.14 2 | 3 | ; Eva wrote her version in the interpreted Scheme. Since the Scheme 4 | ; we can interpret is fairly complete assuming her implementation 5 | ; of it is correct then there is no reason why it should not work. 6 | 7 | ; Louis mixed the interpreted language with the host language (language 8 | ; which is driving the interpreter). This won't work as map takes a function 9 | ; as a parameter, which in this case would be written in the interpretted 10 | ; Scheme but the implementation of map would be in the host language. The 11 | ; host languages map expects the function it is applying to be in the host langauge. 12 | ; Applying the function in the host language is done differently then 13 | ; applying it in the interpretted language. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_15.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.15 2 | 3 | ;http://en.wikipedia.org/wiki/Halting_problem 4 | 5 | ; (define (run-forever) (run-forever)) 6 | ; (define (try p) 7 | ; (if (halts? p p) 8 | ; (run-forever) 9 | ; 'halted)) 10 | 11 | ; If we were to evaluate (try try) then we end up doing 12 | ; (halts? try try). 13 | 14 | ; a) If (halts? try try) returns true -> (run-forever) is called and app runs forever 15 | ; b) If (halts? try try) returns false -> 'halted is returned 16 | 17 | ; in case 'a' halts? claims that (try try) will halt but then it runs forever 18 | ; In case 'b' halts? claims it doesn't halt, but then it does. 19 | 20 | ; Because of these contradictions we know there cannot be a halts? which 21 | ; does what the specification asks. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_16.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.16 2 | 3 | ; Solved in section4.clj and section4_test.clj 4 | 5 | ; I ended up doing part c (installing scan-out-defines) in interpreter by adding 6 | ; it to make-procedure instead of procedure-body. I did this so that 7 | ; the transformation would only have to happen once instead of everytime 8 | ; a procedure body is invoked. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_17.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.17 2 | 3 | ; When it is scanned out there is an extra environment frame. 4 | ; This is because scan-out-defines wraps the body of the method 5 | ; in a let to accomplish its goal. A let gets turned into a lambda 6 | ; which adds a frame. 7 | 8 | ; This won't make a difference. Anything that would have previously been 9 | ; available to the method body would still be available since its frame 10 | ; inherits any vars from the frame that contains it. 11 | 12 | ; We would need to move the internal definitions to be in the higher scope 13 | ; and resist making an extra frame by using let to do so. This would work 14 | ; as when the internal definitions get executed they would resolve 15 | ; their references to valid values -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_18.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.18 2 | 3 | ; No this will not work. When is assigned to b 4 | ; that will evaluate the y in the definition is expected 5 | ; to be there. It will not be there as it hasn't (set! u a) 6 | ; hasn't been evaluated yet. 7 | 8 | 9 | ; This will work with the original. By the time would be evaled 10 | ; has already been setup so it will work -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_19.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.19 2 | 3 | ; I actually like Ben's point of view. This probably comes from a background 4 | ; of doing FPGA programming and a view that this type of assignment can happen all at 5 | ; the same time. I would say that in his defines are truely being done at the 6 | ; same time. 7 | 8 | 9 | ; To implement Eva's idea you could scan what is being assigned to the vars 10 | ; for other vars that are being assigned at the same time and 11 | ; order the assignment in a way where it works. This is a tricky problem though 12 | ; and would be a complex algorithm. Dealing with mutal recursion would be 13 | ; difficult. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_2.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.2 2 | 3 | ; a) 4 | ; The eval function originally treats any list that isn't 5 | ; caught by one of the special cases before the application? 6 | ; check as a procedure to be evaluated. After Loui's moves 7 | ; the application? check before the assignment? check 8 | ; then (define x 3) will be evaluated and treated as thought 9 | ; define is a procedure to be called with x and 3 as arguments. 10 | 11 | ; b) If Louis changes it so that application? checks for a tagged list 12 | ; then he could make this work. For example, doing 13 | ; (defn application? [exp] (tagged-list? exp 'application) 14 | ; and then changing (operator) and (operands) to handle 15 | ; the addition of a tag could make this work. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_20.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.20 2 | 3 | ; Part a: 4 | ; Implemented in section4.clj and section4_test.clj -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_21.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.21 2 | 3 | (ns ex4-21) 4 | 5 | (defn factorial [n] 6 | ((fn [fact] 7 | (fact fact n)) 8 | (fn [ft k] 9 | (if (= k 1) 10 | 1 11 | (* k (ft ft (- k 1))))))) 12 | 13 | ; Part a 14 | (defn fibonacci [n] 15 | (if (<= n 2) 16 | 1 17 | ((fn [fib] 18 | (fib fib 1 1 n)) 19 | (fn [ft x y k] 20 | (if (= k 2) 21 | y 22 | (ft ft y (+ x y) (- k 1))))))) 23 | 24 | ; Part b 25 | (defn is-even? [x] 26 | ((fn [even? odd?] 27 | (even? even? odd? x)) 28 | (fn [ev? od? n] 29 | (if (= n 0) true (od? ev? od? (- n 1)))) 30 | (fn [ev? od? n] 31 | (if (= n 0) false (ev? ev? od? (- n 1)))))) 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_22.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.22 2 | 3 | ; Look in section4_optimized.clj and corresponding test file for 4 | ; implementation fo this. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_23.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.23 2 | 3 | ; Alyssa's version does more work at runtime, whereas the version 4 | ; in the text book does much of the work when it analyzes the code. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_24.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.24 2 | 3 | (ns ex4-24 4 | (:require [section4 :as s4] 5 | [section4-optimized :as s4o])) 6 | 7 | (def func 8 | '(define (add-positive x y) 9 | (if (or (< x 0) (< y 0)) (Error. "Must add positive numbers")) 10 | (if (= x 0) 11 | y 12 | (add-positive (- x 1) (+ y 1))))) 13 | 14 | (s4/interpret func) 15 | (s4o/interpret func) 16 | 17 | (println "Time for unoptimized: ") 18 | (time (dotimes [x 30] (s4/interpret '(add-positive 20 35)))) 19 | 20 | (println "Time for optimized: ") 21 | (time (dotimes [x 30] (s4o/interpret '(add-positive 20 35)))) 22 | 23 | ;Time for unoptimized: 24 | ;"Elapsed time: 231.454 msecs" 25 | ;Time for optimized: 26 | ;"Elapsed time: 98.1 msecs" 27 | 28 | ; Looks like the original evaluated wastes a lot of time 29 | ; analyzing the same expressions multiple times 30 | 31 | -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_5.clj: -------------------------------------------------------------------------------- 1 | ; Exerise 4.5 was done in section4.clj and section4_tests.clj -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_6.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.6 has been implemented in section4.clj and tested in section4_test.clj -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_7.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.7 is solved in section4.clj and tested in section4_test.clj 2 | 3 | ; To answer the question posed in the book, yes you can implement let* by 4 | ; expanding it into nested lets. -------------------------------------------------------------------------------- /clojure/section4.1/src/ex4_8.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.8 has been solved in section4.clj and section4_test.clj -------------------------------------------------------------------------------- /clojure/section4.1/src/scheme_helpers.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns scheme-helpers) 3 | 4 | (defn car [x] (first x)) 5 | (defn cdr [x] (next x)) 6 | (defn cadr [x] (second x)) 7 | (defn caddr [x] (first (next (next x)))) 8 | (defn cdddr [x] (next (next (next x)))) 9 | (defn caddr [x] (first (next (next x)))) 10 | (defn cadddr [x] (first (next (next (next x))))) 11 | (defn null? [x] (nil? x)) 12 | -------------------------------------------------------------------------------- /clojure/section4.1/test/environment_test.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns environment-test 3 | (:use clojure.test 4 | environment)) 5 | 6 | (deftest can-create-frame 7 | (let [f (make-frame '(a b c d) '(1 2 3 4))] 8 | (is (= '(a b c d) (sort (frame-variables f)))) 9 | (is (= '(1 2 3 4) (sort (frame-values f)))))) 10 | 11 | (deftest can-add-vars-to-frame 12 | (let [f (make-frame '() '())] 13 | (add-binding-to-frame! 'a 1 f) 14 | (is (= '(a) (frame-variables f))) 15 | (is (= '(1) (frame-values f))))) 16 | 17 | (deftest can-lookup-variable-in-environment 18 | (let [e (extend-environment '(a b c d) 19 | '(1 2 3 4) 20 | the-empty-environment)] 21 | (is (= 1 (lookup-variable-value 'a e))))) 22 | 23 | (deftest can-set-variable-in-environment 24 | (let [e (extend-environment '(a b c d) 25 | '(1 2 3 4) 26 | the-empty-environment)] 27 | (set-variable-value! 'a 10 e) 28 | (is (= 10 (lookup-variable-value 'a e))))) 29 | 30 | (deftest can-define-new-variable 31 | (let [e (extend-environment '(a b c d) 32 | '(1 2 3 4) 33 | the-empty-environment)] 34 | (define-variable! 'e 5 e) 35 | (is (= 5 (lookup-variable-value 'e e))))) 36 | 37 | (deftest can-define-variable-which-already-exists 38 | (let [e (extend-environment '(a b c d) 39 | '(1 2 3 4) 40 | the-empty-environment)] 41 | (define-variable! 'b 11 e) 42 | (is (= 11 (lookup-variable-value 'b e))))) 43 | 44 | (deftest can-lookup-variables-which-have-false-value 45 | (let [e (extend-environment '(a b c d) 46 | '(1 2 3 4) 47 | the-empty-environment)] 48 | (define-variable! 'g false e) 49 | (define-variable! 'f nil e) 50 | (is (= false (lookup-variable-value 'g e))) 51 | (is (= nil (lookup-variable-value 'f e))))) 52 | 53 | (deftest need-to-make-copy-of-environment 54 | (let [e (extend-environment '(a) 55 | '(1) 56 | the-empty-environment) 57 | e2 (copy-environment e)] 58 | (is (environments-equal? e e2)) 59 | (define-variable! 'b 2 e2) 60 | (is (not (environments-equal? e e2))))) 61 | 62 | (deftest can-unbind-variable-from-frame 63 | (let [e (extend-environment '(a b c d) 64 | '(1 2 3 4) 65 | the-empty-environment)] 66 | (is (= 1 (lookup-variable-value 'a e))) 67 | (unbind-variable! 'a e) 68 | (is (= (type (Error.)) (type (lookup-variable-value 'a e)))))) 69 | 70 | ; Exercise 4.16(a) 71 | (deftest unassigned-variable-gets-error 72 | (let [e (extend-environment '(a) 73 | '(1) 74 | the-empty-environment)] 75 | (set-variable-value! 'e '*unassigned* e) 76 | (is (= (type (Error.)) (type (lookup-variable-value 'e e)))))) 77 | -------------------------------------------------------------------------------- /clojure/section4.1/test/ex4_21_test.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns ex4-21-test 3 | (:use ex4-21 4 | clojure.test)) 5 | 6 | (deftest can-use-lambdas-to-recurse 7 | (is (= 3628800 8 | (factorial 10)))) 9 | 10 | (deftest can-calculate-fibonacci-numbers 11 | (are [a x] (= a (fibonacci x)) 12 | 1 1 13 | 1 2 14 | 2 3 15 | 3 4)) 16 | 17 | (deftest can-tell-if-even 18 | (are [a x] (= a (is-even? x)) 19 | true 2 20 | false 3)) 21 | 22 | -------------------------------------------------------------------------------- /clojure/section4.1/test/ex4_3_tests.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns ex4-3-tests 3 | (:use clojure.test 4 | ex4-3)) 5 | 6 | (use-fixtures :each (fn [f] (reset-global-environment) (f))) 7 | 8 | (deftest test-self-eval 9 | (is (= 5 (interpret 5))) 10 | (is (= "hey" (interpret "hey")))) 11 | 12 | (deftest test-expressions 13 | (are [x y] (= x y) 14 | 3 (interpret '(+ 1 2)) 15 | -14 (interpret '(* (- 10 3) (- 4 6))) 16 | 8 (interpret '(* (/ 4 2) (- 6 4) (+ 1 1))))) 17 | 18 | (deftest test-quoted 19 | (are [x y] (= x y) 20 | 2 (interpret '(quote 2)) 21 | 'howdy (interpret '(quote howdy)) 22 | '(jake jim 2) (interpret '(quote (jake jim 2))))) 23 | 24 | (deftest test-if 25 | (are [x] (true? x) 26 | (interpret '(if (= 1 1) true false)) 27 | (interpret '(if (= 1 0) false true)))) 28 | 29 | (deftest test-cond 30 | (are [x] (true? (interpret x)) 31 | '(cond ((= 1 2) false) 32 | ((= 2 2) true) 33 | ((= 2 3) false)) 34 | '(cond ((= 1 2) false) 35 | ((= 2 3) false) 36 | (else true)))) 37 | 38 | (deftest test-or 39 | (is (interpret '(or 5 4 3))) 40 | (is (false? (interpret '(or false false))))) 41 | 42 | (deftest test-and 43 | (is (true? (interpret '(and true true)))) 44 | (is (false? (interpret '(and false true))))) 45 | 46 | (deftest test-vars 47 | (interpret '(define twelve 12)) 48 | (is (= 12 (interpret 'twelve))) 49 | (is (= 14 (interpret '(+ twelve 2)))) 50 | (interpret '(define two 2)) 51 | (is (= 2 (interpret 'two))) 52 | (is (= 14 (interpret '(+ two twelve)))) 53 | (interpret '(set! twelve 9)) 54 | (is (= 9 (interpret 'twelve)))) 55 | 56 | (deftest test-define 57 | (interpret 58 | '(define (ident a) a)) 59 | (interpret '(define (sum a b) (+ a b))) 60 | (is (= 5 (interpret '(ident 5)))) 61 | (is (= 10 (interpret '(sum 4 6)))) 62 | (is (= 11 (interpret '(sum (ident 5) 6))))) 63 | 64 | (deftest test-lambdas 65 | (is (= 10 (interpret '((lambda (a b) (+ a b)) 7 3))))) 66 | 67 | (deftest test-recursive-function 68 | (interpret 69 | '(define (exp x y) 70 | (if (= y 1) 71 | x 72 | (exp (* x x) (- y 1))))) 73 | (is (= 25 (interpret '(exp 5 2))))) 74 | -------------------------------------------------------------------------------- /clojure/section4.1/test/section4_optimized_test.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns section4-optimized-test 3 | (:use clojure.test 4 | section4-optimized)) 5 | 6 | (use-fixtures :each (fn [f] (reset-global-environment) (f))) 7 | 8 | (deftest test-self-eval 9 | (is (= 5 (interpret 5))) 10 | (is (= "hey" (interpret "hey")))) 11 | 12 | (deftest test-expressions 13 | (are [x y] (= x y) 14 | 3 (interpret '(+ 1 2)) 15 | -14 (interpret '(* (- 10 3) (- 4 6))) 16 | 8 (interpret '(* (/ 4 2) (- 6 4) (+ 1 1))))) 17 | 18 | (deftest test-quoted 19 | (are [x y] (= x y) 20 | 2 (interpret '(quote 2)) 21 | 'howdy (interpret '(quote howdy)) 22 | '(jake jim 2) (interpret '(quote (jake jim 2))))) 23 | 24 | (deftest test-if 25 | (are [x] (true? (interpret x)) 26 | '(if (= 1 1) true false) 27 | '(if (= 1 0) false true) 28 | '(if 1 true false))) 29 | 30 | (deftest test-cond 31 | (are [x] (true? (interpret x)) 32 | '(cond ((= 1 2) false) 33 | ((= 2 2) true) 34 | ((= 2 3) false)) 35 | '(cond ((= 1 2) false) 36 | ((= 2 3) false) 37 | (else true)))) 38 | 39 | ; For exercise 4.5 40 | (deftest test-different-cond-format 41 | (is (= 2 (interpret '(cond ((1 2 3) => cadr) 42 | (else false)))))) 43 | 44 | (deftest test-or 45 | (is (interpret '(or 5 4 3))) 46 | (is (false? (interpret '(or false false))))) 47 | 48 | (deftest test-and 49 | (is (true? (interpret '(and true true)))) 50 | (is (false? (interpret '(and false true))))) 51 | 52 | (deftest test-vars 53 | (interpret '(define twelve 12)) 54 | (is (= 12 (interpret 'twelve))) 55 | (is (= 14 (interpret '(+ twelve 2)))) 56 | (interpret '(define two 2)) 57 | (is (= 2 (interpret 'two))) 58 | (is (= 14 (interpret '(+ two twelve)))) 59 | (interpret '(set! twelve 9)) 60 | (is (= 9 (interpret 'twelve)))) 61 | 62 | (deftest test-define 63 | (interpret 64 | '(define (ident a) a)) 65 | (interpret '(define (sum a b) (+ a b))) 66 | (is (= 5 (interpret '(ident 5)))) 67 | (is (= 10 (interpret '(sum 4 6)))) 68 | (is (= 11 (interpret '(sum (ident 5) 6))))) 69 | 70 | (deftest test-lambdas 71 | (is (= 10 (interpret '((lambda (a b) (+ a b)) 7 3))))) 72 | 73 | (deftest test-recursive-function 74 | (interpret 75 | '(define (exp x y) 76 | (if (= y 1) 77 | x 78 | (exp (* x x) (- y 1))))) 79 | (is (= 25 (interpret '(exp 5 2))))) 80 | 81 | ; Exercise 4.22 82 | (deftest basic-let-form-works 83 | (is (= 2 84 | (interpret '(let ((a 2)) 85 | a)))) 86 | (is (= 42 87 | (interpret '(let ((a 2) (b 40)) 88 | (+ a b)))))) 89 | 90 | -------------------------------------------------------------------------------- /clojure/section4.2/.gitignore: -------------------------------------------------------------------------------- 1 | lib 2 | -------------------------------------------------------------------------------- /clojure/section4.2/project.clj: -------------------------------------------------------------------------------- 1 | (defproject SICP-section3-5 "1.0.0-SNAPSHOT" 2 | :description "Solutions to section 3.5 of SICP" 3 | :dependencies [[org.clojure/clojure "1.2.0-master-SNAPSHOT"] 4 | [org.clojure/clojure-contrib "1.2.0-master-SNAPSHOT"]] 5 | :dev-dependencies [[swank-clojure "1.2.1"]]) 6 | -------------------------------------------------------------------------------- /clojure/section4.2/src/environment.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns environment 3 | (:use scheme-helpers)) 4 | 5 | (defn enclosing-environment [env] (rest env)) 6 | 7 | (defn first-frame [env] (car env)) 8 | 9 | (def the-empty-environment '()) 10 | 11 | (defn make-frame [variables values] 12 | (atom (zipmap variables values))) 13 | 14 | (defn frame-variables [frame] (keys @frame)) 15 | 16 | (defn frame-values [frame] (vals @frame)) 17 | 18 | (defn add-binding-to-frame! [var val frame] 19 | (swap! frame assoc var val)) 20 | 21 | (defn extend-environment [vars vals base-env] 22 | (if (= (count vars) (count vals)) 23 | (cons (make-frame vars vals) base-env) 24 | (if (< (count vars) (count vals)) 25 | (Error. (str "Too many arguments supplied " vars vals)) 26 | (Error. (str "Too few arguments supplied " vars vals))))) 27 | 28 | (defn copy-environment [e] 29 | (doall (map #(atom @%) e))) 30 | 31 | (defn environments-equal? [x y] 32 | (reduce #(and %1 %2) true (map #(= @%1 @%2) x y))) 33 | 34 | (defn lookup-variable-value [variable env] 35 | (letfn [(env-loop [env] 36 | (letfn [(scan [frame] 37 | (if (contains? frame variable) 38 | (let [value (get frame variable)] 39 | (if (= value '*unassigned*) 40 | (Error. (str "Unassigned variable " variable)) 41 | value)) 42 | (env-loop (enclosing-environment env))))] 43 | (if (= env the-empty-environment) 44 | (Error. (str "Unbound variable " variable)) 45 | (let [frame (first-frame env)] 46 | (scan @frame)))))] 47 | (env-loop env))) 48 | 49 | 50 | (defn set-variable-value! [variable value env] 51 | (letfn [(env-loop [env] 52 | (letfn [(scan [frame] 53 | (if (contains? @frame variable) 54 | (swap! frame assoc variable value) 55 | (env-loop (enclosing-environment env))))] 56 | (if (= env the-empty-environment) 57 | (Error. (str "Unbound variable -- SET! " variable)) 58 | (scan (first-frame env)))))] 59 | (env-loop env))) 60 | 61 | (defn define-variable! [variable value env] 62 | (swap! (first-frame env) assoc variable value)) 63 | 64 | (defn unbind-variable! [variable env] 65 | (swap! (first-frame env) dissoc variable)) -------------------------------------------------------------------------------- /clojure/section4.2/src/ex4_25.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.25 2 | 3 | ; The definition will not work in the applicative order langauge. 4 | ; This is because all of the arguments to unless will be evaluated 5 | ; when they are passed into unless. This would cause an infinite loop 6 | ; as factorial will keep getting called with smaller and smaller values. 7 | 8 | ; In a normal order langauge this would work. Then arguments would 9 | ; only be evaluated when needed. Thi would cause the conditional 10 | ; to be evaluated and eventually it would be true, causing 11 | ; the factorial call to not be called. -------------------------------------------------------------------------------- /clojure/section4.2/src/ex4_26.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.26 2 | 3 | ; It is very simple to imagine implementing unless as a 4 | ; special form (macro). We would simply need to transform 5 | ; unless into an if statement prior to evaluating it. I'm not 6 | ; going to bother to write this simple code. 7 | 8 | 9 | ; You may not want unless to be a special form if you could want 10 | ; to pass it into another function. This is at least not possible 11 | ; to pass a macro into a clojure function. -------------------------------------------------------------------------------- /clojure/section4.2/src/ex4_27.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.27 2 | 3 | ;(define w (id (id 10))) 4 | ;;; L-Eval input: 5 | ;count 6 | ;;; L-Eval value: 7 | ; = 0 8 | ;;; L-Eval input: 9 | ;w 10 | ;;; L-Eval value: 11 | ; = 10 12 | ;;; L-Eval input: 13 | ;count 14 | ;;; L-Eval value: 15 | ; = 2 16 | 17 | ; After the definition of w nothing has happened yet so 18 | ; count still equals zero. 19 | 20 | ; After w is used then (id) gets called twice, causing 21 | ; count to be incremented twice. -------------------------------------------------------------------------------- /clojure/section4.2/src/ex4_28.clj: -------------------------------------------------------------------------------- 1 | ; exercise 4.28 2 | 3 | (ns ex4-48 4 | (:use section4)) 5 | 6 | (interpret '(define (p f x y z) 7 | (f x y z))) 8 | 9 | (interpret (define (sum x y z) 10 | (+ x y z))) 11 | 12 | (interpret (p sum 1 2 3)) 13 | 14 | ; The above works. 15 | 16 | ; We need to get the actual value because otherwise when 17 | ; p is passed f to evaulaute it would be evaluating a thunk 18 | ; and not a function. Hence need to use the book version which 19 | ; uses actual-value and not eval. -------------------------------------------------------------------------------- /clojure/section4.2/src/ex4_29.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.29 2 | 3 | 4 | ; A sample program which would run more slowly without memoization 5 | ; would be a simple recurisive factorial problem. 6 | 7 | (comment 8 | (define (fact n) 9 | (if (= 0 n) 10 | 1 11 | (* n (fact (- n 1)))))) 12 | 13 | (comment 14 | (define (square x) 15 | (* x x)) 16 | ;;; L-Eval input: 17 | (square (id 10)) 18 | ;;; L-Eval value: 19 | 20 | ;;; L-Eval input: 21 | count 22 | ;;; L-Eval value: 23 | ) 24 | 25 | ; if memoized then the first response is 100 and the second is 1. 26 | ; if not memoized then the first is still 100 but the second is 2. -------------------------------------------------------------------------------- /clojure/section4.2/src/ex4_30.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.30 2 | 3 | ; a) Each element gets evaluated as the first argument in the begin s-exp. 4 | ; The display s-exp causes the value to be realized since display is 5 | ; primitive. 6 | 7 | ; b) original eval-sequence: 8 | ; (p1 1) => '(1 2) 9 | ; (p2 1) => 1 10 | ; new eval-sequence: 11 | ; (p1 1) => '(1 2) 12 | ; (p2 1) => '(1 2) 13 | 14 | ; c) The example already calls a primitive on each element 15 | ; in the list. Calling actual-value on it as well doesn't do anything 16 | ; bad. 17 | 18 | ; d) I actually like Cy's approach better. It seems to be like it handles 19 | ; side effects in a better way. As someone writing code I don't want to 20 | ; have the burden of thinking about if all of my expressions are going 21 | ; to be executed or not. -------------------------------------------------------------------------------- /clojure/section4.2/src/ex4_32.clj: -------------------------------------------------------------------------------- 1 | ; Exercise 4.32 2 | 3 | ; These lists are competely lazy. The car and the cdr 4 | ; are delayed. This can be useful to buid infinate tree 5 | ; structures and be able to manipulate them without 6 | ; worrying the infiniteness. 7 | -------------------------------------------------------------------------------- /clojure/section4.2/src/scheme_helpers.clj: -------------------------------------------------------------------------------- 1 | 2 | (ns scheme-helpers) 3 | 4 | (defn car [x] (first x)) 5 | (defn cdr [x] (next x)) 6 | (defn cadr [x] (second x)) 7 | (defn caddr [x] (first (next (next x)))) 8 | (defn cdddr [x] (next (next (next x)))) 9 | (defn caddr [x] (first (next (next x)))) 10 | (defn cadddr [x] (first (next (next (next x))))) 11 | (defn null? [x] (nil? x)) 12 | -------------------------------------------------------------------------------- /clojure/section4.3/src/ex4_35.clj: -------------------------------------------------------------------------------- 1 | (ns ex4-35) 2 | 3 | (defn an-integer-between [n z] 4 | (if (> n z) 5 | (amb) 6 | (amb n (an-integer-between (inc n) z)))) 7 | 8 | -------------------------------------------------------------------------------- /clojure/section4.3/src/ex4_36.clj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakemcc/sicp-study/3b9e3d6c8cc30ad92b0d9bbcbbbfe36a8413f89d/clojure/section4.3/src/ex4_36.clj -------------------------------------------------------------------------------- /clojure/section4.3/src/ex4_47.clj: -------------------------------------------------------------------------------- 1 | (ns ex4-37) 2 | 3 | ; My initial reaction is that Ben Bitdiddle's change 4 | ; does improve the efficiency. 5 | 6 | ; It seems to me that because the first 'require check is 7 | ; done earlier (only after i and j have been picked, k is still 8 | ; unpicked) that the work of chosing a k will not always be done. 9 | ; Not doing the work to pick k would cut down on the number of 10 | ; possibilities that need to be checked and hence cause an efficiency 11 | ; gain -------------------------------------------------------------------------------- /q/section1.2/1.12.q: -------------------------------------------------------------------------------- 1 | nextrow:{[p] 2 msum p, 0}; 2 | pth:{[p; n] $[0 = n; p; pth[nextrow p;n-1]]}; 3 | pt:{[n] pth[1; n]}; 4 | 5 | show pt 0; 6 | show pt 1; 7 | show pt 2; 8 | show pt 3; 9 | show pt 4; 10 | show pt 5; 11 | --------------------------------------------------------------------------------