sicp-solutions/ex-2.56.scm

78 lines
No EOL
2.7 KiB
Scheme

#lang sicp
(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 (sum? x) (and (pair? x) (eq? (car x) '+)))
(define (addend s) (cadr s))
(define (augend s) (caddr s))
(define (product? x) (and (pair? x) (eq? (car x) '*)))
(define (multiplier p) (cadr p))
(define (multiplicand p) (caddr p))
; for the purposes of our exponentiation exercise, we need to determine whether
; the exponent is constant so that we can apply the rule correctly
(define (constant? x var)
(or (number? x)
(and (variable? x) (not (same-variable? x var)))
(and (sum? x)
(constant? (addend x) var)
(constant? (augend x) var))
(and (product? x)
(constant? (multiplier x) var)
(constant? (multiplicand x) var))
(and (exponentiation? x)
(constant? (base x) var)
(constant? (exponent x) var))))
(define (make-exponentiation b e)
(cond ((=number? e 0) 1)
((=number? e 1) b)
((=number? b 0) 0)
((and (number? b) (number? e)) (expt b e))
(else (list '** b e))))
(define (exponentiation? x) (and (pair? x) (eq? (car x) '**)))
(define (base e) (cadr e))
(define (exponent e) (caddr e))
(define (deriv exp var)
(cond ((number? exp) 0)
((variable? exp) (if (same-variable? exp var) 1 0))
((sum? exp) (make-sum (deriv (addend exp) var)
(deriv (augend exp) var)))
((product? exp)
(make-sum
(make-product (multiplier exp)
(deriv (multiplicand exp) var))
(make-product (deriv (multiplier exp) var)
(multiplicand exp))))
((exponentiation? exp)
(if (constant? (exponent exp) var)
(make-product (make-product (exponent exp)
(make-exponentiation (base exp)
(make-sum
(exponent exp)
-1)))
(deriv (base exp) var))
(error "non-constant exponents not yet supported: DERIV" exp)))
(else
(error "unknown expression type: DERIV" exp))))