====== 4. Working with matrices and images using higher-order functions ======
===== 1. Introduction =====
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
$math[ \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. Matrix operations =====
2.1. Write a function that computes the scalar product with an integer:
$math[ \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:
$math[ \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:
$math[ \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:
$math[ 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 $math[a_{ij}] for a given line $math[i] and column $math[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 =
===== 3. Image operations =====
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 =
$math[ 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.
$math[ 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' =
$math[ 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. More matrices =====
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?
===== Appendix =====
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=" *****************"