sicp-ex-2.37



<< Previous exercise (2.36) | Index | Next exercise (2.38) >>


jz

I find it a bit mind-boggling that we're essentially using cons, car, cdr, and recursion/iteration to invert a matrix.

  
 ;; Accumulates the result of the first and the already-accumulated 
 ;; rest. 
 (define (accumulate op initial sequence) 
   (if (null? sequence) 
       initial 
       (op (car sequence) 
           (accumulate op initial (cdr sequence))))) 
  
  
 ;; accumulate-n 
 (define (accumulate-n op init sequence) 
   (define nil '()) 
   (if (null? (car sequence)) 
       nil 
       (cons (accumulate op init (map car sequence)) 
             (accumulate-n op init (map cdr sequence))))) 
  
  
 (define matrix (list (list 1 2 3 4) (list 5 6 7 8) (list 9 10 11 12))) 
  
  
 (define (dot-product v1 v2) 
   (accumulate + 0 (map * v1 v2))) 
  
 ;; Test 
 (dot-product (list 1 2 3) (list 4 5 6)) 
  
  
 ;; a. 
 (define (matrix-*-vector m v) 
   (map (lambda (m-row) (dot-product m-row v)) 
        m)) 
  
 ;; Test 
 (matrix-*-vector matrix (list 2 3 4 5)) 
  
  
 ;; b. 
 (define nil '()) 
 (define (transpose m) 
   (accumulate-n cons nil m)) 
  
 ;; Test 
 (transpose matrix) 
  
  
 ;; c. 
 (define (matrix-*-matrix m n) 
   (let ((n-cols (transpose n))) 
     (map (lambda (m-row) 
            (map (lambda (n-col)  
                   (dot-product m-row n-col))  
                 n-cols)) 
          m))) 
  
 ;; But the inner map is just matrix-*-vector, so here's better: 
 (define (matrix-*-matrix m n) 
   (let ((n-cols (transpose n))) 
     (map (lambda (m-row) (matrix-*-vector n-cols m-row)) 
          m))) 
  
 ;; Test 
 (matrix-*-matrix matrix (list (list 1 2) (list 1 2) (list 1 2) (list 1 2)))