Edit this page Backlinks This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ====== 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: <code haskell> type Matrix = [[Integer]] </code> 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) <code haskell> parsem :: String -> Matrix parsem = </code> 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) <code haskell> toString:: Matrix -> String toString= </code> 1.3. Add the following to your code. Test the function ''displayMatrix''. <code haskell> displayMatrix = putStrLn . toString </code> ===== 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)] <code haskell> vprod :: Integer -> Matrix -> Matrix vprod v = </code> 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) ] <code haskell> hjoin :: Matrix -> Matrix -> Matrix hjoin = </code> 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) ] <code haskell> vjoin :: Matrix -> Matrix -> Matrix vjoin = </code> 2.4. Write a function which adds two matrices. <code haskell> msum :: Matrix -> Matrix -> Matrix msum = </code> 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) ] <code haskell> tr :: [[a]] -> [[a]] tr ([]:_) = tr m = </code> 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) <code haskell> mprod :: Matrix -> Matrix -> Matrix mprod m1 m2 = </code> ===== 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). <code haskell> type Image = [String] </code> For instance, a rectangle could be represented as: <code> ******** * * ******** </code> more precisely, as the string: <code haskell> "********\n* *\n********\n" </code> 3.1. Implement an image-displaying function. Use the image from the Appendix as a test. <code haskell> toStringImg :: Image -> String toStringImg = </code> Add the following function in order to view images in a nicer format: <code haskell> displayImg = putStrLn . toStringImg </code> 3.2. Implement a function which flips an image horizontally: <code haskell> flipH :: Image -> Image flipH = </code> 3.3. Implement a function which flips an image vertically: <code haskell> flipV :: Image -> Image flipV = </code> 3.4. Implement a function which rotates an image 90grd clockwise <code haskell> rotate90r :: Image -> Image rotate90r = </code> 3.5. Implement a function which rotates an image -90grd clockwise <code haskell> rotate90l :: Image -> Image rotate90l = </code> 3.6. Implement a function which inverts an image: ' ' becomes * and * becomes ' ': <code haskell> invert :: Image -> Image invert = </code> 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. <code haskell> maskKeep :: Image -> Image -> Image maskKeep = </code> $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. <code haskell> union' :: Image -> Image -> Image union' = </code> $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. <code haskell> transformationSequence :: [Image -> Image] -> Image -> Image </code> Test it with the following sequence <code haskell> seq1 = transformationSequence [invert, union' mask, rotate90r] </code> ===== 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 ===== <code haskell> 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=" *** *** " </code> <code haskell> 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=" *****************" </code>