sicp第二章部分习题解答

(begin
    (load "ex1.scm")
    ;(define (make-rat n d) (cons n d))
    (define (numer x) (car x))
    (define (denom x) (cdr x))

    (define (print-rat x)
      (display (numer x))
      (display "/")
      (display (denom x))
      (newline))
    ;ex 2.1    
    (define (positive? x) (> x 0))    
    (define (negative? x) (< x 0))
    (define (make-rat n d)
        (let ((g (gcd n d)))
        (if (positive? (* n d))
            (cons (/ (abs n) g) (/ (abs d) g))
            (cons (/ (- (abs n)) g) (/ (abs d) g)))))
    ;ex 2.2
    (define (make-point x y)
        (cons x y))
    (define (x-point p)(car p))
    (define (y-point p)(cdr p))
    
    (define (print-point p)
        (display "x:")
        (display (x-point p))
        (display " y:")
        (display (y-point p))
        (newline)
    )
    (define (make-segment p1 p2) (cons p1 p2))
    (define (start-segment s)(car s))
    (define (end-segment s)(cdr s))
    (define (print-segment s)
        (display "[start:")
        (display (x-point (start-segment s)))
        (display " ")
        (display (y-point (start-segment s)))
        (display "] ")
        (display "[end:")
        (display (x-point (end-segment s)))
        (display " ")
        (display (y-point (end-segment s)))
        (display "]")
        (newline)        
    )
    ;线段长度
    (define (length-segment s)
        (sqrt (+ (square (- (x-point (start-segment s)) (x-point (end-segment s))))
             (square (- (y-point (start-segment s)) (y-point (end-segment s)))))))
    ;线段中点         
    (define (midpoint-segment s)
        (make-point (average (x-point (start-segment s)) (x-point (end-segment s))) 
        (average (y-point (start-segment s)) (y-point (end-segment s)))))
    ;ex 2.3
    ;使用2端点定义矩形
    (define (make-rectangle t-left b-right)
        (if (= (y-point t-left) (y-point b-right))
            (error "can't make a rectangle");如果两点构成的线段平行与x轴则无法构成矩形
            (cons t-left b-right)))
    (define (top-left r) (car r))
    (define (bottom-right r) (cdr r))
    ;计算矩形的周长        
    (define (perimeter-rectangle r)
        (* 2
        (+ (abs (- (y-point (top-left r)) (y-point (bottom-right r))))
           (abs (- (x-point (top-left r)) (x-point (bottom-right r)))))))
    ;计算矩形面积
    (define (area-rectangle r)
        (* (abs (- (y-point (top-left r)) (y-point (bottom-right r))))
           (abs (- (x-point (top-left r)) (x-point (bottom-right r))))))
    ;ex 2.4
    (define (cons1 x y)
        (lambda (m) (m x y)))
    (define (car1 z)
        (z (lambda (p q) p)))
    (define (cdr1 z)
        (z (lambda (p q) q)))
    ;ex 2.5 看下 2^2 * 3^3的二进制表示,注:序对不能有负数
    (define (cons2 x y) (* (fast-expt 2 x) (fast-expt 3 y)))
    (define (car2 z)
        (define (iter n z)
            (if (= (remainder z 2) 0)
                (iter (+ n 1) (/ z 2))
                 n))
        (iter 0 z))
    (define (cdr2 z)
        (define (iter n z)
            (if (= (remainder z 3) 0)
                (iter (+ n 1) (/ z 3))
                 n))
        (iter 0 z))
    ;ex 2.17    
    (define (last-pair p)
        (define (last-pair-imp front back)
            (if (null? back)
                (list front)
                (last-pair-imp (car back) (cdr back))))
        (if (null? p)
            p
            (last-pair-imp (car p) (cdr p))))
    ;ex 2.18
    ;递归
    (define (reverse p)
        (define (reverse-pair-imp front back)
            (cond ((null? back) (list front))
                  (else (append (reverse-pair-imp (car back) (cdr back)) (list front)))))
        (if (null? p)
            p
            (reverse-pair-imp (car p) (cdr p))))
    ;迭代
    (define (reverse2 items)
      (define (iter things answer)
        (if (null? things)
            answer
            (iter (cdr things) 
                  (cons (car things)
                        answer))))
      (iter items nil))            
    ;ex 2.19
    (define us-coins (list 50 25 10 5 1))
    (define uk-coins (list 100 50 20 10 5 2 1 0.5))
    ;: (cc 100 us-coins)
    (define no-more? null?)
    (define except-first-denomination cdr)
    (define first-denomination car)
    (define (cc amount coin-values)
      (cond ((= amount 0) 1)
            ((or (< amount 0) (no-more? coin-values)) 0)
            (else
             (+ (cc amount
                    (except-first-denomination coin-values))
                (cc (- amount
                       (first-denomination coin-values))
                    coin-values)))))            
    ;ex 2.20
    (define (same-parity x . y)
        (define (same-parity-imp checker front back)
            (define (process front) (if (checker front)(list front)nil))    
            (if (null? back)(process front)
                (append (process front) (same-parity-imp checker (car back) (cdr back)))))
        (if (even? x) (same-parity-imp even? x y)
            (same-parity-imp odd? x y)))
    ;ex 2.21
    (define (square-list1 items)
        (map square items))
    ;ex 2.22
    (define (square-list2 items)
      (define (iter things answer)
        (if (null? things)
            answer
            (iter (cdr things) 
                  (cons (square (car things))
                        answer))))
      (reverse2 (iter items nil)))
     ;ex 2.23
    (define (for-each proc items)
      (define (iter things)
        (cond ((null? things))
            (else
                (proc (car things))
                (iter (cdr things)))))
     (iter items))
    ;ex 2.27
    (define (deep-reverse tree)
        (cond ((null? tree) nil)
              ((not (pair? tree)) tree)
              (else (reverse (map deep-reverse tree)))))          
    ;ex 2.28
    (define (fringe tree)
        (cond ((null? tree) nil)
              ((not (pair? tree))(list tree))
              (else (append (fringe (car tree)) (fringe (cdr tree))))))
    ;ex 2.30 使用map
    (define (square-tree tree)
            (cond ((null? tree) nil)
            ((not (pair? tree)) (square tree))
            (else (map square-tree tree))))
    ;ex 2.30直接定义        
    (define (square-tree2 tree)
        (cond ((null? tree) nil)
            ((not (pair? tree)) (square tree))
            (else (cons (square-tree2 (car tree))
                        (square-tree2 (cdr tree))))))
    ;ex 2.31
    (define (tree-map func tree)
        (define (tree-map-imp tree)
                (cond ((null? tree) nil)
                ((not (pair? tree)) (func tree))
                (else (map tree-map-imp tree))))
        (tree-map-imp tree))
    (define (square-tree3 tree) (tree-map square tree))
    ;ex 2.32 产生子集合的方式,将集合a分成两部分(front back)
    ;a的子集合 = back的子集合 + 将front插入到back的所有子集合中产生的集合 
    (define (subsets s)
      (if (null? s)
          (list nil)
          (let ((rest (subsets (cdr s))))
            (display "rest:")(display rest)(newline)
            (append rest (map (lambda (rest) (cons (car s) rest)) rest)))))
    ;ex 2.33
    (define (map2 p sequence)
        (accumulate (lambda (x y) (cons (p x) y)) nil sequence))
    (define (append2 seq1 seq2)
        (accumulate cons seq2 seq1))
    (define (length2 sequence)
        (accumulate (lambda (_ counter) (+ 1 counter)) 0 sequence))
    ;ex 2.34
    (define (horner-eval x coefficient-sequence)
      (accumulate (lambda (this-coeff higher-terms) (+ this-coeff (* x higher-terms)))
                0
                coefficient-sequence))
    ;: (horner-eval 2 (list 1 3 0 5 0 1))
    ;ex 2.35
    (define (count-leaves2 t)
        (define (cal node count)
            (if (pair? node) (+ (accumulate cal 0 node) count);当前节点的叶子数+其它兄弟的叶子数
                (+ 1 count))
        )
        (accumulate cal 0 t))
    
    ;map fringe将((1 11) 10 (2 (3 4 5 (7 8))))) 展开成 ((1 11) (10) (2 3 4 5 7 8))
    ;分别计算每个子表的length累加即可    
    (define (count-leaves3 t)    
        (accumulate (lambda (node counter) (+ (length node) counter)) 0 (map fringe t)))
    ;ex 2.36
    (define a_s (list (list 1 2 3) (list 4 5 6) (list 7 8 9) (list 10 11 12)))
    (define (accumulate-n op init seqs)
      (if (null? (car seqs))
          nil
          (cons (accumulate op init (map car seqs))
                (accumulate-n op init (map cdr seqs)))))
    ;ex 2.37
    (define _mat (list (list 1 2 3) (list 4 5 6) (list 7 8 9)))
    (define (transpose mat) ;矩阵转置
        (accumulate-n cons nil mat))
    ;其余两个略去...
    
    ;ex 2.38
    ;fold-right和fold-left的主要区别
    ;fold-right op会首先被应用到最右边的成员
    ;fold-left  op首先被应用到最左边的成员
    ;要想op对fold-right和fold-left的任何输入序列都输出相同的结果,op必须满足交换率
    (define fold-right accumulate)
    (define (fold-left op initial sequence)
      (define (iter result rest)
        (if (null? rest)
            result
            (iter (op result (car rest))
                  (cdr rest))))
      (iter initial sequence))
    ;ex 2.39
    (define (reverse3 sequence)
        (fold-right (lambda (x y) (append y (list x))) nil sequence))
    (define (reverse4 sequence)
        (fold-left (lambda (x y) (cons y x)) nil sequence))
    ;ex 2.40
    (define (unique-pairs n)
        (define (process i)
            (map (lambda (j) (list i j)) (enumerate-interval 1 (- i 1)))
        )
     (accumulate append nil (map process (enumerate-interval 1 n))))
    (define (prime-sum? pair)
        (prime? (+ (car pair) (cadr pair))))

    (define (make-pair-sum pair)
        (list (car pair) (cadr pair) (+ (car pair) (cadr pair))))     
    (define (prime-sum-pairs n)
        (map make-pair-sum (filter prime-sum? (unique-pairs n))))
    ;ex 2.41
    (define (m-pairs2 n m)
        (define (iter l j ret)
            (cond ((< j 1)
                (list ret))
                (else
                (accumulate
                 append
                 nil
                 (map (lambda (x)
                       (cond ((< x j) nil) 
                             (else (iter (- x 1) (- j 1) (cons x ret)))))
                        (enumerate-interval 1 l))))))
        (iter n m nil))        
    ;(define (unique-pairs n) (m-pairs n 2))
    ;(((1 2)(3 4))(5 6))->((1 2)(3 4)(5 6))
    (define (flat seq)
        (define (iter seq ret)
            (cond ((not (pair? seq)) ret)
                  ((null? (car seq)) (cons nil ret))
                  ((pair? (car seq))
                    ;可以替换这两行看下区别
                    ;(let ((ret2 (iter (car seq) ret)))
                    ;     (iter (cdr seq) ret2)))                      
                     (let ((ret2 (iter (cdr seq) ret)))
                         (iter (car seq) ret2)))
                  (else (cons seq ret)))              
        )
        (iter seq nil)
    )        
    ;给定一个列表,从中提取n个所有集合
    ;例如(a b c d)->((a b c) (a c d) (a b d) (b c d))
    ;这个简单的问题整了我一天多,对函数式语言还是不熟啊
    (define (pick-n seq n)
        ;(d-table (1 2 3) 1)->((1 2 3) (2 3) (3))
        ;(d-table (1 2 3) 2)->((1 2 3) (2 3))
        ;(d-table (1 2 3) 3)->((1 2 3))
        (define (d-table seq n)
            (cond ((= n 0) nil)
                  (else
                    (if (<= (length seq) n) (list seq)
                        (cons seq (d-table (cdr seq) n ))))))    
        (define (process seq)
            (let ((size (length seq)))
                (cond ((<= n 1) (if (pair? seq) (list (car seq)) seq))
                      ((<= size n) seq)    
                      (else 
                        (map (lambda (x)(cons (car seq) x)) (pick-n (cdr seq) (- n 1))))))                      
        )
        (flat (map process (d-table seq n)))
    )
    ;更简单的实现
    (define (pick2-n seq n)
        (define (d-table seq n)
            (cond ((= n 0) nil)
                  (else
                    (if (<= (length seq) n) (list seq)
                        (cons seq (d-table (cdr seq) n ))))))    
        (define (process seq)
            (let ((size (length seq)))
                (cond ((<= n 1) (if (pair? seq) (list (car seq)) seq))
                      ((<= size n) (list seq))    
                      (else 
                        (map (lambda (x)
                                (if (pair? x)(cons (car seq) x)
                                    (cons (car seq) (list x)))) (pick2-n (cdr seq) (- n 1))))))                      
        )
        (flatmap process (d-table seq n))
    )
    (define (pick3-n seq n)
        ;从n个中选m个->从n-1个中选m个的集合+(将头部取出插入到从n-1个中选m-1个的集合)
        (define (process seq)
            (cond ((<= n 0) (list nil))
                  ((<= (length seq) n) seq)
                  (else
                     (cons (pick3-n (cdr seq) n) (map (lambda (x)(cons (car seq) x)) (pick3-n (cdr seq) (- n 1)))))
                  )
        )
        (flat (process seq))
    )
    (define (unique-pairs2 n) (pick-n (enumerate-interval 1 n) 2))
    ;(define (3-pairs n) (pick-n (enumerate-interval 1 n) 3))
    (define (m-pairs n m) (pick-n (enumerate-interval 1 n) m))
    ;flatmap练习
    (define (test1 i)
        (define (process x)
            (map (lambda (y) (list x y))(enumerate-interval 1 x)) 
        )
        (flatmap process (enumerate-interval 1 i))
    )
    (define (test2 i j)
        (define (process x)
            (map (lambda (y) (list x y))(enumerate-interval 1 j)) 
        )
        (flatmap process (enumerate-interval 1 i))
    )
    ;(flatmap (lambda (x) (map square x)) (list (list 1) (list 2)))
    ;2.31引号
    ;'后的对象表示对象应该作为数据而不是该求值的表达试对待
    ;(accumulate (lambda (x y) (cons (list x) y)) nil ''a)
    ;''a 表示一个列表其内容为(quote a)与(list 'quote 'a),'(quote a)等价
    ;(cons 'quote 'a)->(quote . a)
    ;(cons 'quote (list 'a))-> ''a
    ;(accumulate (lambda (x y) (cons (list x) y)) nil (car '('a))
    ;'('a)表示列表中有一个元素为('a) (car '('a)) 等价于 ''a
    ;比较''a 于 '('a)的区别(car (cdr ''a)) = (car (cdr (car '('a)))) = 'a
    
    ;ex 2.56
    
    (define (variable? x) (symbol? x))

    (define (same-variable? v1 v2)
      (and (variable? v1) (variable? v2) (eq? v1 v2)))

    ;(define (make-sum a1 a2) (list '+ a1 a2))

    ;(define (make-product m1 m2) (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))
    (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 (=number? exp num)
      (and (number? exp) (= exp num)))

    (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))))
    ;用base^expon表示base的expon次幂
    (define (make-exponentiation base expon)
        (if (number? expon)
            (cond ((= expon 0) 1)
                  ((= expon 1) base)    
                  (else (list '^ base expon)))
            (list '^ base expon))      
    )
    (define make-exp make-exponentiation)
    (define (exponentiation? e)
        (if (pair? e)(eq? (car e) '^)#f))
    (define is-exp? exponentiation?)
    (define (base e)
        (if (not is-exp?) (error "e is not a exponentiation")
            (car (cdr e))))            
    (define (exponent e);获得指数
        (if (not is-exp?) (error "e is not a exponentiation")
            (car (cddr e))))        
    (define (exponent-dec e);指数-1
        (let ((expon (exponent e)))
            (if (number? expon) (make-exp (base e) (- expon 1))
                (make-exp (base e) (list '- expon 1)))))    
    (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))))
            ;对幂的处理
            ((is-exp? exp)
              (make-product (make-product (exponent exp) (exponent-dec exp)) 
              (deriv (base exp) var))    
            )
            (else
             (error "unknown expression type -- DERIV" exp))))
    
    ;ex 2.57
    (define (augend s)
        (if (> (length (cddr s)) 1) (append (list '+) (cddr s))
            (caddr s)))
    (define (multiplicand p)
            (if (> (length (cddr p)) 1) (append (list '*) (cddr p))
            (caddr p)))
    ;ex 2.58        
    ;中缀表示
    (define (sum? x)
      (and (pair? x) (eq? (cadr x) '+)))
    (define (addend s) (car s))
    (define (augend s)        
        (if (> (length (cddr s)) 1) (cddr s)
            (caddr s)))

    (define (product? x)
      (and (pair? x) (eq? (cadr x) '*)))
    (define (multiplier p) (car p))
    (define (multiplicand p)            
        (if (> (length (cddr p)) 1) (cddr p)
            (caddr p)))
    
    (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))))    
    ;(deriv '(x * y * (x + 3)) 'x)
    ;(deriv '(x + 3 * (x + y + 2))
)

 

posted @ 2013-05-22 22:08  sniperHW  阅读(348)  评论(0编辑  收藏  举报