Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
pp:l04 [2023/03/16 13:46]
alexia.ciuclea
pp:l04 [2023/03/22 18:54] (current)
mihai.udubasa old revision restored (2021/03/28 20:51)
Line 1: Line 1:
-====== ​3Lists in Scala ======+====== ​4Working with matrices and images using higher-order functions ​======
  
-Objectives:​ +===== 1. Introduction =====
-  * get familiar with **pattern matching** lists, as well as common list operations from Scala and how they work +
-  * get familiar with common **higher-order functions** over lists (partition, map, foldRight, foldLeft, filter)+
  
-===== 3.1 Common ​list operations =====+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
  
-**3.1.1.** Write a function which returns true if list of integers has at least k elementsUse patterns+$math[ \displaystyle \left(\begin{array}{ccc} 1 & 2 & \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \end{array}\right)]  
-Write a second function that returns true if a list of integers has at least k elements that satisfy a predicate. + 
-<code scala> +will be represented by the list ''​[ [1,​2,​3],​[4,​5,​6],​[7,​8,​9] ]''​. 
-def atLeastk(kInt, lList[Int]): Boolean = + 
-  if (k == 0) ??? +To make signatures more legible, add the //type alias// to your code: 
-  else ??? +<code haskell> type Matrix = [[Integer]] </​code>​ 
-  } +which makes the type-name ''​Matrix''​ stand for ''​[ [Integer] ]''​. 
-   + 
-def atLeastkPred(predInt => Boolean)(kInt, l: List[Int]): Boolean ​???+1.1. Write a function ​''​parsem'' ​which takes string and parses it to a ''​Matrix''​In the string, the columns are separated by whitespace and lines - by '​\n'​.  
 +     * (HintYou need to perform two types of very similar splitting operationsone into lines, and another into column values, for each line
 + 
 +<code haskell> 
 +parsem ​:: String -> Matrix 
 +parsem ​
 </​code>​ </​code>​
  
-**3.1.2.** Write a function ​which returns ​the first ''​n'' ​elements from given list. The function ​should not be implemented as tail-recursive. +1.2. Write a function ​that converts a matrix to a string encoded as illustrated in the previous exercise.  
-<​code ​scala+     * (Hint: use folds) 
-def take(nInt, lList[Int]): List[Int] = ??? +     * (Hint: test the function ​''​show'' ​on several different values) 
-//​take(3,​List(1,​2,​3,​4,​5)) ​List(1,2,3)+     * (Hint: first make a function ​to display one line) 
 + 
 +<​code ​haskell
 +toString:: Matrix -> String 
 +toString
 </​code>​ </​code>​
  
-**3.1.3.** Write a function ​which //drops// the first ''​n'' ​elements from a given list. The function should not be implemented as tail-recursive+1.3. Add the following to your code. Test the function ''​displayMatrix''​. 
-<​code ​scala+<​code ​haskell
-def drop(n: Int, l: List[Int]): List[Int] ​??? +displayMatrix ​putStrLn . toString
-//​drop(3,​List(1,​2,​3,​4,​5)) = List(4,5)+
 </​code>​ </​code>​
  
-**3.1.4.** Write a function ​which takes a predicate ''​pInt => Boolean'',​ a list ''​l''​ and returns a sublist of ''​l''​ containing those elements for which ''​p''​ is true. The function should be **curried**. +===== 2. Matrix operations ===== 
-<code scala> + 
-def takeP(p: Int => Boolean)(l: List[Int]): List[Int] = ??? +2.1. Write a function ​that computes the scalar product with an integer
-//takeP(_%== 0)(List(1,2,3,4,5,6)) = List(2,4,6)+ 
 +$math\displaystyle ​* \left(\begin{array}{ccc} ​\\ \\ 7 & 8 & 9 \\ \end{array}\right) = \left(\begin{array}{ccc} ​\\ 8 & 10 & 12 \\ 14 & 16 & 18 \\ \end{array}\right)]  
 + 
 +<code haskell>​ 
 +vprod :: Integer -> Matrix -> Matrix 
 +vprod v = 
 </​code>​ </​code>​
  
