Use lists as 2D matrix

Problem

Create matrix data structure and functions to operate on matrices.

Solution

(define (make-matrix n)
  (let outter ((i n) (result '()))
    (if (= i 0)
        result
        (outter (- i 1)
                (cons
                 (let inner ((j n) (row '()))
                   (if (= j 0)
                       row
                       (inner (- j 1) (cons (if (= i j) 1 0) row))))
                 result)))))

(define (nth list n)
  (let loop ((n n) (result list))
    (if (= n 0)
        (car result)
        (loop (- n 1)
              (cdr result)))))

(define matrix-row nth)

(define (matrix-col M n)
  (let loop ((i (length M)) (result '()))
    (if (= i 0)
        result
        (loop (- i 1)
              (cons (nth (nth M (- i 1)) n) result)))))

(define (matrix-mul N M)
  (let outter ((i (length N)) (result '()))
    (if (= i 0)
        result
        (outter (- i 1)
                (cons
                 (let inner ((j (length (car M))) (row '()))
                   (if (= j 0)
                       row
                       (inner
                        (- j 1)
                        (cons (reduce + (map *
                                             (matrix-row N (- i 1))
                                             (matrix-col M (- j 1))))
                              row))))
               result)))))

(define (reduce fun lst)
  (let loop ((result (car lst)) (lst (cdr lst)))
    (if (null? lst)
        result
        (loop (fun result (car lst)) (cdr lst)))))

(define (matrix-vector-mul v M)
  (car (matrix-mul (list v) M)))

(define (matrix-transpose M)
  (let loop ((M M) (result '()))
    (if (null? (car M))
        result
        (loop (map cdr M) (append result (list (map car M)))))))

(define (matrix-sum N M)
  (map (lambda (nrow mrow) (map + nrow mrow)) N M))

Credit: Jakub T. Jankiewicz (ref: Matrix manipulation in scheme)

Usage

(define M1 '((1 2 3) (2 3 4) (3 2 1)))
(define M2 (make-matrix 3))

(matrix-mul M1 M2)
;; ==> ((1 2 3) (2 3 4) (3 2 1))

(matrix-mul M1 '((2 3 1) (1 2 1) (1 3 1)))
;; ==> ((7 16 6) (11 24 9) (9 16 6))

(matrix-sum M1 M2)
;; ==> ((2 2 3) (2 4 4) (3 2 2))

(matrix-vector-mul '(2 3 1) M1)
;; ==> (11 15 19)

Back to the Scheme Cookbook