SICP 読み (24)
そろそろ問題のハードルが上がってきた。
問題 2.35
accumulate も map も平たいリスト向けだのに、と思いながら count-leaves の定義をニラむ。メモには「map でリストにする?」とか「accumulate で木を使う?」とか書いてあるがどうかんがえても
((1 2) (3 4) (5 (6 7)))
みたいなソレを map を使って
(1 2 3 4 5 6 7)
にはしてくれそうにない。accumulate は工夫すれば木を使えそうなんですが、そうだとしたら map 使う意味がないし、と。
で、map を使って count-leaves の真似をしてみた。例えば
((1 2) (3 4) (5 (6 7)))
なリストを
(2 2 3)
みたいにしてくれれば accumulate で簡単に扱えるな、と。
(map (lambda (x) (let f ((x x) (ret 0)) (cond ((null? x) 0) ((not (pair? x)) 1) (else (+ (f (car x) ret) (f (cdr x) ret)))))) '((1 2) (3 4) (5 (6 7))))
こうなれば accumulate で扱える形式になっているはず。
(define (count-leaves t) (accumulate + 0 (map (lambda (x) (let f ((x x) (ret 0)) (cond ((null? x) 0) ((not (pair? x)) 1) (else (+ (f (car x) ret) (f (cdr x) ret)))))) t)))
問題 2.36
それぞれの並びの先頭要素なリストを作らんと accumulate では扱えないはず。例えば
((1 2 3) (4 5 6) (7 8 9) (10 11 12))
なリストを処理する場合には
(accumulate + 0 '(1 4 7 10))
して残りのナニを accumulate-n に渡す、と。
(accumulate-n + 0 '((2 3) (5 6) (8 9) (11 12)))
みたいな感じ。これも map かのう、と思いつつ試す。
gosh> (define seqs '((1 2 3) (4 5 6) (7 8 9) (10 11 12))) seqs gosh> (map car seqs) (1 4 7 10) gosh>
うーむ。じゃ逆は cdr で良いの??
gosh> (map cdr seqs) ((2 3) (5 6) (8 9) (11 12)) gosh>