sicp-ex-2.37



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


yc

 (define (accumulate ops initial sequence) 
   (if (null? sequence) 
       initial 
       (ops (car sequence) 
           (accumulate ops initial (cdr sequence))))) 
  
 (define (accumulate-n op init seqs) 
   (if (null? (car seqs)) 
       () 
       (cons (accumulate op init (map car seqs)) 
             (accumulate-n op init (map cdr seqs))))) 
  
 (define (dot-product v w) 
   (accumulate + 0 (map * v w))) 
  
 (define (matrix-*-vector m v) 
   (map (lambda (w) 
          (dot-product v w)) m)) 
  
 (define (transpose m) 
   (accumulate-n cons () m)) 
  
 (define (matrix-*-matrix m n) 
   (let ((cols (transpose n))) 
     (map (lambda (v) (matrix-*-vector cols v)) m))) 

jz

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

  
 ;; 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))) 
  

intarga

Mine looks similar to jz's, but I'm posting with evaluation commented after the expressions, so people can double check their solutions.

 (define my-matrix (list (list 1 2 3 4) 
                         (list 4 5 6 6) 
                         (list 6 7 8 9))) 
  
 (define (dot-product v w) 
   (accumulate + 0 (map * v w))) 
  
 (dot-product (car my-matrix) 
              (car (cdr my-matrix))) ; 56 
  
 (define (matrix-*-vector m v) 
   (map (lambda (mi) (dot-product mi v)) m)) 
  
 (matrix-*-vector my-matrix (car my-matrix)) ; (30 56 80) 
  
 (define (transpose m) 
   (accumulate-n cons '() m)) 
  
 (transpose my-matrix) ; ((1 4 6) (2 5 7) (3 6 8) (4 6 9)) 
  
 (define (matrix-*-matrix m n) 
   (let ((cols (transpose n))) 
     (map (lambda (mi) 
            (map (lambda (nj) 
                   (dot-product mi nj)) 
                 cols)) 
          m))) 
  
 (matrix-*-matrix my-matrix (transpose my-matrix)) ; ((30 56 80) (56 113 161) (80 161 230)) 
 (matrix-*-matrix (list (list 1 2) 
                        (list 3 4)) 
                  (list (list 1 2) 
                        (list 3 4))) ; ((7 10) (15 22)) 

The implementation is same as jz's but with the different tests.