; zeroing a matrix

(define (make-matrix rows columns . value)
  (do ((m (make-vector rows)) (i 0 (+ i 1)))
      ((= i rows) m)
    (if (null? value)
        (vector-set! m i (make-vector columns))
        (vector-set! m i (make-vector columns (car value))))))

(define (matrix-rows x) (vector-length x))

(define (matrix-cols x) (vector-length (vector-ref x 0)))

(define (matrix-ref m i j) (vector-ref (vector-ref m i) j))

(define (matrix-set! m i j x) (vector-set! (vector-ref m i) j x))

(define-syntax for
  (syntax-rules ()
    ((for (var first past step) body ...)
      (let ((ge? (if (< first past) >= <=)))
        (do ((var first (+ var step)))
            ((ge? var past))
          body ...)))
    ((for (var first past) body ...)
      (let* ((f first) (p past) (s (if (< first past) 1 -1)))
        (for (var f p s) body ...)))
    ((for (var past) body ...)
      (let* ((p past)) (for (var 0 p) body ...)))))

(define (adjoin x xs)
  (if (member x xs) xs
    (cons x xs)))

(define (zero mtrx)
  (let ((rows (list)) (cols (list))
        (n-rows (matrix-rows mtrx))
        (n-cols (matrix-cols mtrx)))
    (for (row 0 n-rows)
      (for (col 0 n-cols)
        (when (zero? (matrix-ref mtrx row col))
          (set! rows (adjoin row rows))
          (set! cols (adjoin col cols)))))
    (do ((rows rows (cdr rows))) ((null? rows))
      (for (col 0 n-cols)
        (matrix-set! mtrx (car rows) col 0)))
    (do ((cols cols (cdr cols))) ((null? cols))
      (for (row 0 n-rows)
        (matrix-set! mtrx row (car cols) 0)))
    mtrx))

(display (zero '#(#(0 2 3 4 5)
                  #(1 0 3 4 5)
                  #(1 2 0 4 5)
                  #(1 2 3 0 5)
                  #(1 2 3 4 0))))