Blame


1 665c255d 2023-08-04 jrmu (define (test-case actual expected)
2 665c255d 2023-08-04 jrmu (newline)
3 665c255d 2023-08-04 jrmu (display "Actual: ")
4 665c255d 2023-08-04 jrmu (display actual)
5 665c255d 2023-08-04 jrmu (newline)
6 665c255d 2023-08-04 jrmu (display "Expected: ")
7 665c255d 2023-08-04 jrmu (display expected)
8 665c255d 2023-08-04 jrmu (newline))
9 665c255d 2023-08-04 jrmu
10 665c255d 2023-08-04 jrmu (define (variable? x) (symbol? x))
11 665c255d 2023-08-04 jrmu (define (same-variable? v1 v2)
12 665c255d 2023-08-04 jrmu (and (variable? v1) (variable? v2) (eq? v1 v2)))
13 665c255d 2023-08-04 jrmu
14 665c255d 2023-08-04 jrmu (define (deriv exp var)
15 665c255d 2023-08-04 jrmu (cond ((number? exp) 0)
16 665c255d 2023-08-04 jrmu ((variable? exp) (if (same-variable? exp var) 1 0))
17 665c255d 2023-08-04 jrmu ((sum? exp) (make-sum (deriv (addend exp) var)
18 665c255d 2023-08-04 jrmu (deriv (augend exp) var)))
19 665c255d 2023-08-04 jrmu ((product? exp) (make-sum
20 665c255d 2023-08-04 jrmu (make-product (multiplier exp)
21 665c255d 2023-08-04 jrmu (deriv (multiplicand exp) var))
22 665c255d 2023-08-04 jrmu (make-product (deriv (multiplier exp) var)
23 665c255d 2023-08-04 jrmu (multiplicand exp))))
24 665c255d 2023-08-04 jrmu (error "unknown expression type -- DERIV" exp)))
25 665c255d 2023-08-04 jrmu
26 665c255d 2023-08-04 jrmu ;; b. The problem becomes substantially harder if we allow standard algebraic notation, such as (x + 3 * (x + y + 2)), which drops unnecessary parentheses and assumes that multiplication is done before addition. Can you design appropriate predicates, selectors, and constructors for this notation such that our derivative program still works?
27 665c255d 2023-08-04 jrmu
28 665c255d 2023-08-04 jrmu (define (add-signs exps sign)
29 665c255d 2023-08-04 jrmu (cond ((null? exps) '())
30 665c255d 2023-08-04 jrmu ((null? (cdr exps)) exps)
31 665c255d 2023-08-04 jrmu (else (cons (car exps)
32 665c255d 2023-08-04 jrmu (cons sign
33 665c255d 2023-08-04 jrmu (add-signs (cdr exps) sign))))))
34 665c255d 2023-08-04 jrmu (define (make-sum . exps)
35 665c255d 2023-08-04 jrmu (let* ((nums (filter number? exps))
36 665c255d 2023-08-04 jrmu (non-nums (filter (lambda (exp) (not (number? exp))) exps))
37 665c255d 2023-08-04 jrmu (sum-of-nums (fold-right + 0 nums)))
38 665c255d 2023-08-04 jrmu (cond ((null? non-nums) sum-of-nums)
39 665c255d 2023-08-04 jrmu ((and (= sum-of-nums 0)
40 665c255d 2023-08-04 jrmu (null? (cdr non-nums))) (car non-nums))
41 665c255d 2023-08-04 jrmu ((= sum-of-nums 0) (add-signs non-nums '+))
42 665c255d 2023-08-04 jrmu (else (add-signs (append non-nums (list sum-of-nums)) '+)))))
43 665c255d 2023-08-04 jrmu (define (make-product . exps)
44 665c255d 2023-08-04 jrmu (let* ((nums (filter number? exps))
45 665c255d 2023-08-04 jrmu (non-nums (filter (lambda (exp) (not (number? exp))) exps))
46 665c255d 2023-08-04 jrmu (product-of-nums (fold-right * 1 nums)))
47 665c255d 2023-08-04 jrmu (cond ((null? non-nums) product-of-nums)
48 665c255d 2023-08-04 jrmu ((= product-of-nums 0) 0)
49 665c255d 2023-08-04 jrmu ((and (= product-of-nums 1)
50 665c255d 2023-08-04 jrmu (null? (cdr non-nums))) (car non-nums))
51 665c255d 2023-08-04 jrmu ((= product-of-nums 1) (add-signs non-nums '*))
52 665c255d 2023-08-04 jrmu (else (add-signs (cons product-of-nums non-nums) '*)))))
53 665c255d 2023-08-04 jrmu (define (addend s)
54 665c255d 2023-08-04 jrmu (if (eq? '+ (cadr s))
55 665c255d 2023-08-04 jrmu (car s)
56 665c255d 2023-08-04 jrmu (cons (car s)
57 665c255d 2023-08-04 jrmu (addend (cddr s)))))
58 665c255d 2023-08-04 jrmu (define (augend s)
59 665c255d 2023-08-04 jrmu (cond ((and (eq? '+ (cadr s))
60 665c255d 2023-08-04 jrmu (null? (cdddr s)))
61 665c255d 2023-08-04 jrmu (caddr s))
62 665c255d 2023-08-04 jrmu ((eq? '+ (cadr s)) (cddr s))
63 665c255d 2023-08-04 jrmu ((eq? '* (cadr s)) (augend (cddr s)))))
64 665c255d 2023-08-04 jrmu (define (multiplier p) (car p))
65 665c255d 2023-08-04 jrmu (define (multiplicand p) (caddr p))
66 665c255d 2023-08-04 jrmu
67 665c255d 2023-08-04 jrmu (define (sum? x)
68 665c255d 2023-08-04 jrmu (and (pair? x) (eq? (cadr x) '+)))
69 665c255d 2023-08-04 jrmu (define (product? x)
70 665c255d 2023-08-04 jrmu (and (pair? x) (eq? (cadr x) '*)))
71 665c255d 2023-08-04 jrmu
72 665c255d 2023-08-04 jrmu
73 665c255d 2023-08-04 jrmu (test-case (make-sum 0 'x) 'x)
74 665c255d 2023-08-04 jrmu (test-case (make-sum 1 2) 3)
75 665c255d 2023-08-04 jrmu (test-case (make-sum 1 'x) '(x + 1))
76 665c255d 2023-08-04 jrmu (test-case (make-sum 'x 'y) '(x + y))
77 665c255d 2023-08-04 jrmu (test-case (make-sum (make-sum -3 'y)
78 665c255d 2023-08-04 jrmu (make-sum 3 'x)) '(y + -3 + x + 3)) ;; not the most simplified
79 665c255d 2023-08-04 jrmu (test-case (make-sum -3 'y 3 'x) '(y + x))
80 665c255d 2023-08-04 jrmu (test-case (make-sum (make-product 2 'x 'y) 4) '(2 * x * y + 4))
81 665c255d 2023-08-04 jrmu (test-case (make-sum 4 (make-product 2 'x 'y)) '(4 + 2 * x * y))
82 665c255d 2023-08-04 jrmu (test-case (make-sum (make-product 3 'z) (make-product 2 'x 'y)) '(3 * z + 2 * x * y))
83 665c255d 2023-08-04 jrmu (test-case (make-sum (make-product 'a 'b)
84 665c255d 2023-08-04 jrmu (make-product 'c (make-sum 'd 1) 'e)
85 665c255d 2023-08-04 jrmu (make-product (make-sum 'f 2) (make-sum 'g 3) 'h))
86 665c255d 2023-08-04 jrmu '(a * b + c * (d + 1) * e + (f + 2) * (g + 3) * h))
87 665c255d 2023-08-04 jrmu (test-case (make-product 5 'x) '(5 * x))
88 665c255d 2023-08-04 jrmu (test-case (make-product 5 2) 10)
89 665c255d 2023-08-04 jrmu (test-case (make-product 0 'x) 0)
90 665c255d 2023-08-04 jrmu (test-case (make-product 5 2 'x) '(10 * x))
91 665c255d 2023-08-04 jrmu (test-case (make-product 5 1/5 'x) 'x)
92 665c255d 2023-08-04 jrmu (test-case (make-product 5 1/5 'x 'y) '(x * y))
93 665c255d 2023-08-04 jrmu (test-case (make-sum (make-sum -5 6 'x) 'y (make-sum -3 3))
94 665c255d 2023-08-04 jrmu '(x + 1 + y)) ;; notice that the constant 1 is not right-most
95 665c255d 2023-08-04 jrmu (test-case (make-product (make-sum 2 4 (make-product 3 -2)) (make-product 4 'y)) 0)
96 665c255d 2023-08-04 jrmu (test-case (make-sum (make-product 5 'x)
97 665c255d 2023-08-04 jrmu (make-product 3 'y)
98 665c255d 2023-08-04 jrmu (make-product 2 'y)
99 665c255d 2023-08-04 jrmu (make-product 2 3))
100 665c255d 2023-08-04 jrmu '(5 * x + 3 * y + 2 * y + 6))
101 665c255d 2023-08-04 jrmu (test-case (make-sum (make-product 5 'x)
102 665c255d 2023-08-04 jrmu (make-product 0 'y)
103 665c255d 2023-08-04 jrmu (make-product (make-sum 5 -5) 'x)
104 665c255d 2023-08-04 jrmu (make-product 4 'z)
105 665c255d 2023-08-04 jrmu (make-sum -3 -3)
106 665c255d 2023-08-04 jrmu (make-product 2 3))
107 665c255d 2023-08-04 jrmu '(5 * x + 4 * z))
108 665c255d 2023-08-04 jrmu
109 665c255d 2023-08-04 jrmu (test-case (addend (make-sum 'a 'b 'c 'd 1 2 3 -6 -7 5)) 'a)
110 665c255d 2023-08-04 jrmu (test-case (addend (make-sum (make-product '3 'x) (make-product 4 'y))) '(3 * x))
111 665c255d 2023-08-04 jrmu (test-case (addend (make-sum 4 (make-product 1 'y 'x (make-sum 1 'z)) (make-product 2 2))) '(y * x * (z + 1)))
112 665c255d 2023-08-04 jrmu (test-case (addend '(2 * x * y + 4)) '(2 * x * y))
113 665c255d 2023-08-04 jrmu (test-case (augend (make-sum 1 'x)) 1)
114 665c255d 2023-08-04 jrmu (test-case (augend (make-sum 1 5 'x)) 6)
115 665c255d 2023-08-04 jrmu (test-case (augend (make-sum 1 5 'x 'y)) '(y + 6))
116 665c255d 2023-08-04 jrmu (test-case (augend (make-sum -3 3 'x 'y)) 'y)
117 665c255d 2023-08-04 jrmu (test-case (augend (make-sum 'a 'b 'c 'd 1 2 3 -6 -7 5)) '(b + c + d + -2))
118 665c255d 2023-08-04 jrmu (test-case (augend (make-sum 'a 'b 'c 'd 1 2 3 -6 -7 4 3)) '(b + c + d))
119 665c255d 2023-08-04 jrmu (test-case (augend (make-sum (make-product 5 'x)
120 665c255d 2023-08-04 jrmu (make-product 3 'y)
121 665c255d 2023-08-04 jrmu 2 5 -4))
122 665c255d 2023-08-04 jrmu '(3 * y + 3))
123 665c255d 2023-08-04 jrmu (test-case (augend (make-sum (make-product 5 'x)
124 665c255d 2023-08-04 jrmu (make-product 2 0 'y)
125 665c255d 2023-08-04 jrmu (make-product (make-sum 5 -5) 'x)
126 665c255d 2023-08-04 jrmu (make-product (make-sum 2 4 -6) 'y)
127 665c255d 2023-08-04 jrmu (make-product (make-product 0 1) 'z)
128 665c255d 2023-08-04 jrmu (make-product 4 'z)
129 665c255d 2023-08-04 jrmu -3 -2 -1
130 665c255d 2023-08-04 jrmu (make-product 2 3)))
131 665c255d 2023-08-04 jrmu '(4 * z))
132 665c255d 2023-08-04 jrmu
133 665c255d 2023-08-04 jrmu (test-case (multiplier (make-product (make-product 5 4 'x (make-sum 1 'y))
134 665c255d 2023-08-04 jrmu (make-sum 2 'z)))
135 665c255d 2023-08-04 jrmu '(20 * x * (y + 1)))
136 665c255d 2023-08-04 jrmu (test-case (multiplier (make-product (make-sum 5 6 4 -2)
137 665c255d 2023-08-04 jrmu 'x 'y
138 665c255d 2023-08-04 jrmu (make-sum 1 -3 3)))
139 665c255d 2023-08-04 jrmu 13)
140 665c255d 2023-08-04 jrmu (test-case (multiplicand (make-product 5 'x)) 'x)
141 665c255d 2023-08-04 jrmu (test-case (multiplicand (make-product 5 'x 'y 'z)) '(x * y * z))
142 665c255d 2023-08-04 jrmu (test-case (multiplicand (make-product 5 'x 2 -3 'y)) '(x * y))
143 665c255d 2023-08-04 jrmu (test-case (multiplicand (make-product (make-sum 5 6 4 -2)
144 665c255d 2023-08-04 jrmu 'x 'y
145 665c255d 2023-08-04 jrmu (make-sum 1 -3 3)))
146 665c255d 2023-08-04 jrmu '(x * y))
147 665c255d 2023-08-04 jrmu
148 665c255d 2023-08-04 jrmu (test-case (deriv '(* x y (+ x 3)) 'x) '(+ (* x y) (* y (+ x 3))))