A pascal matrix is a two-dimensional square matrix holding numbers from   Pascal's triangle,   also known as   binomial coefficients   and which can be shown as   nCr.

Shown below are truncated   5-by-5   matrices   M[i, j]   for   i,j   in range   0..4. 


A Pascal upper-triangular matrix that is populated with   jCi:

[[1, 1, 1, 1, 1],
 [0, 1, 2, 3, 4],
 [0, 0, 1, 3, 6],
 [0, 0, 0, 1, 4],
 [0, 0, 0, 0, 1]]

A Pascal lower-triangular matrix that is populated with   iCj   (the transpose of the upper-triangular matrix):

[[1, 0, 0, 0, 0],
 [1, 1, 0, 0, 0],
 [1, 2, 1, 0, 0],
 [1, 3, 3, 1, 0],
 [1, 4, 6, 4, 1]]

A Pascal symmetric matrix that is populated with   i+jCi:

[[1, 1, 1, 1, 1],
 [1, 2, 3, 4, 5],
 [1, 3, 6, 10, 15],
 [1, 4, 10, 20, 35],
 [1, 5, 15, 35, 70]]



Task

Write functions capable of generating each of the three forms of   n-by-n   matrices.

Use those functions to display upper, lower, and symmetric Pascal   5-by-5   matrices on this page.

The output should distinguish between different matrices and the rows of each matrix   (no showing a list of 25 numbers assuming the reader should split it into rows).



Note
 
The   Cholesky decomposition   of a Pascal symmetric matrix is the Pascal lower-triangle matrix of the same size.




(import (srfi 25))
 
(define-syntax dotimes 
  (syntax-rules ()
    ((_ (i n) body ...)
     (do ((i 0 (+ i 1)))
         ((>= i n))
       body ...))))
 
 
(define (pascal-upper n)
  (let ((p (make-array (shape 0 n 0 n) 0)))
    (dotimes (i n)
      (array-set! p 0 i 1))
     (dotimes (i (- n 1))
       (dotimes (j (- n 1))
         (array-set! p (+ 1 i) (+ 1 j)
                     (+ (array-ref p i j)
                        (array-ref p (+ 1 i) j)))))
     p))
 
(define (pascal-lower n)
  (let ((p (make-array (shape 0 n 0 n) 0)))
    (dotimes (i n)
      (array-set! p i 0 1))
     (dotimes (i (- n 1))
       (dotimes (j (- n 1))
         (array-set! p (+ 1 i) (+ 1 j)
                     (+ (array-ref p i j)
                        (array-ref p i (+ 1 j))))))
     p))
(define (pascal-symmetric n)
  (let ((p (make-array (shape 0 n 0 n) 0)))
    (dotimes (i n)
      (array-set! p i 0 1)
      (array-set! p 0 i 1))
     (dotimes (i (- n 1))
       (dotimes (j (- n 1))
         (array-set! p (+ 1 i) (+ 1 j)
                     (+ (array-ref p (+ 1 i) j)
                        (array-ref p i (+ 1 j))))))
     p))
 
 
(define (print-array a)
  (let ((r (array-end a 0))
        (c (array-end a 1)))
    (dotimes (row (- r 1))
      (dotimes (col (- c 1))
        (display (array-ref a row col))
        (display #\space))
      (newline))))