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.




(defun pascal-lower (n &aux (a (make-array (list n n) :initial-element 0)))
    (dotimes (i n)
        (setf (aref a i 0) 1))
    (dotimes (i (1- n) a)
        (dotimes (j (1- n))
            (setf (aref a (1+ i) (1+ j))
                (+ (aref a i j)
                   (aref a i (1+ j)))))))
 
(defun pascal-upper (n &aux (a (make-array (list n n) :initial-element 0)))
    (dotimes (i n)
        (setf (aref a 0 i) 1))
    (dotimes (i (1- n) a)
        (dotimes (j (1- n))
            (setf (aref a (1+ j) (1+ i))
                (+ (aref a j i)
                   (aref a (1+ j) i))))))
 
(defun pascal-symmetric (n &aux (a (make-array (list n n) :initial-element 0)))
    (dotimes (i n)
        (setf (aref a i 0) 1 (aref a 0 i) 1))
    (dotimes (i (1- n) a)
        (dotimes (j (1- n))
            (setf (aref a (1+ i) (1+ j))
                (+ (aref a (1+ i) j)
                   (aref a i (1+ j)))))))
 
? (pascal-lower 4)
#2A((1 0 0 0) (1 1 0 0) (1 2 1 0) (1 3 3 1))
? (pascal-upper 4)
#2A((1 1 1 1) (0 1 2 3) (0 0 1 3) (0 0 0 1))
? (pascal-symmetric 4)
#2A((1 1 1 1) (1 2 3 4) (1 3 6 10) (1 4 10 20))
 
;In case one really insists in printing the array row by row:
 
(defun print-matrix (a)
    (let ((p (array-dimension a 0))
          (q (array-dimension a 1)))
        (dotimes (i p)
            (dotimes (j q)
                (princ (aref a i j))
                (princ #\Space))
            (terpri))))
 
? (print-matrix (pascal-lower 5))
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
 
? (print-matrix (pascal-upper 5))
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
 
? (print-matrix (pascal-symmetric 5))
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