SICPを読む(57) 問題 2.37 - 2.39

どうやら僕のSICPリーディング速度はかなり遅いらしい(汗

回りが凄い人達だらけなので、圧倒されないようにマイペースで行こうと思う。

問題 2.37

ベクトル演算の問題。

行列があんま得意じゃない。つうか数学全般的に。

(define v '(1 2 3))
(define w '(4 5 6))
(define m '((1 2 3) (4 5 6) (7 8 9)))
(define n '((9 8 7) (6 5 4) (3 2 1)))

(define (dot-product v m)
  (fold + 0 (map * v m)))
(dot-product v w) ; 32

(define (matrix-*-vector m v)
  (map (cut dot-product v <>) m))

(matrix-*-vector m v) ; (14 32 50)

(define (transpose mat)
  (accumulate-n cons '() mat))

(transpose m) ; ((1 4 7) (2 5 8) (3 6 9))

(define (matrix-*-matrix m n)
  (let ((cols (transpose n)))
    (map (cut matrix-*-vector cols <>) m)))

(matrix-*-matrix m n) ; ((30 24 18) (84 69 54) (138 114 90))

(map * v m)という強烈な技があったとは・・・。

問題 2.38

fold_left(fold),fold_rightの順番について。

紙の上で計算して、答合わせした。

まず割り算。

(define l '(1 2 3))

(fold-right / 1 l) ; 3/2
(fold / 1 l)       ; 3/2

(/ 1 (/ 2 (/ 3 1))) ; 3/2
(/ 3 (/ 2 (/ 1 1))) ; 3/2

アレ?答えが同じになった?!オカシイ。

と思ったら、lのlengthが奇数の時は答えが同じ。偶数の時は答えが逆数になる。

ひっかけ問題かよ!!


リストの場合。

(fold-right list '() l) ; (1 (2 (3 ())))
(fold list '() l)       ; (3 (2 (1 ())))

入れ子のリストができあがる。

どのような並びに対しても同じ値を生じるためにopが満たすべき性質は?という設問。

上の実験結果から、

(op a b) = (op b a)が成り立つ時にはリストも同値となる。

foldの扱いには注意。

問題 2.39

reverseをfold_right,fold_leftで作る。

 2.39
(define (reverse sequence)
  (fold-right (lambda (x y)
                (append y (list x))) '() sequence))

(define (reverse sequence)
  (fold cons '() sequence))

何度もやってきたので慣れてきたかも。