Skip to content

Commit 4d36cd9

Browse files
committed
add three chapter 2 solutions & tests
1 parent 4f6b55d commit 4d36cd9

File tree

5 files changed

+302
-1
lines changed

5 files changed

+302
-1
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ My solutions to exercises of the CS textbook ['Structure and Interpretation of C
77
* Each `src` file is self-contained, and deals with either one or multiple related exercises
88
* Tests are included in the `test` directory
99

10-
Currently only Chapter 1 solutions and tests are uploaded (but I expect to add more). Any corrections or enhancements are welcome. Have fun!
10+
Currently only Chapter 1 and few Chapter 2 solutions and tests are uploaded (but I expect to add more). Any corrections or enhancements are welcome. Have fun!
1111

1212
## License
1313

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
; sicp-clojure - SICP exercise solutions in Clojure
2+
; Copyright (C) 2022 Ioannis Stefanis
3+
4+
; This file is part of sicp-clojure.
5+
6+
; sicp-clojure is free software: you can redistribute it and/or modify
7+
; it under the terms of the GNU General Public License as published by
8+
; the Free Software Foundation, either version 3 of the License, or
9+
; (at your option) any later version.
10+
11+
; sicp-clojure is distributed in the hope that it will be useful, but
12+
; WITHOUT ANY WARRANTY; without even the implied warranty of
13+
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
; General Public License for more details.
15+
16+
; You should have received a copy of the GNU General Public License
17+
; along with sicp-clojure. If not, see <https://www.gnu.org/licenses/>.
18+
19+
20+
(ns sicp_clojure.ch_2.ex_01_rational_numbers)
21+
22+
23+
;////// 2.1 //////
24+
;improve the function that defines rational numbers,
25+
;so that it can also normalize its sign
26+
27+
;utils
28+
(defn gcd [a b]
29+
(if (= b 0)
30+
a
31+
(gcd b (mod a b))))
32+
33+
;instead of: {list, car, cdr, cadr} of other Lisp dialects,
34+
;in Clojure we can use: {vector, first, next, second}
35+
;(a two-element vector does not resemble a cons pair,
36+
;but a list of two elements)
37+
38+
(defn make-rat-version1 [n d]
39+
(vector n d))
40+
41+
(defn make-rat-version2 [n d] ;normalizes sign
42+
(let [g (gcd n d)] ;(the existing implementation works fine)
43+
(vector (/ n g) (/ d g))))
44+
45+
(defn make-rat-version3 [n d] ;normalizes sign
46+
((fn [g] (vector (/ n g) (/ d g))) ;function application
47+
(gcd n d)))
48+
49+
(def make-rat make-rat-version2)
50+
51+
(defn numer [x] (first x))
52+
(defn denom [x] (second x))
53+
54+
(defn add-rat [x y]
55+
(make-rat (+ (* (numer x) (denom y)) (* (denom x) (numer y)))
56+
(* (denom x) (denom y))))
57+
58+
(defn sub-rat [x y]
59+
(make-rat (- (* (numer x) (denom y)) (* (denom x) (numer y)))
60+
(* (denom x) (denom y))))
61+
62+
(defn mul-rat [x y]
63+
(make-rat (* (numer x) (numer y))
64+
(* (denom x) (denom y))))
65+
66+
(defn div-rat [x y]
67+
(make-rat (* (numer x) (denom y))
68+
(* (denom x) (numer x))))
69+
70+
(defn equal-rat? [x y]
71+
(= (* (numer x) (denom y)) (* (denom x) (numer y))))
72+
73+
(defn print-rat [x]
74+
(println (numer x) "/" (denom x)))
75+
76+
;implementation
77+
(defn sign [x]
78+
(if (= x 0)
79+
0
80+
(/ x (Math/abs x))))
81+
82+
(defn make-rat-version4 [n d] ;normalizes sign
83+
(let [g (gcd (Math/abs n) (Math/abs d))
84+
s (sign d)]
85+
(vector (/ n (* g s))
86+
(/ d (* g s)))))
87+
88+
(defn make-rat-version5 [n d] ;normalizes sign
89+
(let [g (gcd (Math/abs n) (Math/abs d))
90+
s (sign d)]
91+
(vector (* (/ n g) s)
92+
(/ (Math/abs d) g))))
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
; sicp-clojure - SICP exercise solutions in Clojure
2+
; Copyright (C) 2022 Ioannis Stefanis
3+
4+
; This file is part of sicp-clojure.
5+
6+
; sicp-clojure is free software: you can redistribute it and/or modify
7+
; it under the terms of the GNU General Public License as published by
8+
; the Free Software Foundation, either version 3 of the License, or
9+
; (at your option) any later version.
10+
11+
; sicp-clojure is distributed in the hope that it will be useful, but
12+
; WITHOUT ANY WARRANTY; without even the implied warranty of
13+
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
; General Public License for more details.
15+
16+
; You should have received a copy of the GNU General Public License
17+
; along with sicp-clojure. If not, see <https://www.gnu.org/licenses/>.
18+
19+
20+
(ns sicp_clojure.ch_2.ex_02_03_geometric_elements)
21+
22+
23+
;////// 2.2 & 2.3 //////
24+
;implement representations for points, line segments and plane rectangles
25+
26+
;utils
27+
(defn average [x y] (/ (+ x y) 2))
28+
(defn square [x] (* x x))
29+
30+
;implementation (2.2)
31+
(defn make-point [x y] (vector x y))
32+
(defn x-point [p] (first p))
33+
(defn y-point [p] (second p))
34+
(defn print-point [p] (println "(" (x-point p) "," (y-point p) ")"))
35+
36+
(defn distance [p1 p2]
37+
(Math/sqrt (+ (square (- (x-point p1) (x-point p2)))
38+
(square (- (y-point p1) (y-point p2))))))
39+
40+
(defn make-segment [p1 p2] (vector p1 p2))
41+
(defn start-segment [s] (first s))
42+
(defn end-segment [s] (second s))
43+
44+
(defn midpoint-segment [s]
45+
(make-point (average (x-point (start-segment s)) (x-point (end-segment s)))
46+
(average (y-point (start-segment s)) (y-point (end-segment s)))))
47+
48+
;implementation (2.3)
49+
50+
;representation in terms of points (their order is important)
51+
(defn rectangle-version1 [p1 p2 p3 p4] (vector 1 p1 p2 p3 p4))
52+
53+
(defn rect-version1-p1 [r] (first (next r)))
54+
(defn rect-version1-p2 [r] (first (next (next r))))
55+
(defn rect-version1-p3 [r] (first (next (next (next r)))))
56+
(defn rect-version1-p4 [r] (second (next (next (next r)))))
57+
58+
;alternative representation in terms of segments (their order is important)
59+
(defn rectangle-version2 [s1 s2 s3 s4] (vector 2 s1 s2 s3 s4))
60+
61+
(defn rect-version2-p1 [r] (start-segment (first (next r))))
62+
(defn rect-version2-p2 [r] (start-segment (first (next (next r)))))
63+
(defn rect-version2-p3 [r] (start-segment (first (next (next (next r))))))
64+
(defn rect-version2-p4 [r] (start-segment (second (next (next (next r))))))
65+
66+
(defn representation [r] (first r))
67+
68+
(defn rect-p1 [r]
69+
(cond (= (representation r) 1) (rect-version1-p1 r)
70+
(= (representation r) 2) (rect-version2-p1 r)))
71+
(defn rect-p2 [r]
72+
(cond (= (representation r) 1) (rect-version1-p2 r)
73+
(= (representation r) 2) (rect-version2-p2 r)))
74+
(defn rect-p3 [r]
75+
(cond (= (representation r) 1) (rect-version1-p3 r)
76+
(= (representation r) 2) (rect-version2-p3 r)))
77+
(defn rect-p4 [r]
78+
(cond (= (representation r) 1) (rect-version1-p4 r)
79+
(= (representation r) 2) (rect-version2-p4 r)))
80+
81+
(defn rect-perimeter [r]
82+
(let [p1 (rect-p1 r)
83+
p2 (rect-p2 r)
84+
p3 (rect-p3 r)]
85+
(* 2 (+ (distance p1 p2) (distance p2 p3)))))
86+
87+
(defn rect-area [r]
88+
(let [p1 (rect-p1 r)
89+
p2 (rect-p2 r)
90+
p3 (rect-p3 r)]
91+
(* (distance p1 p2) (distance p2 p3))))
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
; sicp-clojure - SICP exercise solutions in Clojure
2+
; Copyright (C) 2022 Ioannis Stefanis
3+
4+
; This file is part of sicp-clojure.
5+
6+
; sicp-clojure is free software: you can redistribute it and/or modify
7+
; it under the terms of the GNU General Public License as published by
8+
; the Free Software Foundation, either version 3 of the License, or
9+
; (at your option) any later version.
10+
11+
; sicp-clojure is distributed in the hope that it will be useful, but
12+
; WITHOUT ANY WARRANTY; without even the implied warranty of
13+
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
; General Public License for more details.
15+
16+
; You should have received a copy of the GNU General Public License
17+
; along with sicp-clojure. If not, see <https://www.gnu.org/licenses/>.
18+
19+
20+
(ns sicp_clojure.ch_2.test_ex_01_rational_numbers
21+
(:require [clojure.test :refer [deftest is run-tests]]
22+
[sicp_clojure.ch_2.ex_01_rational_numbers
23+
:refer [add-rat make-rat-version1 make-rat-version2
24+
make-rat-version3 make-rat-version4 make-rat-version5
25+
print-rat equal-rat?]]))
26+
27+
28+
;////// 2.1 //////
29+
30+
(def rat1 (make-rat-version1 -3 -5))
31+
(def rat2 (make-rat-version1 1 -5))
32+
(def rat3 (make-rat-version2 1 -5)) ;normalizes sign
33+
(def rat4 (add-rat rat1 rat2))
34+
(def rat5 (add-rat rat1 rat3))
35+
(run! print-rat [rat1 rat2 rat3 rat4 rat5])
36+
(newline)
37+
38+
(def rat6 (make-rat-version3 -3 -5)) ;normalizes sign
39+
(def rat7 (make-rat-version4 1 -5)) ;normalizes sign
40+
(def rat8 (make-rat-version5 1 -5)) ;normalizes sign
41+
(def rat9 (add-rat rat6 rat7))
42+
(def rat10 (add-rat rat6 rat8))
43+
(run! print-rat [rat6 rat7 rat8 rat9 rat10])
44+
45+
(deftest test1 (is (equal-rat? rat1 rat6)))
46+
(deftest test2 (is (equal-rat? rat2 rat7)))
47+
(deftest test3 (is (equal-rat? rat3 rat8)))
48+
(deftest test4 (is (equal-rat? rat4 rat9)))
49+
(deftest test5 (is (equal-rat? rat5 rat10)))
50+
51+
(defn test-ns-hook [] ;to be run in order
52+
(test1) (test2) (test3) (test4) (test5))
53+
54+
(run-tests)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
; sicp-clojure - SICP exercise solutions in Clojure
2+
; Copyright (C) 2022 Ioannis Stefanis
3+
4+
; This file is part of sicp-clojure.
5+
6+
; sicp-clojure is free software: you can redistribute it and/or modify
7+
; it under the terms of the GNU General Public License as published by
8+
; the Free Software Foundation, either version 3 of the License, or
9+
; (at your option) any later version.
10+
11+
; sicp-clojure is distributed in the hope that it will be useful, but
12+
; WITHOUT ANY WARRANTY; without even the implied warranty of
13+
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
; General Public License for more details.
15+
16+
; You should have received a copy of the GNU General Public License
17+
; along with sicp-clojure. If not, see <https://www.gnu.org/licenses/>.
18+
19+
20+
(ns sicp_clojure.ch_2.test_ex_02_03_geometric_elements
21+
(:require [clojure.test :refer [deftest is run-tests]]
22+
[sicp_clojure.ch_2.ex_02_03_geometric_elements
23+
:refer [make-point make-segment midpoint-segment x-point y-point
24+
rect-area rect-perimeter rectangle-version1 rectangle-version2]]))
25+
26+
27+
;////// 2.2 & 2.3 //////
28+
29+
(defn print-equal? [x y]
30+
(println x y)
31+
(println (= x y))
32+
(= x y))
33+
34+
(def point1 (make-point 0 0))
35+
(def point2 (make-point 0 4))
36+
(def point3 (make-point 5 4))
37+
(def point4 (make-point 5 0))
38+
39+
(def seg1 (make-segment point1 point2))
40+
(def seg2 (make-segment point2 point3))
41+
(def seg3 (make-segment point3 point4))
42+
(def seg4 (make-segment point4 point1))
43+
(def midpoint1 (midpoint-segment seg1))
44+
45+
(def rect1 (rectangle-version1 point1 point2 point3 point4))
46+
(def rect2 (rectangle-version2 seg1 seg2 seg3 seg4))
47+
48+
(def per1 (rect-perimeter rect1))
49+
(def per2 (rect-perimeter rect2))
50+
(def area1 (rect-area rect1))
51+
(def area2 (rect-area rect2))
52+
53+
;tests (2.2)
54+
(deftest test1 (is (print-equal? (x-point midpoint1) 0)))
55+
(deftest test2 (is (print-equal? (y-point midpoint1) 2)))
56+
57+
;tests (2.3)
58+
(deftest test3 (is (print-equal? per1 per2)))
59+
(deftest test4 (is (print-equal? area1 area2)))
60+
61+
(defn test-ns-hook [] ;to be run in order
62+
(test1) (test2) (test3) (test4))
63+
64+
(run-tests)

0 commit comments

Comments
 (0)