/2-5.rkt

http://github.com/Tabemasu/sicp · Racket · 397 lines · 310 code · 18 blank · 69 comment · 44 complexity · 307c9dee0a3255c687fea2b72d05bc60 MD5 · raw file

  1. #lang racket
  2. (require "2-4.rkt")
  3. (define (add x y) (apply-generic 'add x y))
  4. (define (sub x y) (apply-generic 'sub x y))
  5. (define (mul x y) (apply-generic 'mul x y))
  6. (define (div x y) (apply-generic 'div x y))
  7. (define (install-scheme-number-package)
  8. (define (tag x)
  9. (attach-tag 'scheme-number x))
  10. (put 'add '(scheme-number scheme-number)
  11. (lambda (x y) (tag (+ x y))))
  12. (put 'sub '(scheme-number scheme-number)
  13. (lambda (x y) (tag (- x y))))
  14. (put 'mul '(scheme-number scheme-number)
  15. (lambda (x y) (tag (* x y))))
  16. (put 'div '(scheme-number scheme-number)
  17. (lambda (x y) (tag (/ x y))))
  18. (put 'equal? '(scheme-number scheme-number)
  19. (lambda (x y) (= x y)))
  20. (put '=zero? '(scheme-number)
  21. (lambda (x) (= x 0)))
  22. (put 'make 'scheme-number
  23. (lambda (x) (tag x)))
  24. 'done)
  25. (define (make-scheme-number n)
  26. ((get 'make 'scheme-number) n))
  27. (define (install-rational-package)
  28. ;; internal procedures
  29. (define (numer x) (car x))
  30. (define (denom x) (cdr x))
  31. (define (make-rat n d)
  32. (let ((g (gcd n d)))
  33. (cons (/ n g) (/ d g))))
  34. (define (add-rat x y)
  35. (make-rat (+ (* (numer x) (denom y))
  36. (* (numer y) (denom x)))
  37. (* (denom x) (denom y))))
  38. (define (sub-rat x y)
  39. (make-rat (- (* (numer x) (denom y))
  40. (* (numer y) (denom x)))
  41. (* (denom x) (denom y))))
  42. (define (mul-rat x y)
  43. (make-rat (* (numer x) (numer y))
  44. (* (denom x) (denom y))))
  45. (define (div-rat x y)
  46. (make-rat (* (numer x) (denom y))
  47. (* (denom x) (numer y))))
  48. (define (equal-rat? x y)
  49. (and (= (numer x) (numer y))
  50. (= (denom x) (denom y))))
  51. (define (=zero-rat? x)
  52. (= (numer x) 0))
  53. ;; interface to rest of the system
  54. (define (tag x) (attach-tag 'rational x))
  55. (put 'add '(rational rational)
  56. (lambda (x y) (tag (add-rat x y))))
  57. (put 'sub '(rational rational)
  58. (lambda (x y) (tag (sub-rat x y))))
  59. (put 'mul '(rational rational)
  60. (lambda (x y) (tag (mul-rat x y))))
  61. (put 'div '(rational rational)
  62. (lambda (x y) (tag (div-rat x y))))
  63. (put 'equal? '(rational rational)
  64. (lambda (x y) (equal-rat? x y)))
  65. (put '=zero? '(rational)
  66. (lambda (x) (=zero-rat? x)))
  67. (put 'make 'rational
  68. (lambda (n d) (tag (make-rat n d))))
  69. 'done)
  70. (define (make-rational n d)
  71. ((get 'make 'rational) n d))
  72. (define (install-complex-package)
  73. ;; imported procedures from rectangular and polar packages
  74. (define (make-from-real-imag x y)
  75. ((get 'make-from-real-imag 'rectangular) x y))
  76. (define (make-from-mag-ang r a)
  77. ((get 'make-from-mag-ang 'polar) r a))
  78. ;; internal procedures
  79. (define (add-complex z1 z2)
  80. (make-from-real-imag (+ (real-part z1) (real-part z2))
  81. (+ (imag-part z1) (imag-part z2))))
  82. (define (sub-complex z1 z2)
  83. (make-from-real-imag (- (real-part z1) (real-part z2))
  84. (- (imag-part z1) (imag-part z2))))
  85. (define (mul-complex z1 z2)
  86. (make-from-mag-ang (* (magnitude z1) (magnitude z2))
  87. (+ (angle z1) (angle z2))))
  88. (define (div-complex z1 z2)
  89. (make-from-mag-ang (/ (magnitude z1) (magnitude z2))
  90. (- (angle z1) (angle z2))))
  91. (define (equal-complex? z1 z2)
  92. (or (and (= (real-part z1) (real-part z2))
  93. (= (imag-part z1) (imag-part z2)))
  94. (and (= (magnitude z1) (magnitude z2))
  95. (= (angle z1) (angle z2)))))
  96. (define (=zero-complex? z1)
  97. (= (magnitude z1) 0))
  98. ;; interface to rest of the system
  99. (define (tag z) (attach-tag 'complex z))
  100. (put 'add '(complex complex)
  101. (lambda (z1 z2) (tag (add-complex z1 z2))))
  102. (put 'sub '(complex complex)
  103. (lambda (z1 z2) (tag (sub-complex z1 z2))))
  104. (put 'mul '(complex complex)
  105. (lambda (z1 z2) (tag (mul-complex z1 z2))))
  106. (put 'div '(complex complex)
  107. (lambda (z1 z2) (tag (div-complex z1 z2))))
  108. (put 'equal? '(complex complex)
  109. (lambda (z1 z2) (equal-complex? z1 z2)))
  110. (put '=zero? '(complex)
  111. (lambda (z) (=zero-complex? z)))
  112. (put 'make-from-real-imag 'complex
  113. (lambda (x y) (tag (make-from-real-imag x y))))
  114. (put 'make-from-mag-ang 'complex
  115. (lambda (r a) (tag (make-from-mag-ang r a))))
  116. (put 'real-part '(complex) real-part)
  117. (put 'imag-part '(complex) imag-part)
  118. (put 'magnitude '(complex) magnitude)
  119. (put 'angle '(complex) angle)
  120. 'done)
  121. (define (make-complex-from-real-imag x y)
  122. ((get 'make-from-real-imag 'complex) x y))
  123. (define (make-complex-from-mag-ang r a)
  124. ((get 'make-from-mag-ang 'complex) r a))
  125. ;Exercise 2.78
  126. (define (attach-tag type-tag contents)
  127. (if (pair? contents)
  128. (cons type-tag contents)
  129. contents))
  130. (define (type-tag datum)
  131. (cond [(pair? datum) (car datum)]
  132. [(number? datum) 'scheme-number]
  133. [else (error "Bad tagged datum -- TYPE-TAG" datum)]))
  134. (define (contents datum)
  135. (cond [(pair? datum) (cdr datum)]
  136. [(number? datum) datum]
  137. [else (error "Bad tagged datum -- TYPE-TAG" datum)]))
  138. ;Exercise 2.79
  139. (define (equ? x y) (apply-generic 'equal? x y))
  140. ;Exercise 2.80
  141. (define (=zero? x) (apply-generic '=zero? x))
  142. ;End exercise
  143. (define (put-coercion x) '()) ;stub implementations
  144. (define (get-coercion x) '())
  145. ;(define (scheme-number->complex n)
  146. ; (make-complex-from-real-imag (contents n) 0))
  147. ;(put-coercian 'scheme-number 'complex scheme-number-complex)
  148. ;Exercise 2.82
  149. ;(define (apply-generic op . args)
  150. ; (let ([type-tags (map type-tag args)]
  151. ; [arg-contents (map contents args)])
  152. ; (let ([proc (get op type-tags)])
  153. ; (if proc
  154. ; (apply proc arg-contents)
  155. ; (apply-with-coercion op type-tags arg-contents)))))
  156. ;(define (apply-with-coercion op type-tags arg-contents)
  157. ; (define (try-to-coerce type not-tried tried)
  158. ; (define (loop type other-types new-type-list)
  159. ; (if (null? other-types)
  160. ; (get op (cons type new-type-list))
  161. ; (let* ([next-type (car other-types)]
  162. ; [nt->t (get-coercion next-type type)])
  163. ; (if nt->t
  164. ; (loop type (cdr other-types) (cons (nt->t next-type) new-type-list))
  165. ; #f))))
  166. ; (let ([proc (loop (type (append tried not-tried) '()))])
  167. ; (if proc
  168. ; (apply proc arg-contents)
  169. ; (if (null? not-tried)
  170. ; (error "No method for these types"
  171. ; (list op type-tags))
  172. ; (try-to-coerce (car not-tried) (cdr not-tried) (cons type tried))))))
  173. ; (try-to-coerce (car type-tags) (cdr type-tags) '()))
  174. ;Exercise 2.83
  175. ; in interger package
  176. (define (raise-integer i)
  177. (make-rational i 1))
  178. (put 'raise 'integer raise-integer)
  179. ; in rational package
  180. (define (raise-rational r)
  181. (make-real (/ (numer r) (denom r))))
  182. (put 'raise 'rational raise-rational)
  183. ; in real package
  184. (define (raise-real n)
  185. (make-complex-from-real-imag n 0))
  186. (put 'raise 'real raise-real)
  187. ; generic operation raise
  188. (define (raise x) (apply-generic 'raise x))
  189. ;Exercise 2.84
  190. (define (get-tier type)
  191. (cond [(eq? type 'integer) 0]
  192. [(eq? type 'rational) 100]
  193. [(eq? type 'real) 200]
  194. [(eq? type 'complex) 300]))
  195. (define (compare-tiers t1 t2)
  196. (if (< (get-tier t1) (get-tier t2)) t2 t1))
  197. (define (get-highest-tier types)
  198. (define (loop highest-so-far types)
  199. (if (null? types)
  200. highest-so-far
  201. (loop (compare-tiers (car types) highest-so-far) (cdr types))))
  202. (loop (car types) (cdr types)))
  203. (define (same-tier? t1 t2)
  204. (= (get-tier t1) (get-tier t2)))
  205. ;(define (apply-generic op . args)
  206. ; (let ([type-tags (map type-tag args)]
  207. ; [arg-contents (map contents args)])
  208. ; (let ([proc (get op type-tags)])
  209. ; (if proc
  210. ; (apply proc arg-contents))
  211. ; (apply-with-coercion op type-tags args))))))
  212. (define (apply-with-coercion op type-tags args)
  213. (let* ([top-tier (get-highest-tier type-tags)]
  214. [coerced-list (coerce-list top-tier args)]
  215. [proc (get op (map type-tag coerced-list))])
  216. (if proc
  217. (apply proc (map contents coerced-list))
  218. (error "No method for these types"
  219. (list op type-tags)))))
  220. (define (coerce-list top-tier tc-pairs)
  221. (cons (coerce (car tc-pairs) top-tier)
  222. (coerce-list top-tier (cdr tc-pairs))))
  223. (define (coerce tc-pair t)
  224. (if (same-tier? t (type-tag tc-pair))
  225. tc-pair
  226. (coerce (raise (contents tc-pair)) t)))
  227. ;Exercise 2.85
  228. ;in rational package
  229. (define (project-rational r)
  230. (make-integer (numer r)))
  231. (put 'project 'rational project-rational)
  232. ;in real package
  233. (define (project-real n)
  234. (make integer (round n)))
  235. (put 'project 'real project-real)
  236. ;in complex package
  237. (define (project-complex z)
  238. (make-real (real-part z)))
  239. (put 'project 'complex project-complex)
  240. ;generic project operation
  241. (define (project x) (apply-generic 'project x))
  242. (define (drop x)
  243. (let ([simplified-value (project x)])
  244. (if (or (lowest-tier? (type-tag x)) (not (equ? (raise simplified-value) x)))
  245. x
  246. (drop simplified-value))))
  247. (define (lowest-tier? x)
  248. (same-tier? x 'integer))
  249. (define (apply-generic op . args)
  250. (let ([type-tags (map type-tag args)]
  251. [arg-contents (map contents args)])
  252. (let ([proc (get op type-tags)])
  253. (if proc
  254. (drop (apply proc arg-contents))
  255. (drop (apply-with-coercion op type-tags args))))))
  256. ;End exercise
  257. (define (install-polynomial-package)
  258. ;; internal procedures
  259. (define (add-terms L1 L2)
  260. (cond [(empty-termlist? L1) L2]
  261. [(empty-termlist? L2) L1]
  262. [else
  263. (let ([t1 (first-term L1)] [t2 (first-term L2)])
  264. (cond [(> (order t1) (order t2))
  265. (adjoin-term
  266. t1 (add-terms (rest-terms L1) L2))]
  267. [(< (order t1) (order t2))
  268. (adjoin-term
  269. t2 (add-terms L1 (rest-terms L2)))]
  270. [else
  271. (adjoin-term
  272. (make-term (order t1)
  273. (add (coeff t1) (coeff t2)))
  274. (add-terms (rest-terms L1)
  275. (rest-terms L2)))]))]))
  276. (define (mul-terms L1 L2)
  277. (if (empty-termlist? L1)
  278. (the-empty-termlist)
  279. (add-terms (mul-term-by-all-terms (first-term L1) L2)
  280. (mul-terms (rest-terms L1) L2))))
  281. (define (mul-term-by-all-terms t1 L)
  282. (if (empty-termlist? L)
  283. (the-empty-termlist)
  284. (let ([t2 (first-term L)])
  285. (adjoin-term
  286. (make-term (+ (order t1) (order t2))
  287. (mul (coeff t1) (coeff t2)))
  288. (mul-term-by-all-terms t1 (rest-terms L))))))
  289. ;; representation of poly
  290. (define (make-poly variable term-list)
  291. (cons variable term-list))
  292. (define (variable p) (car p))
  293. (define (term-list p) (cdr p))
  294. (define (same-variable? x y) (eq? x y))
  295. (define (variable? x) (symbol? x))
  296. (define (adjoin-term term term-list)
  297. (if (=zero? (coeff term))
  298. term-list
  299. (cons term term-list)))
  300. (define (the-empty-termlist) '())
  301. (define (first-term term-list) (car term-list))
  302. (define (rest-terms term-list) (cdr term-list))
  303. (define (empty-termlist? term-list) (null? term-list))
  304. (define (make-term order coeff) (list order coeff))
  305. (define (order term) (car term))
  306. (define (coeff term) (cadr term))
  307. (define (add-poly p1 p2)
  308. (if (same-variable? (variable p1) (variable p2))
  309. (make-poly (variable p1)
  310. (add-terms (term-list p1)
  311. (term-list p2)))
  312. (error "Polys not in same var -- ADD-POLY" (list p1 p2))))
  313. (define (mul-poly p1 p2)
  314. (if (same-variable? (variable p1) (variable p2))
  315. (make-poly (variable p1)
  316. (mul-terms (term-list p1)
  317. (term-list p2)))
  318. (error "Polys not in same var -- MUL-POLU" (list p1 p2))))
  319. ;; interface to rest of the system
  320. (define (tag p) (attach-tag 'polynomial p))
  321. (put 'add '(polynomial polynomial)
  322. (lambda (p1 p2) (tag (add-poly p1 p2))))
  323. (put 'mul '(polynomial polynomial)
  324. (lambda (p1 p2) (tag (mul-poly p1 p2))))
  325. (put 'make 'polynomial
  326. (lambda (var terms) (tag (make-poly var terms))))
  327. 'done)
  328. ;Exercise 2.87
  329. ;in polynomial package
  330. (define (=zero?-poly p)
  331. (if (empty-termlist? (term-list p))
  332. #t
  333. (and (=zero? (coeff (first-term p)))
  334. (=zero?-poly (rest-terms p)))))
  335. (put '=zero? 'polynomial =zero?-poly)
  336. ;Exercise 2.88
  337. ;given a generic negation operation
  338. ;in polynomial package
  339. (define (sub-poly p1 p2)
  340. (add-poly p1 (negate p2)))
  341. (put 'sub '(polynomial polynomial)
  342. (lambda (x y) (tag (sub-poly x y))))
  343. ;Exercise 2.89
  344. ;in polynomial package
  345. (define (adjoin-term term-list)
  346. (if (=zero? (coeff term))
  347. term-list
  348. (cons (coeff term) term-list)))
  349. (define (first-term term-list)
  350. (make-term (- (length term-list) 1) (car term-list)))
  351. ;Exercise 2.91
  352. ;in polynomial package
  353. (define (div-poly p1 p2)
  354. (if (same-variable? (variable p1) (variable p2))
  355. (let ([div-result (div-terms (term-list p1) (term-list p2))]
  356. [var (variable p1)])
  357. (list (make-poly var (car div-result))
  358. (make-poly var (cadr div-result))))
  359. (error "Poly not in the same variable -- DIV-POLY" (list p1 p2))))
  360. (define (div-terms L1 L2)
  361. (if (empty-termlist? L1)
  362. (list (the-empty-termlist) (the-empty-termlist))
  363. (let ([t1 (first-term L1)]
  364. [t2 (first-term L2)])
  365. (if (> (order t2) (order t1))
  366. (list (the-empty-termlist) L1)
  367. (let* ([new-c (div (coeff t1) (coeff t2))]
  368. [new-o (- (order t1) (order t2))]
  369. [new-t (make-term new-c new-o)]
  370. [mult (mul-terms L2 (adjoin-term new-term (the-empty-termlist)))]
  371. [diff (add-terms L1 (negate-terms mult))])
  372. (let ([rest-of-result (div-terms diff L2)])
  373. (cons (adjoin-term new-term (car rest-of-result))
  374. (cadr rest-of-result))))))))
  375. (put 'div '(polynomial polynomial)
  376. (lambda (p1 p2)
  377. (let ([div-result (div-poly p1 p2)])
  378. (list (tag (car div-result))
  379. (tag (cadr div-reuslt))))))