Differences

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

Link to this comparison view

Next revision
Previous revision
fp2025:lab03 [2025/03/03 00:20]
cata_chiru created
fp2025:lab03 [2025/03/12 15:40] (current)
pdmatei
Line 1: Line 1:
-====== Lab 3. Lists in Scala ======+====== Lab 3. Higher-order functions ​======
  
 Objectives: Objectives:
-  * get familiar with **pattern matching** lists, as well as common list operations from Scala and how they work +  * implement and use **higher-order** functions. A **higher-order** function takes other functions ​as parameter or returns them 
-  * get familiar with common ​**higher-order functions** ​over lists (partitionmap, foldRight, foldLeft, filter)+  ​implement ​**curry** and **uncurry** functionsand how they should be properly used (review lecture).
  
-==== 3.1. Common list operations ====+**3.1.** Define the function ''​foldWith''​ which uses an operation ''​op'',​ and an initial value ''​b''​ to reduce a range of integers to a value. For instance, given that ''​op''​ is addition (+), the result of folding the range 1 to 3 with ''​b ​0''​ will be ''​( ( 0 + 1 ) + 2 + 3 6''​. ''​foldWith''​ should be **curried** (it will take the operation and return another function which expects the bounds).
  
-**3.1.1.** Write a function which returns true if a list of integers has at least ''​k''​ elements. Use **patterns**. Write a second function which returns ''​true''​ if the list has at least ''​k''​ elements that satisfy a predicate. 
 <code scala> <code scala>
-def atLeastk(k: Int, lList[Int]): Boolean ​= { +def foldWith ​(bInt)(op: (Int,Int) => Int)(start: Int, stop: Int): Int = { 
-  ​if (k == 0) ??? +  ​def tail_fold(crt: Int, acc: Int): Int  = ??? 
-  ​else ???+  ??
 } }
-  ​ 
-def atLeastkPred(pred:​ Int => Boolean)(k: Int, l: List[Int]): Boolean = ??? 
 </​code>​ </​code>​
  
-**3.1.2.** Write a function which returns the first ''​n'' ​elements from given listThe function should **not** be implemented as tail-recursive.+**3.2.** ​Define the function ​''​foldConditional'' ​which extends ​''​foldWith'' ​by also adding ​predicate ''​p:​ Int => Int''​''​foldConditional''​ will reduce only those elements of a range which satisfy the predicate.
  
 <code scala> <code scala>
-def take(n: Int, lList[Int]): List[Int??? +def foldConditional(b: Int)(op(Int,Int) => Int, p: Int => Boolean)(start: Intstop: Int): Int = ???
-//​take(3,​List(1,​2,​3,​4,​5)) = List(1,2,3)+
 </​code>​ </​code>​
  
-**3.1.3.** Write a function which //​drops// ​the first ''​n'' ​elements from a given list.+**3.3.** ​Implement the function ​''​foldRight'' ​which has the same behaviour as ''​foldWith'',​ but the order in which the operation is performed is now: ''​1+(2+(3+0))=6''​. ​What is the simplest way to implement it?
  
-<code scala> 
-def drop(n: Int, l: List[Int]): List[Int] = ??? 
-//​drop(3,​List(1,​2,​3,​4,​5)) = List(4,5) 
-</​code>​ 
- 
-**3.1.4.** Write a function which takes a predicate ''​p:​ Int => Boolean'',​ a list ''​l''​ and returns a sublist of ''​l''​ containing those elements for which ''​p''​ is true. The function should be **curried**. 
  
 +**3.4.** Write a function ''​foldMap''​ which takes values $math[a_1, a_2, \ldots, a_k] from a range and computes $math[f(a_1)\;​op\;​f(a_2)\;​op\;​\ldots \;​op\;​f(a_k)].
 <code scala> <code scala>
-def takeP(p: Int => Boolean)(lList[Int]): List[Int= ??? +def foldMap(op(Int,Int=> Int, f: Int => Int)(start: Int, stop: Int): Int = ???
-//takeP(_%2 == 0)(List(1,​2,​3,​4,​5,​6)) = List(2,4,6)+
 </​code>​ </​code>​
  
-**3.1.5.** Write a function which uses a predicate to partition ​(splita list.+**3.5.** Write a function which computes $math[1 + 2^2 + 3^2 + \ldots + (n-1)^2 + n^2] using ''​foldMap''​.
 <code scala> <code scala>
-def part(p: Int => Boolean)(lList[Int]): (List[Int], List[Int]) ​= ??? +def sumSquares(n: Int): Int = ???
-// part(_%2 == 0)(List(1,​2,​3,​4,​5,​6)) = (List(2,​4,​6),​List(1,​3,​5))+
 </​code>​ </​code>​
  
-**3.1.6.** Write a function ​that reverses the elements of list. Use ''​fold'' ​function (determine if it should be right or left).+**3.6.** Write a function ​''​hasDivisor''​ which checks if range contains a multiple of k. Use ''​foldMap'' ​and choose ''​f''​ carefully.
 <code scala> <code scala>
-def rev(lList[Int]): List[Int] ​= ??? +def hasDivisor(k: Int, start: Int, stop: Int): Boolean ​= ???
-// rev(List(1,​2,​3,​4,​5,​6)) = List(6,​5,​4,​3,​2,​1)+
 </​code>​ </​code>​
  
-==== 3.2String processing ==== +**3.7.** We can compute the sum of an area defined by a function within a range a,b (the integral of that function given the range), using the following recursive scheme: 
- +  * if the range is small enough, we treat f as line (and the area as a trapeze). It's area is $math[(f(a) + f(b))(b-a)/​2]. 
-In what follows, we shall encode ​String ​as a list of charactersusing the type defined below:+  * otherwise, we compute the mid of the rangewe recursively compute ​the integral from a to mid and from mid to b, and add-up the result.
  
 +Implement the function ''​integrate''​ which computes the integral of a function f given a range:
 <code scala> <code scala>
-type Str List[Char]+def integrate(f:​ Double ​=> Double)(start:​ Double, stop: Double): Double = ???
 </​code>​ </​code>​
-Add this type alias to your code before solving the following exercises. 
  
-The following is an input testYou can add more examples ​to it:+**3.8.** We define ''​Line2D'' ​to be lines in a 2-dimensional space, and we represent them as functions. Write a function which takes a Line2D and translates ​it up on the Ox axis by a given offset. For instance, translateOx of 2 on y=x+1 will return y=x+3.
 <code scala> <code scala>
-val l: List[Str] ​List("​matei@gmail.com",​ "​mihai@gmail.com",​ "​tEst@mail.com",​ "​email@email.com",​ "​short@ax.ro"​).map(x => x.toList)+type Line2D ​Int => Int 
 +def translateOx(offset: Int)(l: Line2D): Line2D = ???
 </​code>​ </​code>​
  
-Use ''​map'',​ ''​foldr''/''​foldl'',​ instead of recursive functions. +**3.9.** (!Write a function which takes a Line2D and translates it up on the Oy axis by a given offset.
- +
-**3.2.1.** Remove uppercases from emails. ​(Do **not** use recursion). Use the Internet to find the appropriate character function. +
 <code scala> <code scala>
-def remUpper(listList[Str]): List[Str] ​= ???+def translateOy(offsetInt)(l: Line2D): Line2D ​= ???
 </​code>​ </​code>​
  
-**3.2.2.** Write a function which removes emails longer than a given size. Try to think of two ways to implement this using already defined functions (do not define your own auxiliary functions). +**3.10.** Write a function which takes two lines, and checks if there exist integer coordinates within ​a given range for x, where the lines intersect.
 <code scala> <code scala>
-def longer(kIntlistList[Str]): List[Str] = ??? +def intersect(l1Line2Dl2Line2D)(start: Int, stop: Int): Boolean = ???
-</​code>​ +
- +
-**3.2.3.** Count the number of emails longer than k characters. Use ''​foldRight''​. +
- +
-<code scala> +
-def howMany(k: Int)(list: List[Str]): Int = ??? +
-</​code>​ +
- +
-**(!) 3.2.4.** Implement a function that tokenizes a String split by a given delimiter using ''​foldRight''​. Try to figure out what the accumulator should do. +
-<code scala> +
-def mySplit(l: StrsepChar): List[Str] = ??? +
-</​code>​ +
- +
-**3.2.5.** Implement a function that return the domains without the dot (ex. ''​gmail''​). +
-<code scala> +
-def domains(list:​ List[Str]): List[Str] = ??? +
-</​code>​ +
- +
- +
- +
- +
-==== 3.3. Gradebooks ==== +
-More general implementations of ''​taken'',​ ''​dropn''​ and ''​part''​ are already implemented in Scala and can be used as member functions of lists. Examples are shown below: +
-<code scala> +
-val l = List(1,​2,​3,​4,​5,​6,​7,​8,​9) +
-l.take(3) +
-l.drop(3) +
-l.partition(_%2 == 0) +
-</​code>​ +
- +
-In what follows, we shall encode a gradebook as a list of pairs ''​(<​name>,<​grade>​)'',​ where ''<​name>''​ is a String and ''<​grade>''​ is an Int. Example: +
-<code scala> +
-val gradebook: List[(Str, ​Int)] = List((List('​G'​),​3),​ (List('​F'​),​ 10), (List('​M'​),​6),​ (List('​P'​),​4)) +
-</​code>​  +
- +
-To make the type signatures more legible, we can introduce type aliases in Scala: +
-<code scala> +
-type Gradebook = List[(Str,​Int)] //the type Gradebook now refers to a list of pairs of String and Int +
-</​code>​ +
-Add this type alias to your code before solving the following exercises. +
- +
-**3.3.1.** Write a function which adds one point to all students that satisfy a given predicate (ex: grade >= 5), and leaves all other grades unchanged. +
-<code scala> +
-def increment(g:​ Gradebook, p: (Str, Int) => Boolean): Gradebook ​= +
-  g.map(???)  +
-</​code>​ +
- +
-**3.3.2.** Find the average grade from a gradebook. You must use ''​foldRight''​. +
-<code scala> +
-def average(g: Gradebook): Double = ??? +
-</​code>​ +
- +
-**3.3.3.** Write a function which takes a gradebook and returns the list of names which have passed. Use filter and map from Scala. +
-<code scala> +
-def pass(g: Gradebook): List[Str] = ??? +
-</​code>​ +
- +
-**3.3.4.** Implement merge-sort (in ascending order) over gradebooks:​ +
-<code scala> +
-def mergeSort(l:​ Gradebook): Gradebook = { +
-   def merge(u: Gradebook, v: Gradebook): Gradebook = ??? +
-   ??? +
-}+
 </​code>​ </​code>​
  
-**3.3.5** Write a function which takes a gradebook ​and reports all passing students in **descending** order of their grade.+**3.11.** Write a function which takes two lines and range of integers, ​and checks if l1 has larger y values than l2 over the entire range.
 <code scala> <code scala>
-def honorsList(gGradebook): List[Str] ​= ???+def larger(l1Line2D, l2: Line2D)(start:​ Int, stop: Int): Boolean ​= ???
 </​code>​ </​code>​