莊周夢蝶

          生活、程序、未來
             :: 首頁 ::  ::  :: 聚合  :: 管理

          sicp習題2.33-2.39嘗試解答

          Posted on 2007-06-27 15:14 dennis 閱讀(489) 評論(3)  編輯  收藏 所屬分類: 計算機科學與基礎
          這一節的內容非常有趣,通過將序列作為interface,在此基礎上進而提取出各種高階操作(map,filter,accumulate,enumerate等),由此引出模塊化設計的討論。模塊化設計帶來復雜性的降低,同時可能引入性能上的損失,比如書中對sum-odd-squares過程的兩種寫法,原來的寫法枚舉列表元素的過程散落在累積、過濾、映射的過程中,主要一次循環就夠了,而通過三個高階過程來操作反而需要3次的遍歷。

          習題2.33,將map,append,length基本過程用累積操作重新定義,聯系以往的實現通過觀察和測試可以得出:
          (define (map p sequence)
            (accumulate  (
          lambda(x y) 
                          (cons (p x) y))       
                                 () sequence))
          (define (append seq1 seq2)
            (accumulate cons seq2 seq1))
          (define (length sequence)
            (accumulate (
          lambda(x y)
                          (
          + 1 y))
                          0 sequence))
          難點就在于累積的操作。

          習題2.34,Horner規則求多項式,難點也是累積操作的定義:
          (define (horner-eval x coefficient-sequence)
            (accumulate (
          lambda(this-coeff higher-terms)
                          (
          + this-coeff (* x higher-terms)))
                        0 coefficient
          -sequence))
          只要記住lambda中的y其實是另一個遞歸的accumulate就比較容易完成了。
          測試下:
          > (horner-eval 2 (list 1 3 0 5 0 1))
           
          79

          習題2.35,利用map和accumulate重新定義count-leaves統計樹的節點數目:
          (define (count-leaves t)
            (accumulate 
          + 0 (map (lambda (x) (if (pair? x) (count-leaves x) 1)) t)))
          map過程的參數op是過程
          (lambda (x) (if (pair? x) (count-leaves x) 1))
          當x是列表,遞歸調用count-leaves,否則返回個數1

          習題2.36,列表的列表,因此map過程的第一個參數是一個過程作用于列表中的每個列表,當然是采用car將它們首項取出然后進行op操作,因此:
          (define (accumulate-n op init seqs)
            (
          if (null? (car seqs))
                ()
                (cons (accumulate op init (map car seqs))
                      (accumulate
          -n op init (map cdr seqs)))))

          習題2.37,list作為Lisp的基本結構可以演化出各式各樣的復雜結構,比如此題就將列表作為矢量,矢量通過組合成為矩陣,3個解答就是矩陣的運算:
          (define (dot-product v w)
            (accumulate 
          + 0 (map * v w)))
          (define (matrix
          -*-vector m v)
            (map (
          lambda (x) (dot-product x v)) m))
          (define (transpose mat)
            (accumulate
          -n cons () mat))
          (define (matrix
          -*-matrix m n)
            (let ((cols (transpose n)))
              (map (
          lambda (x) (matrix-*-vector cols x)) m)))
          知道矩陣運算的定義得出結果并不困難。

          習題2.38,計算下結果:
          > (fold-right / 1 (list 1 2 3))
          1 1/2
          ;也就是3
          /2

          > (fold-left / 1 (list 1 2 3))
          1/6
          > (fold-right list () (list 1 2 3))
          (
          1 (2 (3 ())))
          > (fold-left list () (list 1 2 3))
          (((() 
          123)

          如果想使這兩個過程的結果相同,op需要滿足交換率和結合率的條件。

          習題2.39:
          ;2.39
          (define (reverse
          -list sequence)
            (fold
          -right (lambda(x y)(append y (list x))) () sequence))
          (define (reverse
          -list2 sequence)
            (fold
          -left (lambda(x y) (cons y x)) () sequence))





          評論

          # re: sicp習題2.33-2.39嘗試解答  回復  更多評論   

          2011-02-18 11:24 by shiqicai
          哥們,你習題2.33跑沒跑過啊,根本就做錯了!

          # re: sicp習題2.33-2.39嘗試解答  回復  更多評論   

          2011-02-18 11:26 by dennis
          @shiqicai
          那請給我一個正確答案嘛

          # re: sicp習題2.33-2.39嘗試解答  回復  更多評論   

          2011-02-18 11:30 by dennis
          @shiqicai
          回頭看了下,沒發現有什么問題,我這個解答跟下面這個解答是一樣的
          http://community.schemewiki.org/?sicp-ex-2.33
          主站蜘蛛池模板: 西充县| 平顺县| 凌源市| 永清县| 平安县| 屯留县| 赤城县| 深水埗区| 甘德县| 科技| 昂仁县| 宣汉县| 平原县| 柘荣县| 宽甸| 高唐县| 两当县| 巴中市| 武义县| 丘北县| 江都市| 双牌县| 且末县| 长海县| 长汀县| 汕尾市| 古浪县| 于田县| 饶河县| 德安县| 吉水县| 青神县| 绵阳市| 连平县| 柳州市| 阿城市| 扶风县| 桃江县| 涞水县| 昭苏县| 泗水县|