diff options
author | Jacques Comeaux <jacquesrcomeaux@protonmail.com> | 2023-07-11 12:31:39 -0500 |
---|---|---|
committer | Jacques Comeaux <jacquesrcomeaux@protonmail.com> | 2023-07-11 12:31:39 -0500 |
commit | 6437f2e13d07a290304ab2a2fa7fe898ce89d373 (patch) | |
tree | 765b9749e00ecdffee993a93f0bf1f274bb2a0d2 | |
parent | 1f7aa972194ca35ed12bf41fc7d59576f3796ad0 (diff) |
Begin chapter 2 part 4
-rw-r--r-- | chap2/part4.rkt | 592 |
1 files changed, 592 insertions, 0 deletions
diff --git a/chap2/part4.rkt b/chap2/part4.rkt new file mode 100644 index 0000000..63b64d7 --- /dev/null +++ b/chap2/part4.rkt @@ -0,0 +1,592 @@ +#lang sicp +(#%require (only racket/base print-as-expression print-mpair-curly-braces)) +(print-as-expression #f) +(print-mpair-curly-braces #f) + +;; Chapter 2 +;; Building Abstractions with Data + +;; 2.4 +;; Multiple Representations for Abstract Data + +(define (square x) (* x x)) + +;; Tagged data + +(define (attach-tag- type-tag contents) + (cons type-tag contents)) + +(define (type-tag- datum) + (if (pair? datum) + (car datum) + (error "Bad tagged datum -- TYPE-TAG" datum))) + +(define (contents- datum) + (if (pair? datum) + (cdr datum) + (error "Bad tagged datum -- CONTENTS" datum))) + +;; Complex number representations + +(define (rectangular? z) + (eq? (type-tag z) 'rectangular)) + +(define (polar? z) + (eq? (type-tag z) 'polar)) + +;; Ben's representation + +(define (real-part-rectangular z) (car z)) + +(define (imag-part-rectangular z) (cdr z)) + +(define (magnitude-rectangular z) + (sqrt + (+ + (square (real-part-rectangular z)) + (square (imag-part-rectangular z))))) + +(define (angle-rectangular z) + (atan + (imag-part-rectangular z) + (real-part-rectangular z))) + +(define (make-from-real-imag-rectangular x y) + (attach-tag 'rectangular (cons x y))) + +(define (make-from-mag-ang-rectangular r a) + (attach-tag + 'rectangular + (cons (* r (cos a)) (* r (sin a))))) + +;; Alyssa's representation + +(define (real-part-polar z) + (* (magnitude-polar z) (cos (angle-polar z)))) + +(define (imag-part-polar z) + (* (magnitude-polar z) (sin (angle-polar z)))) + +(define (magnitude-polar z) (car z)) + +(define (angle-polar z) (cdr z)) + +(define (make-from-real-imag-polar x y) + (attach-tag + 'polar + (cons + (sqrt (+ (square x) (square y))) + (atan y x)))) + +(define (make-from-mag-ang-polar r a) + (attach-tag 'polar (cons r a))) + +;; Generic selectors + +(#%provide real-part-) +(define (real-part- z) + (cond + ((rectangular? z) + (real-part-rectangular (contents z))) + ((polar? z) + (real-part-polar (contents z))) + (else (error "Unknown type -- REAL-PART" z)))) + +(#%provide imag-part-) +(define (imag-part- z) + (cond + ((rectangular? z) + (imag-part-rectangular (contents z))) + ((polar? z) + (imag-part-polar (contents z))) + (else (error "Unknown type -- IMAG-PART" z)))) + +(#%provide magnitude-) +(define (magnitude- z) + (cond + ((rectangular? z) + (magnitude-rectangular (contents z))) + ((polar? z) + (magnitude-polar (contents z))) + (else (error "Unknown type -- MAGNITUDE" z)))) + +(#%provide angle-) +(define (angle- z) + (cond + ((rectangular? z) + (angle-rectangular (contents z))) + ((polar? z) + (angle-polar (contents z))) + (else (error "Unknown type -- ANGLE" z)))) + +;; Constructors + +(#%provide make-from-real-imag-) +(define (make-from-real-imag- x y) + (make-from-real-imag-rectangular x y)) + +(#%provide make-from-mag-ang-) +(define (make-from-mag-ang- r a) + (make-from-mag-ang-polar r a)) + +;; Complex number arithmetic operations + +(#%provide add-complex-) +(define (add-complex- z1 z2) + (make-from-real-imag- + (+ (real-part- z1) (real-part- z2)) + (+ (imag-part- z1) (imag-part- z2)))) + +(#%provide sub-complex) +(define (sub-complex z1 z2) + (make-from-real-imag- + (- (real-part- z1) (real-part- z2)) + (- (imag-part- z1) (imag-part- z2)))) + +(#%provide mul-complex-) +(define (mul-complex- z1 z2) + (make-from-mag-ang- + (* (magnitude- z1) (magnitude- z2)) + (+ (angle- z1) (angle- z2)))) + +(#%provide div-complex-) +(define (div-complex- z1 z2) + (make-from-mag-ang- + (/ (magnitude- z1) (magnitude- z2)) + (- (angle- z1) (angle- z2)))) + +(define (get) (error "get not implemented")) +(define (put) (error "put not implemented")) + +;; Ben's rectangular package +(define (install-rectangular-package) + ;; internal procedures + (define (real-part z) (car z)) + (define (imag-part z) (cdr z)) + (define (make-from-real-imag x y) (cons x y)) + (define (magnitude z) + (sqrt + (+ + (square (real-part z)) + (square (imag-part z))))) + (define (angle z) + (atan (imag-part z) (real-part z))) + (define (make-from-mag-ang r a) + (cons (* r (cos a)) (* r (sin a)))) + ;; interface to rest of system + (define (tag x) (attach-tag 'rectangular x)) + (put 'real-part '(rectangular) real-part) + (put 'imag-part '(rectangular) imag-part) + (put 'magnitude '(rectangular) magnitude) + (put 'angle '(rectangular) angle) + (put 'make-from-real-imag 'rectangular + (lambda (x y) (tag (make-from-real-imag x y)))) + (put 'make-from-mag-ang 'rectangular + (lambda (r a) (tag (make-from-mag-ang r a)))) + 'done) + +;; Alyssa's polar package +(define (install-polar-package) + ;; internal procedures + (define (magnitude z) (car z)) + (define (angle z) (cdr z)) + (define (make-from-mag-ang r a) (cons r a)) + (define (real-part z) + (* (magnitude z) (cos (angle z)))) + (define (imag-part z) + (* (magnitude z) (sin (angle z)))) + (define (make-from-real-imag x y) + (cons + (sqrt (+ (square x) (square y))) + (atan y x))) + ;; interface to rest of system + (define (tag x) (attach-tag 'polar x)) + (put 'real-part '(polar) real-part) + (put 'imag-part '(polar) imag-part) + (put 'magnitude '(polar) magnitude) + (put 'angle '(poar) angle) + (put 'make-from-real-imag 'polar + (lambda (x y) (tag (make-from-real-imag x y)))) + (put 'make-from-mag-ang 'polar + (lambda (r a) (tag (make-from-mag-ang r a)))) + 'done) + +(define (apply-generic op . args) + (let ((type-tags (map type-tag args))) + (let ((proc (get op type-tags))) + (if proc + (apply proc (map contents args)) + (error + "No method for these types -- APPLY-GENERIC" + (list op type-tags)))))) + +(define (real-part z) (apply-generic 'real-part z)) +(define (imag-part z) (apply-generic 'imag-part z)) +(define (magnitude z) (apply-generic 'magnitude z)) +(define (angle z) (apply-generic 'angle z)) + +(define (make-from-real-imag x y) + ((get 'make-from-real-imag 'rectangular) x y)) + +(define (make-from-mag-ang r a) + ((get 'make-from-mag-ang 'polar) r a)) + +#| 2.73 |# + +(define (deriv exp var) + (cond + ((number? exp) 0) + ((variable? exp) (if (same-variable? exp var) 1 0)) + (else ((get 'deriv (operator exp)) (operands exp) var)))) + +(define (operator exp) (car exp)) + +(define (operands exp) (cdr exp)) + +(define (variable? x) (symbol? x)) + +(define (same-variable? v1 v2) + (and (variable? v1) (variable? v2) (eq? v1 v2))) + +(define (=number? exp num) + (and (number? exp) (= exp num))) + +(define (make-sum a1 a2) + (cond + ((=number? a1 0) a2) + ((=number? a2 0) a1) + ((and (number? a1) (number? a2)) + (+ a1 a2)) + (else (list '+ a1 a2)))) + +(define (make-product m1 m2) + (cond + ((or (=number? m1 0) (=number? m2 0)) + 0) + ((=number? m1 1) m2) + ((=number? m2 1) m1) + ((and (number? m1) (number? m2)) + (* m1 m2)) + (else (list '* m1 m2)))) + +(define (make-exponentiation u n) + (cond + ((not (number? n)) (error "exponent must be a number")) + ((=number? n 0) 1) + ((=number? n 1) u) + (else (list '** u n)))) + +(define (install-sum-package) + ;; internal procedures + (define (deriv-sum operands var) + (make-sum + (deriv (car operands) var) + (deriv (cadr operands) var))) + ;; interface to rest of system + (put 'deriv '(+) deriv-sum) + 'done) + +(define (install-product-package) + ;; internal procedures + (define (deriv-product operands var) + (make-sum + (make-product + (car operands) + (deriv (cadr operands) var)) + (make-product + (deriv (car operands) var) + (cadr operands)))) + ;; interface to rest of system + (put 'deriv '(*) deriv-product) + 'done) + +(define (install-exponentiation-package) + ;; internal procedures + (define (deriv-expo operands var) + (make-product + (make-product + (cadr exp) + (make-exponentiation + (car exp) + (- (cadr exp) 1))) + (deriv (car exp) var))) + ;; interface to rest of system + (put 'deriv '(^^) deriv-expo) + 'done) + +(#%provide make-from-real-imag--) +(define (make-from-real-imag-- x y) + (define (dispatch op) + (cond + ((eq? op 'real-part) x) + ((eq? op 'imag-part) y) + ((eq? op 'magnitude)) + ((eq? op 'magnitude) + (sqrt (+ (square x) (square y)))) + ((eq? op 'angle) (atan y x)) + (else (error "Unknown op -- MAKE-FROM-REAL-IMAG" op)))) + dispatch) + +(#%provide apply-generic-) +(define (apply-generic- op arg) (arg op)) + +#| 2.75 |# + +(#%provide make-from-mag-ang--) +(define (make-from-mag-ang-- r a) + (define (dispatch op) + (cond + ((eq? op 'real-part) (* r (cos a))) + ((eq? op 'imag-part) (* r (sin a))) + ((eq? op 'magnitude) r) + ((eq? op 'angle) a) + (else (error "Unknown op -- MAKE-FROM-MAG-ANG" op)))) + dispatch) + +#| 2.76 |# + +;; Message passing is ideal if new types must often be added. +;; Generic operations with explict dispatch is best if new +;; operations must often be added. + +(define (add x y) (apply-generic 'add x y)) +(define (sub x y) (apply-generic 'sub x y)) +(define (mul x y) (apply-generic 'mul x y)) +(define (div x y) (apply-generic 'div x y)) + +(define (install-scheme-number-package) + ;; interface + (define (tag x) + (attach-tag 'scheme-number x)) + (put 'add '(scheme-number scheme-number) + (lambda (x y) (tag (+ x y)))) + (put 'sub '(scheme-number scheme-number) + (lambda (x y) (tag (- x y)))) + (put 'mul '(scheme-number scheme-number) + (lambda (x y) (tag (* x y)))) + (put 'div '(scheme-number scheme-number) + (lambda (x y) (tag (/ x y)))) + (put 'equ? '(scheme-number scheme-number) + (lambda (x y) (tag (= x y)))) + (put '=zero? '(scheme-number) + (lambda (x) (tag (= x 0)))) + (put 'make 'scheme-number (lambda (x) (tag x))) + 'done) + +(define (make-scheme-number n) + ((get 'make 'scheme-number) n)) + +(define (install-rational-package) + ;; internal procedures + (define (numer x) (car x)) + (define (denom x) (cdr x)) + (define (make-rat n d) + (let ((g (gcd n d))) + (cons (/ n g) (/ d g)))) + (define (add-rat x y) + (make-rat + (+ + (* (numer x) (denom y)) + (* (numer y) (denom x))) + (* (denom x) (denom y)))) + (define (sub-rat x y) + (make-rat + (- + (* (numer x) (denom y)) + (* (numer y) (denom x))) + (* (denom x) (denom y)))) + (define (mul-rat x y) + (make-rat + (* (numer x) (numer y)) + (* (denom x) (denom y)))) + (define (div-rat x y) + (make-rat + (* (numer x) (denom y)) + (* (denom x) (numer y)))) + (define (equ?-rat x y) + (= + (* (numer x) (denom y)) + (* (denom x) (numer y)))) + (define (=zero?-rat x) + (= (numer x) 0)) + ;; interface + (define (tag x) (attach-tag 'rational x)) + (put 'add '(rational rational) + (lambda (x y) (tag (add-rat x y)))) + (put 'sub '(rational rational) + (lambda (x y) (tag (sub-rat x y)))) + (put 'mul '(rational rational) + (lambda (x y) (tag (mul-rat x y)))) + (put 'div '(rational rational) + (lambda (x y) (tag (div-rat x y)))) + (put 'equ? '(rational rational) + (lambda (x y) (tag (equ?-rat x y)))) + (put '=zero? '(rational) + (lambda (x) (tag (=zero?-rat x)))) + (put 'make 'rational + (lambda (n d) (tag (make-rat n d)))) + 'done) + +(define (make-rational n d) + ((get 'make 'rational) n d)) + +(define (install-complex-package) + ;; imported procedures + (define (make-from-real-imag x y) + ((get 'make-from-real-imag 'rectangular) x y)) + (define (make-from-mag-ang r a) + ((get 'make-from-mag-ang 'polar) r a)) + ;; internal procedures + (define (add-complex z1 z2) + (make-from-real-imag + (+ (real-part z1) (real-part z2)) + (+ (imag-part z1) (imag-part z2)))) + (define (sub-complex z1 z2) + (make-from-real-imag + (- (real-part z1) (real-part z2)) + (- (imag-part z1) (imag-part z2)))) + (define (mul-complex z1 z2) + (make-from-mag-ang + (* (magnitude z1) (magnitude z2)) + (+ (angle z1) (angle z2)))) + (define (div-complex z1 z2) + (make-from-mag-ang + (/ (magnitude z1) (magnitude z2)) + ( (angle z1) (angle z2)))) + (define (equ?-complex z1 z2) + (and + (= (real-part z1) (real-part z2)) + (= (imag-part z1) (imag-part z2)))) + (define (=zero?-complex z) + (and + (= (real-part z) 0) + (= (imag-part z) 0))) + ;; interface + (define (tag z) (attach-tag 'complex z)) + (put 'add '(complex complex) + (lambda (z1 z2) (tag (add-complex z1 z2)))) + (put 'sub '(complex complex) + (lambda (z1 z2) (tag (sub-complex z1 z2)))) + (put 'mul '(complex complex) + (lambda (z1 z2) (tag (mul-complex z1 z2)))) + (put 'div '(complex complex) + (lambda (z1 z2) (tag (div-complex z1 z2)))) + (put 'equ? '(complex complex) + (lambda (z1 z2) (tag (equ?-complex z1 z2)))) + (put '=zero? '(complex) + (lambda (z) (tag (=zero?-complex z)))) + (put 'make-from-real-imag 'complex + (lambda (x y) (tag (make-from-real-imag x y)))) + (put 'make-from-mag-ang 'complex + (lambda (r a) (tag (make-from-mag-ang r a)))) + (put 'real-part '(complex) real-part) + (put 'imag-part '(complex) imag-part) + (put 'magnitude '(complex) magnitude) + (put 'angle '(complex) angle) + 'done) + +(define (make-complex-from-real-imag x y) + ((get 'make-from-real-imag 'complex) x y)) + +(define (make-complex-from-mag-ang r a) + ((get 'make-from-mag-ang 'complex) r a)) + +#| 2.77 |# + +;; (define z (make-complex-from-real-imag 3 4)) + +;; (magnitude z) + +;; (magnitude '(complex rectangular (3 . 4))) + +;; (apply-generic 'magnitude '(complex rectangular (3 . 4))) + +;; ((get 'magnitude 'complex) '(rectangular (3 . 4))) + +;; (magnitude '(rectangular (3 . 4))) + +;; (apply-generic 'magnitude '(rectangular (3 . 4))) + +;; ((get 'magnitude 'rectangular) '(3 . 4)) + +;; ((lambda (z) (sqrt (+ (square (real-part z)) (square (imag-part z))))) '(3 . 4)) + +;; (sqrt (+ (square 3) (square 4))) + +;; 5 + +#| 2.78 |# + +(define (attach-tag type-tag contents) + (if (eq? type-tag 'scheme-number) + contents + (cons type-tag contents))) + +(define (type-tag datum) + (cond + ((pair? datum) (car datum)) + ((number? datum) 'scheme-number) + (error "Bad tagged datum -- TYPE-TAG" datum))) + +(define (contents datum) + (cond + ((pair? datum) (cdr datum)) + ((number? datum) datum) + (error "Bad tagged datum -- CONTENTS" datum))) + +#| 2.79 |# + +(define (equ? x y) (apply-generic 'equ? x y)) + +;; Add to scheme-number package: + + #| (put 'equ? '(scheme-number scheme-number) |# + #| (lambda (x y) (tag (= x y)))) |# + +;; Add to rational package: + + #| (define (equ?-rat x y) |# + #| (= |# + #| (* (numer x) (denom y)) |# + #| (* (denom x) (numer y)))) |# + + + #| (put 'equ? '(rational rational) |# + #| (lambda (x y) (tag (equ?-rat x y)))) |# + +;; Add to complex package: + + #| (define (equ?-complex z1 z2) |# + #| (and |# + #| (= (real-part z1) (real-part z2)) |# + #| (= (imag-part z1) (imag-part z2)))) |# + + #| (put 'equ? '(complex complex) |# + #| (lambda (z1 z2) (tag (equ?-complex z1 z2)))) |# + +#| 2.80 |# + +(define (=zero? x) (apply-generic '=zero? x)) + +;; Add to scheme-number package: + + #| (put '=zero? '(scheme-number) |# + #| (lambda (x) (tag (= x 0)))) |# + +;; Add to rational package: + + #| (define (=zero?-rat x) |# + #| (= (numer x) 0)) |# + + #| (put '=zero? '(rational) |# + #| (lambda (x) (tag (=zero?-rat x)))) |# + +;; Add to complex package: + + #| (define (=zero?-complex z) |# + #| (and |# + #| (= (real-part z) 0) |# + #| (= (imag-part z) 0))) |# + + #| (put '=zero? '(complex) |# + #| (lambda (z) (tag (=zero?-complex z)))) |# |