ex 2.33, 2.34, 2.35, 2.36, 2.37, 2.38, 2.39, 2.40, 2.41
;; sicp ex 2.33 (define (my-accumulate op initial sequence) (if (null? sequence) initial (op (car sequence) (my-accumulate op initial (cdr sequence))))) (define (my-map p sequence) (my-accumulate (lambda (x y) (cons (p x) y)) '() sequence)) (define (my-append seq1 seq2) (my-accumulate cons seq2 seq1)) (define (my-length sequence) (my-accumulate (lambda (x y) (+ 1 y)) 0 sequence))
;; sicp ex 2.34 (define (horner-eval x coefficient-sequence) (my-accumulate (lambda (this-coeff higher-terms) (+ this-coeff (* higher-terms x))) 0 coefficient-sequence))
;; sicp ex 2.35 ;; 2.2.2 count-leaves (define (count-leaves x) (cond ((null? x) 0) ((not (pair? x)) 1) (else (+ (count-leaves (car x)) (count-leaves (cdr x)))))) ;; 参考に (define (enumerate-tree tree) (cond ((null? tree) '()) ((not (pair? tree)) (list tree)) (else (append (enumerate-tree (car tree)) (enumerate-tree (cdr tree)))))) (define (count-leaves-accum-sub t) (cond ((null? t) 0) ((not (pair? t)) 1) (else (count-leaves-accum t)))) (define (count-leaves-accum t) (my-accumulate + 0 (map count-leaves-accum-sub t)))
;; sicp ex 2.36 (define (my-accumulate-n op init seqs) (if (null? (car seqs)) '() (cons (my-accumulate op init (map car seqs)) (my-accumulate-n op init (map cdr seqs))))) ;; '((1 2 3) (4 5 6) (7 8 9))みたいなリストのとき ;; (map car seqs) で先頭の要素を集めたリストが得られるのか。覚えておこう。
;; sicp ex 2.38 (define (my-fold-left op initial sequence) (define (iter result rest) (if (null? rest) result (iter (op result (car rest)) (cdr rest)))) (iter initial sequence)) (define (my-fold-right op initial sequence) (my-accumulate op initial sequence)) ;; (my-fold-right / 1 '(1 2 3)) -> 3/2 ;; (my-fold-left / 1 '(1 2 3)) -> 1/6 ;; (my-fold-right list '() '(1 2 3)) -> (1 (2 (3 ()))) ;; (my-fold-left list '() '(1 2 3)) -> (((() 1) 2) 3) ;; fold-left, fold-rightどちらをつかっても結果が変わらないためには、 ;; opが交換則を満たしている必要がある。
;; sicp ex 2.39 (define (my-reverse-r sequence) (my-fold-right (lambda (x y) (append y (cons x '()))) '() sequence)) (define (my-reverse-l sequence) (my-fold-left (lambda (x y) (cons y x)) '() sequence))
;; sicp ex 2.40 ;; prime? ;; ex 1.21のを再利用 (define (square x) (* x x)) (define (smallest-divisor n) (find-divisor n 2)) (define (find-divisor n test-divisor) (cond ((> (square test-divisor) n) n) ((divides? test-divisor n) test-divisor) (else (find-divisor n (+ test-divisor 1))))) (define (divides? a b) (= (remainder b a) 0)) (define (prime? n) (= n (smallest-divisor n))) ;; filter 本文から (define (filter pred seq) (cond ((null? seq) '()) ((pred (car seq)) (cons (car seq) (filter pred (cdr seq)))) (else (filter pred (cdr seq))))) ;; 以下問題 ;; 実装のために必要な関数。 (define (enumerate-interval low high) (if (> low high) '() (cons low (enumerate-interval (+ low 1) high)))) ;; flatmap 本文から (define (flatmap proc seq) (my-accumulate append '() (map proc seq))) (define (unique-pairs n) (flatmap (lambda (x) (map (lambda (y) (list x y)) (enumerate-interval 1 (- x 1)))) (enumerate-interval 1 n))) (define (make-sum-pairs pair) (list (car pair) (cadr pair) (+ (car pair) (cadr pair)))) (define (prime-sum? pair) (prime? (+ (car pair) (cadr pair)))) ;; 実装 (define (prime-sum-pairs n) (map make-sum-pairs (filter prime-sum? (unique-pairs n))))
;; sicp ex 2.41 ;; i,j,kの組のリストを作る (define (unique-tris n) (flatmap (lambda (x) (flatmap (lambda (y) (map (lambda (z) (list x y z)) (enumerate-interval 1 (- y 1)))) (enumerate-interval 1 (- x 1)))) (enumerate-interval 1 n))) (define (search-sum-eq x n) (define (search-sum-eq-sub y items) (if (null? items) '() (if (= y (+ (caar items) (cadar items) (caddar items))) (cons (car items) (search-sum-eq-sub y (cdr items))) (search-sum-eq-sub y (cdr items))))) (search-sum-eq-sub x (unique-tris n)))
うむむ。徐々に歯ごたえが出てきました。
こうすればいいと、アイデアは思いつくものの、
それをうまく表現できなかったり、
表現してみたら、結果が全然別のものができていたり。
もっと、分割戦略を意識した方がいいのかな。
小さい問題の組み合わせで解いていく、ということを。
これは、公認インターフェイスにも通ずるし。
と書いていたら、ex 2.41はfilter使えばいいことに気づいた。
;; 書いた後に気づいた。 ;; filter使えばいいじゃん!! (define (search-sum-eq2 x n) (filter (lambda (y) (= x (+ (car y) (cadr y) (caddr y)))) (unique-tris n)))
...。
分割戦略だね!公認インターフェイスだね!