sicp(13)m2,35〜m2.37

;;復習
;;15分ぐらいでaccumulate(list),filter, acc-map, acc-length,
;;fringe, enumerate-intervalを作ろうとした。
;;30分以上かかった。

(define (accumulate op initial sequence)
  (if (null? sequence)
      initial
      (op (car sequence)
          (accumulate op initial (cdr sequence)))))

(define (filter predicate sequense)
  (cond ((null? sequense) '())
        ((predicate (car sequense))
         (cons (car sequense)
            (filter predicate (cdr sequense))))
         (else  (filter predicate (cdr sequense)))))

(define (acc-map f tree)
  (accumulate cons '() tree))

(define (acc-length tree)
  (accumulate (lambda (x y) (+ 1 y)) tree))
(define (fringe tree)
  (cond ((null? tree) '())
        ((not (pair? tree)) (list tree))
        (else (append (fringe (car tree))
                      (fringe (cdr tree))))))

;;filterのようなものを使ってfringeを作れないかな。
;;(互換性を保ちつつ)

(define (enumerate-interval low high)
  (if (> low high)
      '()
      (cons low (enumerate-interval (+ low 1) high))))
(define (acc-sum list)
  (accumulate + 0 list))
;	gosh> (acc-sum (enumerate-interval 1 10))
;	55

;;m2.35
;;これ以外思いつかないので、先に進み後でまた考える。
(define (count-leaves t)
  (accumulate (lambda (x y) (+ 1 y)) 0 (fringe t)))
;	gosh> (count-leaves '(1 2 3 (4 (5 6))))
;	6
;(define (count-leaves t)
;  (accumulate <> <> (map <> <>)))
;;思いつかない…
;;m2.36
(define (accumulate-n op init seqs)
  (if (null? (car seqs))
      '()
      (cons (accumulate op init (map car seqs))
            (accumulate-n op init (map cdr seqs)))))
(define s '((1 2 3) (4 5 6) (7 8 9) (10 11 12)))
;	gosh> (accumulate-n + 0 s)
;	(22 26 30)
;;置き換えてみると分かる。(ただし、逆方向)
;;※accmulate-n=an, accumulate=a
;;めんどうなので(a + 0 ' (map car)=am-carとかく。
;	(22 26 30)
;	(am-car am-cadr am-caddr (an '(() () ())))
;	(am-car am-cadr (an '((3) (6) (9) (12))))
;	(am-car (an '((2 3) (5 6) (8 9) (11 12))))
;	(an s)

;;ちなみにrubyで同じようなことをするとこんな感じ。
;;(読みづらいかもしれない)
;def f n
;  [n, n+1, n+2]
;end
;p s=(0..3).map{|e| (f(e*3+1))}
;#=>[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
;;これでsと同じような配列を作成。  
;def s.sum_n
;  #schemeのlambdaと違うのでlambda->procの方が良いかも
;  f = proc {|i| self.map{|e| e[i]}}
;  (0..(self[0].size-1)).inject([]){|re,e|re << f[e].inject{|s,n| s+n}}
;end
;p s.sum_n
;
;#=>[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]

;;2.37
;;とりあえず、問題の元の行列を手軽に呼び出せるようする
(define ei enumerate-interval)
(define m2.37 (list (ei 1 4) (append (ei 4 6) '(6)) (ei 6 9)))

(define (dot-product v w)
  (accumulate + 0 (map * v w)))
;;m2.37は明日する