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 Data.List (transpose)
import System.Environment (getArgs)
import Text.Printf (printf)
 
-- Pascal's triangle.
pascal :: [[Int]]
pascal = iterate (\row -> 1 : zipWith (+) row (tail row) ++ [1]) [1]
 
-- The n by n Pascal lower triangular matrix.
pascLow :: Int -> [[Int]]
pascLow n = zipWith (\row i -> row ++ replicate (n-i) 0) (take n pascal) [1..]
 
-- The n by n Pascal upper triangular matrix.
pascUp :: Int -> [[Int]]
pascUp = transpose . pascLow
 
-- The n by n Pascal symmetric matrix.
pascSym :: Int -> [[Int]]
pascSym n = take n . map (take n) . transpose $ pascal
 
-- Format and print a matrix.
printMat :: String -> [[Int]] -> IO ()
printMat title mat = do
  putStrLn $ title ++ "\n"
  mapM_ (putStrLn . concatMap (printf " %2d")) mat
  putStrLn "\n"
 
main :: IO ()
main = do
  ns <- fmap (map read) getArgs
  case ns of
    [n] -> do printMat "Lower triangular" $ pascLow n
              printMat "Upper triangular" $ pascUp  n
              printMat "Symmetric"        $ pascSym n
    _   -> error "Usage: pascmat <number>"