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.




func grow_matrix(matrix, callback) {
    var m = matrix
    var s = m.len
    m[s][0] = callback(0, m[s-1][0], 0)
    m[0][s] = callback(m[0][s-1], 0, 0)
    {|i| m[i+1][s] = callback(m[i+1][s-1], m[i][s], m[i][s-1])} * (s-1)
    {|i| m[s][i+1] = callback(m[s][i], m[s-1][i+1], m[s-1][i])} * (s)
    return m
}
 
func transpose(matrix) {
    matrix[0].range.map{|i| matrix.map{_[i]} }
}
 
func madd_n_nw(m) { grow_matrix(m, ->(_, n, nw) { n + nw }) }
func madd_w_nw(m) { grow_matrix(m, ->(w, _, nw) { w + nw }) }
func madd_w_n(m)  { grow_matrix(m, ->(w, n, _)  { w + n  }) }
 
var functions = [madd_n_nw, madd_w_nw, madd_w_n].map { |f|
    func(n) {
        var r = [[1]]
        { f(r) } * n
        transpose(r)
    }
}
 
functions.map { |f|
    f(4).map { .map{ '%2s' % _ }.join(' ') }.join("\n")
}.join("\n\n").say