SICPを読む(53) 2.2.2(2) 木の写像
さてさて、リスト処理も本格的な感じになってきます。今回は木の写像。
まずは普通に
ふつうに。
(define (scale-tree tree n) (cond ((null? tree) `()) ((not-pair? tree) (* tree n)) (else (cons (scale-tree (car tree) n) (scale-tree (cdr tree) n))))) (scale-tree '(1 (2 (3 4))) 10) ; (10 (20 (30 40)))
car,cdrで巡ればいい。
map再帰
ex-2.27 | SICP | OpenSource Webで出てきたmap再帰が登場。
こんなのは・・・。
(map (lambda (x) (+ x 10)) '(1 (2 (3 4)))) ; Error
ダメだよね・・・。
仕方ないので、真面目に巡ろう。
(define (scale-tree tree n) (map (lambda (sub-tree) (if (pair? sub-tree) (scale-tree sub-tree n) (* sub-tree n))) tree)) (scale-tree '(1 (2 (3 4))) 10) ; (10 (20 (30 40)))
mapをして、pairを見ると。
map再帰セクシーすぎる!!
問題 2.30
square-treeを定義せよと。
ふつうの。
(define (square-tree tree) (cond ((null? tree) '())(list '()) ((not-pair? tree) (square tree)) (else (cons (square-tree (car tree)) (square-tree (cdr tree))))))
map再帰。
(define (square-tree tree) (map (lambda (sub-tree) (if (pair? sub-tree) (square-tree sub-tree) (square sub-tree))) tree))
map再帰の方がらくちん。
問題 2.31
tree-mapを定義せよ。
(define (tree-map f tree) (map (lambda (sub-tree) (if (pair? sub-tree) (tree-map f sub-tree) (f sub-tree))) tree))
使ってみる。
(define (square-tree tree) square tree) (square-tree '(1 (2 (3 4) (5 6))))
スゲー楽。
問題 2.32
穴埋めながら全然わからず・・・。
とりあえず(subsets '(1 2))の場合の方針を練ってみる。
(append (list '()) (list '(2)) (list '(1) (list '(1 2)))) ; (() (2) (1) ((1 2)))
あぁ、こんな感じか。(list '())を使っている理由が判明。
carを使ってないので、carを使えばなんとかなるような気がして、適当に・・・。
(define (subsets s) (if (null? s) (list '()) (let ((rest (subsets (cdr s)))) (append rest (map (lambda (x) (cons (car s) x)) ; 穴の部分 rest)))))
えい!
(subsets '(1 2 3)) ; (() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))
出来た!!
が、「明快に説明せよ」という問には答えられず・・・。
素晴らしい回答が
SICP memo: 問題2.32
地道にdisplayしてみた。
rest (cons (car s) x) (()) + (3) (() (3)) + (2) + (2 3) (() (3) (2) (2 3)) + (1) + (1 3) + (1 2) + (1 2 3) = (() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))
おぉ、わかった!!
ズズーっと下っていって。(list '())からスタートする。 restが、(())で、(())に3を加えると((3))。appendして(() (3)) (() (3))にそれぞれ2を加えると((2) (2 3))。appendして(() (3) (2) (2 3)) (() (3) (2) (2 3))にそれぞれ1を加えて、((1) (1 3) (1 2) (1 2 3))。appendしたら!! (() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))
つまり、
すべての部分集合の集合 =(「s の最初の要素」を含む部分集合の集合) +(「s の最初の要素」を含まない部分集合の集合)
である。
できたぁぁぁっっっっっっっっっっっっっっ!!
Gaucheのライブラリが凄すぎ
Gauche リファレンスマニュアル: 組み合わせ
ナンダコレハ。