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> 

できちゃった。がしかし、次の線形代数なソレが微妙。ちなみに今、NHK にて google な番組をやっていますな。