分别将练习2.88和2.89的两种表现方式封装成包,然后安装进操作表(install-sparse-polynomial-package)稀疏多项式
(install-dense-polynomial-package)稠密多项式
提取出一个公共谓词coeff-all-zero?来判断所有系数是否为零,将它作为判断多项式是否为零的谓词子过程。
其他add-terms、sub-terms、mul-terms过程直接放进操作表就可以。
#lang racket
;put get实现
(define *op-table* (make-hash))
(define (put op type proc)
(hash-set! *op-table* (list op type) proc))
(define (get op type)
(hash-ref *op-table* (list op type) #f))
(define (attach-tag type-tag contents)
(cond ((eq? type-tag 'scheme-number) contents)
(else (cons type-tag contents))))
(define (type-tag datum)
(cond ((number? datum) 'scheme-number)
((pair? datum) (car datum))
(else (error "Bad tagged datum -- TYPE-TAG" datum))))
(define (contents datum)
(cond ((number? datum) datum)
((pair? datum) (cdr datum))
(else (error "Bad tagged datum -- CONTENTS" datum))))
(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"
(list op type-tags))))))
(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 (=zero? x) (apply-generic '=zero? x))
(define (coeff-all-zero? x) (apply-generic 'coeff-all-zero? x))
(define (install-scheme-number-package)
(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 '=zero? '(scheme-number)
(lambda (x) (= x 0)))
(put 'make 'scheme-number
(lambda (x) (tag x)))
'done)
(define (make-scheme-number n)
((get 'make 'scheme-number) n))
(define (install-polynomial-package)
(define (make-poly variable term-list)
(cons variable term-list))
(define (variable p) (car p))
(define (term-list p) (cdr p))
(define (add-poly p1 p2)
(if (same-variable? (variable p1) (variable p2))
(make-poly (variable p1)
(add (term-list p1)
(term-list p2)))
(error "Poly not in same var -- ADD-POLY"
(list p1 p2))))
(define (sub-poly p1 p2)
(if (same-variable? (variable p1) (variable p2))
(make-poly (variable p1)
(sub (term-list p1)
(term-list p2)))
(error "Poly not in same var -- SUB-POLY"
(list p1 p2))))
(define (mul-poly p1 p2)
(if (same-variable? (variable p1) (variable p2))
(make-poly (variable p1)
(mul (term-list p1)
(term-list p2)))
(error "Polys not in same var -- MUL-POLY"
(list p1 p2))))
(define (=zero-poly? poly)
(coeff-all-zero? (term-list poly)))
(define (tag p) (attach-tag 'polynomial p))
(put 'add '(polynomial polynomial)
(lambda (p1 p2) (tag (add-poly p1 p2))))
(put 'mul '(polynomial polynomial)
(lambda (p1 p2) (tag (mul-poly p1 p2))))
(put 'sub '(polynomial polynomial)
(lambda (p1 p2) (tag (sub-poly p1 p2))))
(put '=zero? '(polynomial) =zero-poly?)
(put 'make 'polynomial
(lambda (var terms) (tag (make-poly var terms))))
'done)
(define (install-sparse-polynomial-package)
(define (add-terms L1 L2)
(cond ((empty-termlist? L1) L2)
((empty-termlist? L2) L1)
(else
(let ((t1 (first-term L1)) (t2 (first-term L2)))
(cond ((> (order t1) (order t2))
(adjoin-term
t1 (add-terms (rest-terms L1) L2)))
((< (order t1) (order t2))
(adjoin-term
t2 (add-terms L1 (rest-terms L2))))
(else
(adjoin-term
(make-term (order t1)
(add (coeff t1) (coeff t2)))
(add-terms (rest-terms L1)
(rest-terms L2)))))))))
(define (sub-terms L1 L2)
(cond ((empty-termlist? L1) L2)
((empty-termlist? L2) L1)
(else
(let ((t1 (first-term L1)) (t2 (first-term L2)))
(cond ((> (order t1) (order t2))
(adjoin-term
t1 (sub-terms (rest-terms L1) L2)))
((< (order t1) (order t2))
(adjoin-term
t2 (sub-terms L1 (rest-terms L2))))
(else
(adjoin-term
(make-term (order t1)
(sub (coeff t1) (coeff t2)))
(sub-terms (rest-terms L1)
(rest-terms L2)))))))))
(define (mul-terms L1 L2)
(if (empty-termlist? L1)
(the-empty-termlist)
(add-terms (mul-term-by-all-terms (first-term L1) L2)
(mul-terms (rest-terms L1) L2))))
(define (mul-term-by-all-terms t1 L)
(if (empty-termlist? L)
(the-empty-termlist)
(let ((t2 (first-term L)))
(adjoin-term
(make-term (+ (order t1) (order t2))
(mul (coeff t1) (coeff t2)))
(mul-term-by-all-terms t1 (rest-terms L))))))
(define (adjoin-term term term-list)
(if (=zero? (coeff term))
term-list
(cons term term-list)))
(define (coeff-all-zero? term-list)
(if (empty-termlist? term-list)
#t
(if (=zero? (coeff (first-term term-list)))
(coeff-all-zero? (rest-terms term-list))
#f)))
(define (the-empty-termlist) '())
(define (first-term term-list) (car term-list))
(define (rest-terms term-list) (cdr term-list))
(define (empty-termlist? term-list) (null? term-list))
(define (make-term order coeff) (list order coeff))
(define (order term) (car term))
(define (coeff term) (cadr term))
(define (tag p) (attach-tag 'sparse p))
(put 'coeff-all-zero? '(sparse)
(lambda (p1) (coeff-all-zero? p1)))
(put 'add '(sparse sparse)
(lambda (p1 p2) (tag (add-terms p1 p2))))
(put 'mul '(sparse sparse)
(lambda (p1 p2) (tag (mul-terms p1 p2))))
(put 'sub '(sparse sparse)
(lambda (p1 p2) (tag (sub-terms p1 p2))))
(put 'make 'sparse
(lambda (terms) (tag terms)))
'done)
(define (install-dense-polynomial-package)
(define (add-terms L1 L2)
(cond ((empty-termlist? L1) L2)
((empty-termlist? L2) L1)
(else
(let ((t1 (first-term L1)) (t2 (first-term L2)))
(cond ((> (order L1) (order L2))
(adjoin-term
t1 (add-terms (rest-terms L1) L2)))
((< (order L1) (order L2))
(adjoin-term
t2 (add-terms L1 (rest-terms L2))))
(else
(adjoin-term
(add (coeff L1) (coeff L2))
(add-terms (rest-terms L1)
(rest-terms L2)))))))))
(define (sub-terms L1 L2)
(cond ((empty-termlist? L1) L2)
((empty-termlist? L2) L1)
(else
(let ((t1 (first-term L1)) (t2 (first-term L2)))
(cond ((> (order L1) (order L2))
(adjoin-term
t1 (sub-terms (rest-terms L1) L2)))
((< (order L1) (order L2))
(adjoin-term
t2 (sub-terms L1 (rest-terms L2))))
(else
(adjoin-term
(sub (coeff L1) (coeff L2))
(sub-terms (rest-terms L1)
(rest-terms L2)))))))))
(define (mul-terms L1 L2)
(if (empty-termlist? L1)
(the-empty-termlist)
(add-terms (mul-term-by-all-terms L1 L2)
(mul-terms (rest-terms L1) L2))))
(define (mul-term-by-all-terms L1 L2)
(if (empty-termlist? L2)
(if (= (length L1) 1) (the-empty-termlist) (make-term-list (- (order L1) 1) 0))
(let ((t1 (first-term L1))
(t2 (first-term L2)))
(adjoin-term
(mul t1 t2)
(mul-term-by-all-terms L1 (rest-terms L2))))))
(define (adjoin-term term term-list)
(cons term term-list))
(define (the-empty-termlist) '())
(define (first-term term-list) (car term-list))
(define (rest-terms term-list) (cdr term-list))
(define (coeff-all-zero? term-list)
(if (empty-termlist? term-list)
#t
(if (=zero? (first-term term-list))
(coeff-all-zero? (rest-terms term-list))
#f)))
(define (make-term-list order coeff)
(define (iter n term-list)
(if (= n order) (cons coeff term-list)
(iter (+ n 1) (cons 0 term-list))))
(iter 0 '()))
(define (order term-list) (- (length term-list) 1))
(define (coeff term-list) (car term-list))
(define (tag p) (attach-tag 'dense p))
(put 'coeff-all-zero? '(dense)
(lambda (p1) (coeff-all-zero? p1)))
(put 'add '(dense dense)
(lambda (p1 p2) (tag (add-terms p1 p2))))
(put 'mul '(dense dense)
(lambda (p1 p2) (tag (mul-terms p1 p2))))
(put 'sub '(dense dense)
(lambda (p1 p2) (tag (sub-terms p1 p2))))
(put 'make 'dense
(lambda (terms) (tag terms)))
'done)
(define (make-polynomial var terms)
((get 'make 'polynomial) var terms))
(define (make-dense-terms terms)
((get 'make 'dense) terms))
(define (make-sparse-terms terms)
((get 'make 'sparse) terms))
(define (empty-termlist? term-list) (null? term-list))
(define (same-variable? v1 v2)
(define (variable? x) (symbol? x))
(and (variable? v1) (variable? v2) (eq? v1 v2)))
(install-scheme-number-package)
(install-polynomial-package)
(install-sparse-polynomial-package)
(install-dense-polynomial-package)
(define sparse-polynumial-A (make-polynomial 'x (make-sparse-terms '((5 5) (4 2) (3 4) (2 5) (1 6) (0 7)))))
(define sparse-polynumial-B (make-polynomial 'x (make-sparse-terms '((5 5) (4 2) (3 4) (2 5) (1 6) (0 7)))))
(define sparse-polynumial-C (make-polynomial 'x (make-sparse-terms '((1 2) (0 1)))))
(add sparse-polynumial-A sparse-polynumial-B)
(sub sparse-polynumial-A sparse-polynumial-B)
(mul sparse-polynumial-B sparse-polynumial-C)
(define dense-polynumial-A (make-polynomial 'x (make-dense-terms '(5 2 4 5 6 7))))
(define dense-polynumial-B (make-polynomial 'x (make-dense-terms '(5 2 4 5 6 7))))
(define dense-polynumial-C (make-polynomial 'x (make-dense-terms '(2 1))))
(add dense-polynumial-A dense-polynumial-B)
(sub dense-polynumial-A dense-polynumial-B)
(mul dense-polynumial-B dense-polynumial-C)
运行结果
'done
'done
'done
'done
'(polynomial x sparse (5 10) (4 4) (3 8) (2 10) (1 12) (0 14))
'(polynomial x sparse)
'(polynomial x sparse (6 10) (5 9) (4 10) (3 14) (2 17) (1 20) (0 7))
'(polynomial x dense 10 4 8 10 12 14)
'(polynomial x dense 0 0 0 0 0 0)
'(polynomial x dense 10 9 10 14 17 20 7)