; Differentiate an infix polynomial with terms of the form +cax^n ; where c is an optional integer constant and a is an optional ; variable other than x, and optional exponent n is an integer > 0. ; Example: (3 a x ^ 5 + b x ^ 4 + 2 x ^ 3 + 6 x ^ 2 + 3 x + 7) ; Differentiate with respect to var, for example x. ; The derivative will be in the same infix form. ; ; Assumptions: ; The polynomial is in the "canonical" form as described above. ; There is no error checking of the form. In particular, only ; the variable we're differentiating with respect to (such as x) ; can have an exponent. Any deviation from canonical form may ; cause a runtime exception. ; ; CS 152 Programming Language Paradigms ; Department of Computer Science ; San Jose State University ; Spring 2014 ; Instructor: Ron Mak ; Find the derivative of polynomial poly with respect to variable var. ; The polynomial must be in canonical infix form. ; First "terminize" the polynomial. ; Example: ; (terminize '(3 a x ^ 5 + b x ^ 4 + 2 x ^ 3 + 6 x ^ 2 + 3 x + 7)) ; ==> ((3 a x ^ 5) (b x ^ 4) (2 x ^ 3) (6 x ^ 2) (3 x) (7))) ; Note that var is a free variable in local procedure deriv-term. ; At run time, deriv-term obtains the value of var from its closure, ; and it is mapped over each sublist in the terminized polynomial. ; The result is a list of sublists, each sublist representing the derivative ; of the corresponding term. ; Example: ; (map deriv-term '((3 a x ^ 5) (b x ^ 4) (2 x ^ 3) (6 x ^ 2) (3 x) (7)))) ; ==> ((15 a x ^ 4) (4 b x ^ 3) (6 x ^ 2) (12 x) (3) (0)) ; Example: ; (deriv '(3 a x ^ 5 + b x ^ 4 + 2 x ^ 3 + 6 x ^ 2 + 3 x + 7) 'x) ; ==> (15 a x ^ 4 + 4 b x ^ 3 + 6 x ^ 2 + 12 x + 3) (define deriv (lambda (poly var) (let* ((terms (terminize poly)) ; "terminize" the polynomial (deriv-term ; local procedure deriv-term (lambda (term) (cond ((null? term) '()) ((not (member? var term)) '(0)) ; deriv = 0 ((not (member? '^ term)) (upto var term)) ; deriv = coeff (else (deriv-term-expo term var)) ; handle exponent ))) (diff (map deriv-term terms))) ; map deriv-term over the terms (remove-trailing-plus (polyize diff)) ; finalize the answer ))) ; Differentiate a single term that contains the var ; raised to a power (i.e., there's an exponent). ; If there are two adjacent integer constants in the new ; coefficient, replace them by their product. ; Example: (deriv-term-expo '(3 a x ^ 5) 'x) ==> (15 a x ^ 4) (define deriv-term-expo (lambda (term var) (let* ((coeff (upto var term)) ; get the coefficient (rev-term (reverse term)) ; reverse so that we can (expo (car rev-term)) ; get the exponent at the end (new-expo (sub1 expo)) ; new exponent (new-coeff (cond ((null? coeff) (list expo)) ; no coefficient ((number? (car coeff)) (cons (* (car coeff) expo) (cdr coeff))) ; product (else (cons expo coeff))))) ; The derivative: (if (= new-expo 1) (append new-coeff (list var)) (append new-coeff (list var '^ new-expo))) ))) ; Convert an infix polynomial into a list of sublists, ; where each sublist is a term. ; Example: (terminize '(3 a x ^ 5 + b x ^ 4 + 2 x ^ 3 + 6 x ^ 2 + 3 x + 7)) ; ==> ((3 a x ^ 5) (b x ^ 4) (2 x ^ 3) (6 x ^ 2) (3 x) (7))) (define terminize (lambda (poly) (cond ((null? poly) '()) (else (cons (upto '+ poly) (terminize (after '+ poly)))) ))) ; Convert a list of term sublists to an infix polynomial. ; Do not include any + 0 term. ; There may be an extra + at the end. ; Example: (polyize '((15 a x ^ 4) (4 b x ^ 3) (6 x ^ 2) (12 x) (3) (0))) ; ==> (15 a x ^ 4 + 4 b x ^ 3 + 6 x ^ 2 + 12 x + 3 +) (define polyize (lambda (terms) (cond ((null? terms) '()) ((equal? '(0) (car terms)) '()) ((null? (cdr terms)) (car terms)) (else (append (car terms) '(+) (polyize (cdr terms)))) ))) ; Return the polynomial without any extra + at the end. ; If the polynomial is empty, return (0). (define remove-trailing-plus (lambda (poly) (if (null? poly) '(0) (let ((rev-poly (reverse poly))) (if (equal? '+ (car rev-poly)) (reverse (cdr rev-poly)) (reverse rev-poly)) )))) ; Return #t if the given item is a top-level item of the given list. ; Else return #f. (define member? (lambda (item lst) (cond ((null? lst) #f) ((equal? item (car lst)) #t) (else (member? item (cdr lst))) ))) ; Return a list consisting of the items of the given list ; up to the first occurrence of the given item. ; Used to extract the coefficient of a term. ; Return the original list if the given item isn't in the list. ; Example: (upto 'x '(3 a x ^ 5)) ==> (3 a) (define upto (lambda (item lst) (cond ((null? lst) '()) ((equal? item (car lst)) '()) (else (cons (car lst) (upto item (cdr lst)))) ))) ; Return a list consisting of the items of the given list ; after the first occurrence of the given item. ; Used to extract the exponent of a term. ; Return the empty list if the given item isn't in the list. ; Example: (after 'x '(3 a x ^ 5)) ==> (^ 5) (define after (lambda (item lst) (cond ((null? lst) '()) ((equal? item (car lst)) (cdr lst)) (else (after item (cdr lst))) )))