4. Working with matrices and images using higher-order functions

We shall represent matrices as lists of lists, i.e. values of type [ [Integer ] ]. Each element in the outer list represents a line of the matrix. Hence, the matrix

$ \displaystyle \left(\begin{array}{ccc} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{array}\right)$

will be represented by the list [ [1,2,3],[4,5,6],[7,8,9] ].

To make signatures more legible, add the type alias to your code:

 type Matrix = [[Integer]] 

which makes the type-name Matrix stand for [ [Integer] ].

1.1. Write a function parsem which takes a string and parses it to a Matrix. In the string, the columns are separated by whitespace and lines - by '\n'.

  • (Hint: You need to perform two types of very similar splitting operations: one into lines, and another into column values, for each line)
parsem :: String -> Matrix
parsem = 

1.2. Write a function that converts a matrix to a string encoded as illustrated in the previous exercise.

  • (Hint: use folds)
  • (Hint: test the function show on several different values)
  • (Hint: first make a function to display one line)
toString:: Matrix -> String
toString= 

1.3. Add the following to your code. Test the function displayMatrix.

displayMatrix = putStrLn . toString

2.1. Write a function that computes the scalar product with an integer:

$ \displaystyle 2 * \left(\begin{array}{ccc} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{array}\right) = \left(\begin{array}{ccc} 2 & 4 & 6 \\ 8 & 10 & 12 \\ 14 & 16 & 18 \\ \end{array}\right)$

vprod :: Integer -> Matrix -> Matrix
vprod v = 

2.2. Write a function which adjoins two matrices by extending rows:

$ \displaystyle \left(\begin{array}{cc} 1 & 2 \\ 3 & 4\\\end{array}\right) hjoin \left(\begin{array}{cc} 5 & 6 \\ 7 & 8\\\end{array}\right) = \left(\begin{array}{cc} 1 & 2 & 5 & 6 \\ 3 & 4 & 7 & 8\\\end{array}\right) $

hjoin :: Matrix -> Matrix -> Matrix
hjoin = 

2.3. Write a function which adjoins two matrices by adding new rows:

$ \displaystyle \left(\begin{array}{cc} 1 & 2 \\ 3 & 4\\\end{array}\right) vjoin \left(\begin{array}{cc} 5 & 6 \\ 7 & 8\\\end{array}\right) = \left(\begin{array}{cc} 1 & 2 \\ 3 & 4 \\ 5 & 6\\ 7 & 8\\ \end{array}\right) $

vjoin :: Matrix -> Matrix -> Matrix
vjoin = 

2.4. Write a function which adds two matrices.

msum :: Matrix -> Matrix -> Matrix
msum = 

2.5. Write a function which computes the transposition of a matrix:

$ tr \left(\begin{array}{ccc} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{array}\right) = \left(\begin{array}{ccc} 1 & 4 & 7 \\ 2 & 5 & 8 \\ 3 & 6 & 9 \\ \end{array}\right) $

tr :: [[a]] -> [[a]]
tr ([]:_) =
tr m =

2.6. Write a function which computes the vectorial product of two matrices.

  • (Hint: start by writing a function which computes $ a_{ij}$ for a given line $ i$ and column $ j$ (both represented as lists))
  • (Hint: write a function which takes a line of matrix m1 and the matrix m2 and computes the respective line from the product)
mprod :: Matrix -> Matrix -> Matrix
mprod m1 m2 = 

We can represent images as matrices of pixels. In our example a pixel will be represented as a Char, which can take the values: '*' (signifying that the respective pixel is on) and ' ' (the pixel is off).

 type Image = [String] 

For instance, a rectangle could be represented as:

********
*      *
********

more precisely, as the string:

"********\n*      *\n********\n"

3.1. Implement an image-displaying function. Use the image from the Appendix as a test.

toStringImg :: Image -> String
toStringImg =

Add the following function in order to view images in a nicer format:

displayImg = putStrLn . toStringImg

3.2. Implement a function which flips an image horizontally:

flipH :: Image -> Image 
flipH = 

3.3. Implement a function which flips an image vertically:

flipV :: Image -> Image
flipV = 

3.4. Implement a function which rotates an image 90grd clockwise

rotate90r :: Image -> Image
rotate90r =

3.5. Implement a function which rotates an image -90grd clockwise

rotate90l :: Image -> Image
rotate90l = 

3.6. Implement a function which inverts an image: ' ' becomes * and * becomes ' ':

invert :: Image -> Image
invert = 

3.7. Implement a function maskKeep which takes a mask and some image and only keeps the part of image which overlays the mask. Use the mask and the logo from Appendix to test it.

maskKeep :: Image -> Image -> Image
maskKeep = 

$ maskKeep \left(\begin{array}{ccc} & & * \\ & & * \\ & & * \\ \end{array}\right) \left(\begin{array}{ccc} * & & * \\ * & & \\ * & & * \\ \end{array}\right) = \left(\begin{array}{ccc} & & * \\ & & \\ & & * \\ \end{array}\right) $

3.8. Implement a function maskDiscard which takes a mask and some image and discards the part of the mask which overlays the image.

$ maskDiscard\left(\begin{array}{ccc} & & * \\ & & * \\ & & * \\ \end{array}\right) \left(\begin{array}{ccc} * & & * \\ * & & \\ * & & * \\ \end{array}\right) = \left(\begin{array}{ccc} & & \\ & & * \\ & & \\ \end{array}\right) $

3.9. Implement the union' of two images.

union' :: Image -> Image -> Image
union' = 

$ union \left(\begin{array}{ccc} & & * \\ & & * \\ & & * \\ \end{array}\right) \left(\begin{array}{ccc} * & & * \\ * & & \\ * & & * \\ \end{array}\right) = \left(\begin{array}{ccc} * & & * \\ * & & * \\ * & & * \\ \end{array}\right) $

3.10. Implement a function which takes a list of transformation and an image and applies all those transformations.

transformationSequence :: [Image -> Image] -> Image -> Image

Test it with the following sequence

seq1 = transformationSequence [invert, union' mask, rotate90r]

4.1. Implement a function which places zeros above the diagonal of a square matrix. Use folds.

4.2. Implement a function which places zeros below the diagonal of a square matrix. Use folds.

4.3. Implement either of 4.1 or 4.2 using the function(s) take and drop. Check the types of these and test them.

4.4. Implement a function which computes the diagonal matrix of a square matrix.

4.5. Implement a function which computes recursively the determinant of a matrix. What additional functions would be necessary?

logo = [l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,l15,l16,l17,l18,l19]
    where l1 ="        ***** **            ***** **    "
          l2 ="     ******  ****        ******  ****   "
          l3 ="    **   *  *  ***      **   *  *  ***  "
          l4 ="   *    *  *    ***    *    *  *    *** "
          l5 ="       *  *      **        *  *      ** "
          l6 ="      ** **      **       ** **      ** "
          l7 ="      ** **      **       ** **      ** "
          l8 ="    **** **      *      **** **      *  "
          l9 ="   * *** **     *      * *** **     *   "
          l10="      ** *******          ** *******    "
          l11="      ** ******           ** ******     "
          l12="      ** **               ** **         "
          l13="      ** **               ** **         "
          l14="      ** **               ** **         "
          l15=" **   ** **          **   ** **         "
          l16="***   *  *          ***   *  *          "
          l17=" ***    *            ***    *           "
          l18="  ******              ******            "
          l19="    ***                 ***             "
mask = [l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,l15,l16,l17,l18,l19]
    where l1 ="                       *****************"
          l2 ="                       *****************"
          l3 ="                       *****************"
          l4 ="                       *****************"
          l5 ="                       *****************"
          l6 ="                       *****************"
          l7 ="                       *****************"
          l8 ="                       *****************"
          l9 ="                       *****************"
          l10="                       *****************"
          l11="                       *****************"
          l12="                       *****************"
          l13="                       *****************"
          l14="                       *****************"
          l15="                       *****************"
          l16="                       *****************"
          l17="                       *****************"
          l18="                       *****************"
          l19="                       *****************"