-**3.1.5.** Write a function which uses a predicate to partition (split) a list. +2.2. Write a function which adjoins two matrices by extending rows: 
-<code scala> + 
-def part(p: Int => Boolean)(l: List[Int]): (List[Int], List[Int]) = ??? +$math\displaystyle \left(\begin{array}{cc} ​\\ 4\\\end{array}\right) ​ hjoin \left(\begin{array}{cc} ​\\ 7 & 8\\\end{array}\right) = \left(\begin{array}{cc} 1 & & 5 & \\ & 4 & 7 & 8\\\end{array}\right
-// part(_%2 == 0)(List(1,2,3,4,5,6)) = (List(2,4,6),List(1,3,5))+ 
 +<code haskell>​ 
 +hjoin :: Matrix -> Matrix -> Matrix 
 +hjoin = 
 </​code>​ </​code>​
  
-**3.1.6** Write a function ​that returns the max value from a list. ''​ Use foldRight''​. +2.3. Write a function ​which adjoins two matrices by adding new rows: 
-<​code ​scala+ 
-def maxList(lList[Int])Int ???+$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>​ </​code>​
  
-**3.1.7** Reverse ​list using folds+2.4Write function which adds two matrices. 
-<​code ​scala+ 
-def reverseList(lList[Int])List[Int] ​???+<​code ​haskell
 +msum :: Matrix -> Matrix -> Matrix 
 +msum 
 </​code>​ </​code>​
  
-==== 3.2 Gradebooks ==== +2.5. Write a function which computes the transposition ​of a matrix
-More general implementation ​of ''​take'',​ ''​drop''​ and ''​part''​ are already implemented in Scala and can be used as member functions of lists. Examples are shown below+ 
-<code scala> +$math[ tr \left(\begin{array}{ccc} ​\\ \\ \\ \end{array}\right= \left(\begin{array}{ccc} 1 & 4 & 7 \\ 2 & 5 & 8 \\ & 6 & 9 \\ \end{array}\right] 
-val l = List(1,2,3,4,5,6,7,8,9) + 
-l.take(3) +<code haskell>​ 
-l.drop(3) +tr :: [[a]] -> [[a]] 
-l.partition(_%2 == 0)+tr ([]:_= 
 +tr m =
 </​code>​ </​code>​
  
-In what follows, we shall encode a gradebook as list of pairs ''​(<​name>,<​grade>​)'',​ where ''<​name>''​ is String ​and ''<​grade>''​ is an Int. Example: +2.6. Write function which computes the vectorial product ​of two matrices. 
-<code scala> +  * (Hint: start by writing ​function which computes $math[a_{ij}] for a given line $math[i] ​and column $math[j] ​(both represented as lists)) 
-val gradebook = List(("​G",​3), ("​F",​ 10)("​M",​6), ("​P",​4)) +  * (Hint: write a function which takes a line of matrix m1 and the matrix m2 and computes the respective line from the product)
-</​code> ​+
  
-To make the type signatures more legible, we can introduce type aliases in Scala: +<​code ​haskell>​ 
-<​code ​scala+mprod :: Matrix -> Matrix -Matrix 
-type Gradebook ​List[(String,​Int)] //the type Gradebook now refers to a list of pairs of String and Int+mprod m1 m2 
 </​code>​ </​code>​
-Add this type alias to your code before solving the following exercises. 
  
-**3.2.1.** Write function which adds one point  to all students which have passing grade (>= 5)and leaves all other grades unchanged+===== 3. Image operations ===== 
-<​code ​scala+ 
-def increment(gGradebook): Gradebook = +We can represent images as matrices of pixelsIn our example ​pixel will be represented as ''​Char'',​ which can take the values: '​*' ​(signifying that the respective pixel is //on//) and ' ' (the pixel is off) 
-  ​g.map(???​) ​+ 
 +<​code ​haskell> type Image = [String] </code
 + 
 +For instance, a rectangle could be represented as
 + 
 +<​code>​ 
 +******** 
 +*      * 
 +********
 </​code>​ </​code>​
  
-**3.2.2.** Find the average grade from a gradebook. You must use ''​foldRight''​. +more precisely, as the string: ​ 
-<​code ​scala+<​code ​haskell
-def average(g: Gradebook): Double = ???+"​********\n* ​     *\n********\n"​
 </​code>​ </​code>​
  
-**3.2.3.** Write a function ​which takes a gradebook and returns the percentage of failed vspassed students, ​as a pair (x,y)+3.1Implement an image-displaying ​function. ​Use the image from the Appendix ​as a test
-<​code ​scala+<​code ​haskell
-def percentage(gGradebook)(Double,​Double) ​???+toStringImg ​:: Image -> String 
 +toStringImg ​ 
 </​code>​ </​code>​
  
-**3.2.4.** Write a function ​which takes gradebook and returns the list of names which have passed. Use filter and map from Scala. +Add the following ​function ​in order to view images in nicer format: 
-<​code ​scala+<​code ​haskell
-def pass(g: Gradebook): List[String] ​???+displayImg ​putStrLn . toStringImg
 </​code>​ </​code>​
  
-**3.2.5.(!)** ​Implement ​merge-sort (in ascending order) over gradebooks+3.2. Implement ​a function which flips an image horizontally
-<​code ​scala+<​code ​haskell
-def mergeSort(lGradebook)Gradebook = { +flipH :: Image -> Image  
-   def merge(u: Gradebook, v: Gradebook): Gradebook ​??? +flipH 
-   ??? +
-}+
 </​code>​ </​code>​
  
-**3.2.6.(!)** Write a function which takes a gradebook and reports all passing students in **descending** order of their grade. +3.3Implement ​a function which flips an image vertically: 
-<​code ​scala+<​code ​haskell
-def honorsList(gGradebook)List[String] ​???+flipV :: Image -> Image 
 +flipV 
 </​code>​ </​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>​
 +
 +