This is an old revision of the document!


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. 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 = 

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)
toString :: Matrix -> String
toString = 

3. Add the following to your code. Test the function displaymat.

displaymat = putStrLn . toString

4. 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} 1 & 4 & 6 \\ 8 & 10 & 12 \\ 14 & 16 & 18 \\ \end{array}\right)$

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

5. 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 = 

6. 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 = 

7. Write a function which adds two matrices.

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

8. 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 & 6 \\ 2 & 5 & 8 \\ 3 & 6 & 9 \\ \end{array}\right) $

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

9. 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"

10. Implement an image-displaying function:

toStringImg :: Image -> String
toStringImg =

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

displaym = putStrLn . toStringImg

11. Implement a function which flips an image horizontally:

flipH :: Image -> Image 
flipH = 

12. Implement a function which flips an image vertically:

flipV :: Image -> Image
flipV = 

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

rotate90r :: Image -> Image
rotate90r =

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

rotate90l :: Image -> Image
rotate90l = 

15. Implement a function which returns a diamond of a specified height. Example:

                          *
                         ***
   diamond 3 =          *****
                         ***
                          *

                         *
   diamond 2 =          ***
                         *
diamond :: Integer -> Image 

16. Implement a function with takes two images with the same dimensions. The second image is a mask. The output will be another image in which all pixels from the first image overlaying with a '*'-pixel from the mask will be displayed. All others will be deleted (made equal to ' '). Example:

  
   
   ******                ****     ****
   **  **   0111verlay0032  ******   **  ** 
   **  **                ****     *  *
   ******                 **       **
overlay :: Image -> Image -> Image
l1="        ***** **            ***** **    "
l2="     ******  ****        ******  ****   "
l3="    **   *  *  ***      **   *  *  ***  "
l4="   *    *  *    ***    *    *  *    *** "
l5="       *  *      **        *  *      ** "
l6="      ** **      **       ** **      ** "
l7="      ** **      **       ** **      ** "
l8="    **** **      *      **** **      *  "
l9="   * *** **     *      * *** **     *   "
l10="      ** *******          ** *******    "
l11="      ** ******           ** ******     "
l12="      ** **               ** **         "
l13="      ** **               ** **         "
l14="      ** **               ** **         "
l15=" **   ** **          **   ** **         "
l16="***   *  *          ***   *  *          "
l17=" ***    *            ***    *           "
l18="  ******              ******            "
l19="    ***                 ***             "
 
logo = [l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,l15,l16,l17,l18,l19]