SICPを読む(58) 2.2.3(2) 写像の入れ子 と 問題 2.40 - 2.41
順列の問題です。頭の中が混乱した。
話題の中心は
mapをfor文のように使ってみてはどうだろうかという話題らしい。
混乱したのは問題の定義
混乱したところを分割して読むと。
- 与えられた整数nに対して
- 1<= j < i <= nである
- 正の整数(i, j)
- i + jが素数になるもの。
「j < i で、(i, j)」ってiとjが逆じゃないか!!
と随分たってから気づいた。
素数について。
- キミならどう書く 2.0 - ROUND 1 - ― Lightweight Language Ring
- shiroさんのコメントに注目。srfi-42が凄い。邪道すぎ。
疑問
removeで(not (= x item))と指定したものを取り除いている。リストがユニークな場合はこれでいいと思う。もしも内容がユニークでない場合、removeだとおかしな事になってしまう。
(1 2 2 3 3 3)というリストだった場合、3を取り除くと、(1 2 2)になってしまう。
n番目の要素を取り除くように、インデックスで判断したほうが良さげな気がする。
問題 2.40
必要な要素を抜き出せば良い。
(define (unique-pairs n) (flatmap (lambda (i) (map (lambda (j) (list i j)) (iota (- i 1) 1))) (iota n 1))) (define (prime-sum-pairs n) (map make-pair-sum (filter prime-sum? (unique-pairs n))))
問題 2.41
まずは、unique-pairsの3個版。
(define (unique-trio n) (flatmap (lambda (i) (flatmap (lambda (j) (map (lambda (k) (list i j k)) (iota (- j 1) 1))) (iota (- i 1) 1))) (iota n 1))) (define (unique-trio n) (flatmap (lambda (i) (map (lambda (j) (cons i j)) (unique-pairs (- i 1)))) (iota n 1))) (map reverse (unique-trio 4)) ; ((1 2 3) (1 2 4) (1 3 4) (2 3 4))
上は最初に作った奴。下はunique-pairsを利用したもの。
(map reverse)を使うと見やすくできます。
これを使ってフィルタを通します。
(define (trio-filter-sumeq n sum) (filter (lambda (i) (= sum (+ (car i) (cadr i) (caddr i)))) (unique-trio n))) (map reverse (trio-filter-sumeq 10 12)) ; ((3 4 5) (2 4 6) (1 5 6) (2 3 7) (1 4 7) (1 3 8) (1 2 9))
いい感じ。
まとめ
(i, j, k)は i < j < kの方がわかりやすい。