関数 intersectall は、セットのリスト l-set を引数にとって、各セットすべての共通部分を返す関数。
これは答えを見なければわからなかった。というか、はじめに思いついたのは fold を使った実装。でも、fold はまだ出てきてないから使わないとするとどうしたらいいんだろう、と。
とりあえず fold を使ったコードを載せる。
(use mymodule) (define intersect (lambda (s1 s2) (cond ((null? s1) (quote ())) ((member? (car s1) s2) (cons (car s1) (intersect (cdr s1) s2))) (else (intersect (cdr s1) s2))))) (define intersectall (lambda (l-set) (fold intersect (car l-set) (cdr l-set)))) (print (intersectall '((a b c) (c a d e) (e f g h a b)))) (print (intersectall '((6 pears and) (3 peaches and 6 peppers) (8 pears and 6 plums) (and 6 prunes with lots of apples))))
^o^ > gosh -I. intersectall2.scm (a) (and 6)
期待どおりに動いている。
で、こっちが fold を使わないコード。答を見ながら写経した。
(use mymodule) (define intersect (lambda (s1 s2) (cond ((null? s1) (quote ())) ((member? (car s1) s2) (cons (car s1) (intersect (cdr s1) s2))) (else (intersect (cdr s1) s2))))) (define intersectall (lambda (l-set) (cond ((null? (cdr l-set)) (car l-set)) (else (intersect (car l-set) (intersectall (cdr l-set))))))) (print (intersectall '((a b c) (c a d e) (e f g h a b))))
なるほど、最終条件は (null? (cdr l-set))
なら値は (car l-set)
、つまり最後のセットはそのまま返す。で、途中は (car l-set)
と (cdr l-set)
で再帰したセットに intersect を適用している。これですべてのセットの共通部分が取り出せるわけだ。
結果は:
^o^ > gosh -I. intersectall.scm (a) (6 and)
fold を使ったものと同じになった。よかった、fold 使ったコードも間違いじゃなかった。