Pascal matrix generation
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.
Showing truncated 5-by-5 matrices M[i, j] for i,j in range 0..4.
A Pascal upper-triangular matrix 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 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 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]]
The task is to write functions capable of generating each of the three forms of n-by-n matrices.<br? 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 upper-triangle matrix is the Identity matrix of the same size.
- The Cholesky decomposition of a Pascal symmetric matrix is the Pascal lower-triangle matrix of the same size.
J
<lang J> !/~ i. 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
!~/~ i. 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
(["0/!+/)~ i. 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</lang>
Explanation:
x!y is the number of ways of picking x balls (unordered) from a bag of y balls and x!/y for list x and list y gives a table where rows correspond to the elements of x and the columns correspond to the elements of y. Meanwhile !/~y is equivalent to y!/y (and i.y just counts the first y non-negative integers).
Also, x!~y is y!x (and the second example otherwise follows the same pattern as the first example.
For the final example we use an unadorned ! but prepare tables for its x and y values. Its right argument is a sum table, and its left argument is a left identity table. They look like this:
<lang J> (+/)~ i. 5 0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8
(["0/)~ i. 5
0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4</lang>
The parenthesis in these last two examples are redundant - they could have been omitted without changing the result, but were left in place for emphasis.
Python
Python: Summing adjacent values
<lang python>from pprint import pprint as pp
def pascal_upp(n):
s = [[0] * n for _ in range(n)] s[0] = [1] * n for i in range(1, n): for j in range(i, n): s[i][j] = s[i-1][j-1] + s[i][j-1] return s
def pascal_low(n):
# transpose of pascal_upp(n) return [list(x) for x in zip(*pascal_upp(n))]
def pascal_sym(n):
s = [[1] * n for _ in range(n)] for i in range(1, n): for j in range(1, n): s[i][j] = s[i-1][j] + s[i][j-1] return s
if __name__ == "__main__":
n = 5 print("\nUpper:") pp(pascal_upp(n)) print("\nLower:") pp(pascal_low(n)) print("\nSymmetric:") pp(pascal_sym(n))</lang>
- Output:
Upper: [[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]] Lower: [[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]] Symmetric: [[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]]
Python: Using a binomial coefficient generator function
<lang python>def binomialCoeff(n, k):
result = 1 for i in range(1, k+1): result = result * (n-i+1) // i return result
def pascal_upp(n):
return [[binomialCoeff(j, i) for j in range(n)] for i in range(n)]
def pascal_low(n):
return [[binomialCoeff(i, j) for j in range(n)] for i in range(n)]
def pascal_sym(n):
return [[binomialCoeff(i+j, i) for j in range(n)] for i in range(n)]</lang>
- Output:
(As above)