Differences

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

Link to this comparison view

Next revision
Previous revision
fp2025:lab02 [2025/03/03 00:19]
cata_chiru created
fp2025:lab02 [2025/03/05 17:03] (current)
pdmatei
Line 1: Line 1:
-====== Lab 2. High order functions ​======+====== Lab 2. Scala syntax and function definition ​======
  
-Objectives:​ +** Objectives: ​** 
-  * implement and use **higher-order** functions. A **higher-order** function takes other functions as parameter or returns them +  * get yourself familiar with Scala syntax basics 
-  * implement **curry** ​and **uncurry** functions, and how they should be properly used (review lecture).+  * practice writing ​**tail-recursive** functions ​as an alternative to imperative ​**loops**  
 +  * keep your code clean and well-structured.
  
 ** Create a new Scala worksheet to write your solutions ** ** Create a new Scala worksheet to write your solutions **
  
-===== 2.1 Intro. Functions as parameters ===== +**2.1.** Write a tail-recursive ​function that computes ​the factorial ​of a natural number. Start from the code stub below:
-**2.1.1** Write a function ​''​apply'' ​that takes an integer and return ​the result ​of the applied function on the given integer. Start from the code stub below: +
-<code scala> +
-def apply(n: Int, f: Int => Int): Int = { +
-   ??? +
-+
-</​code>​+
  
-**2.1.2** Write a function ''​doubler''​ that returns a function that doubles the input it receives (an integer). Start from the code stub below: 
 <code scala> <code scala>
-def doubler(): Int =Int = {+def fact (n: Int): Int = 
 +   def aux_fact(i: Int, acc: Int): Int =  
 +       if (???) acc 
 +       else ???
    ???    ???
 } }
 </​code>​ </​code>​
  
-**2.1.3** Create ​a function ​''​trycatch'' ​that takes an integer and evaluates its value using the try function. If an error occurs (try function returns 0), the catch function will be called instead.+ 
 +**2.2.** Implement ​tail-recursive ​function that computes ​the greatest common divisor of a natural number: 
 <code scala> <code scala>
-def trycatch(tInt => Int, c: Int => Int)(x: Int): Int = +def gcd(a: Int, b: Int): Int = ???
-   ??? +
-}+
 </​code>​ </​code>​
  
-**2.1.4** Write a function ​''​realtrycatch''​ where t and c take no parameters ​and produce a result upon evaluationIf an error occurs ​(try function returns 0), the catch function will be called instead.+ 
 +**2.3.** Write a tail-recursive ​function ​takes an integer $math[n] ​and computes the value $math[1 + 2^2 + 3^2 + ... + (n-1)^2 + n^2]. (Hint: use inner functions). 
 <code scala> <code scala>
-def realtrycatch(=> Int, c: => Int): Int  +def sumSquares(n: Int): Int = ???
-   ??? +
-}+
 </​code>​ </​code>​
  
-===== 2.2 Custom high order functions ===== +**2.4.** Write a function which computes the sum of all natural numbers within ​a range. Use **two styles** ​to write this function: direct recursion, and tail recursion.
-**2.2.1** Define the function ​''​foldWith'' ​which uses an operation ''​op''​ to reduce ​a range of integers ​to a value. For instancegiven that ''​op''​ is addition (+), the result of folding the range 1 to 3 will be 1+2+3=6. ''​foldWith''​ should be curried (it will take the operation ​and return another function which expects the bounds).+
 <code scala> <code scala>
-def foldWith (op: (Int,Int) => Int)(start: Int, stop: Int): Int = { +def sumNats(start: Int, stop: Int): Int = ??? 
-  def tail_fold(crt: Int, acc: Int): Int  = ??? +def tailSumNats(start: Int, stop: Int): Int = ???
-  ?? +
-}+
 </​code>​ </​code>​
  
-**2.2.2** Define the function ​''​foldConditional'' ​which extends ''​foldWith''​ by also adding a predicate ''​p:​ Int => Boolean''​. ''​foldConditional''​ will reduce only those elements of a range which satisfy ​the predicate.+**2.5.** (!) Write a function which takes an initial value $math[x] and a range of values $math[x_0, x_1, \ldots, x_n] and computes $math[((x - x_0) - x_1) - \ldots x_n]. Use the most appropriate **type of recursion** for this task.
  
 <code scala> <code scala>
-def foldConditional(op(Int,Int) => Int, p: Int => Boolean)(start: Int, stop: Int): Int = ???+def subtractRange(x: Int, start: Int, stop: Int): Int = ???
 </​code>​ </​code>​
  
-**2.2.3** Write a function ​''​foldMap'' ​which takes values $math[a_1a_2, \ldots, ​a_kfrom a range and computes $math[f(a_1)\;op\;f(a_2)\;op\;\ldots ​f(a_k)]. +**2.6.** (!) Write a function which takes an initial value $math[x] and a range of values $math[x_0x_1, \ldots, ​x_n] and computes $math[x_0 - (x_1 - (x_2 - (\ldots - (x_n - x)\ldots )]. Use the most appropriate **type of recursion** for this task. 
-Use the ''​apply''​ and ''​foldWith''​ methods + 
-<code scala> + 
-def foldMap(op: (Int,Int=> Intf: Int => Int)(start: IntstopInt): Int ??? +===== Newton's Square Root method ===== 
-</​code>​+ 
 +A very fast way to numerically compute $math[\sqrt{a}]often used as a standard //sqrt(.)// implementationrelies on Newton'​s Square Root approximation. The main idea relies on starting with an estimate ​(often 1)and incrementally improving the estimate. More precisely: 
 +  * Start with $math[x_0 ​1]. 
 +  * Compute $math[x_{n+1} = \displaystyle\frac{1}{2}(x_n+\frac{a}{x_n})]
  
-===== 2.3 Curry vs Uncurry ===== +**2.4.** Implement ​the function ''​improve'' ​which takes an estimate $math[x_n] of $math[\sqrt{a}] and improves it (computes $math[x_{n+1}]).
-**2.3.1** Modify ​the function ​below so that it's curry and use it to calculate ​''5*3''​+
 <code scala> <code scala>
-def multiply(x:Inty:Int): Int => x * y+def improve(xnDoubleaDouble): Double ​???
 </​code>​ </​code>​
  
-**2.3.2** Modify ​the function ​below so that it's curry and use it to compare 3 numbers ​and return ​the maximum+**2.5.** Implement ​the function ''​nthGuess''​ which starts with $math[x_0 = 1] and computes ​the nth estimate $math[x_n] of $math[\sqrt{a}]:​
 <code scala> <code scala>
-def compare(x: Int, yInt, z: Int): Int = +def nth_guess(n: Int, aDouble): Double ​???
-+
-  if x > y && x > z then  +
-    x +
-  else if y > x && y > z then +
-    y +
-  else +
-    z +
-}+
 </​code>​ </​code>​
  
-===== 2.4 Function transformations ===== +Note that: 
-The graph of function can undergo different geometric transformation such as scalingshifting, rotating, mirroring and so on. The result of those transformation will also be a function that looks similarly to the original. In this exercice we will particularly work with lines. A line is a linear equation of the form $math[f(xa*x + b+  * for smaller $math[a]there is no need to compute $math[n] estimations as $math[(x_n)_n] converges quite fast to $math[\sqrt{a}] 
- +  
-**2.4.1** Implement a function ​that shifts a line on Oy axis by a certain amount ​$math[\Delta y]+**2.6.** Thus, implement the function ​''​acceptable''​ which returns ''​true''​ iff $math[\mid x_n^2 - a \mid \leq 0.001]. (Hint, google the ''​abs''​ function in Scala. Don't forget to import ''​scala.math._''​).
 <code scala> <code scala>
-def shiftOY(lineDouble => Double, ​delta_y: Double): ​Double ​=> Double = { +  ​def acceptable(xn: Double, ​a: Double): ​Boolean ​= ???
-   ??? +
-}+
 </​code>​ </​code>​
  
-**2.4.2** Implement ​function ​that shifts ​line on Ox axis by a certain amount $math[\Delta x]+**2.7.** Implement ​the function ​''​mySqrt''​ which computes the square root of an integer ''​a''​. Modify the previous implementations to fit the following code structure:
 <code scala> <code scala>
-def shiftOX(line: Double ​=> Double, delta_x: Double): Double =Double = {+def mySqrt(a: Double): Double ​= { 
 +   def improve(xn: Double): Double = ??? 
 +   def acceptable(xn: ​Double): Boolean ​??? 
 +    
 +   def tailSqrt(estimate:​ Double): Double = ??? 
 +   
    ???    ???
 } }
 </​code>​ </​code>​
  
-**2.4.3** Implement ​function ​that checks if two lines intersect at an integer value from a given interval +**2.8(!) **  Try out your code for: ''​2.0e50''​ (which is $math[2.0\cdot 10^{50}]) or ''​2.0e-50''​. The code will likely take very long time to finish. The reason is that $math[x_n^2 - a] will suffer ​from rounding error which may be larger than 0.001. Can you find different implementation for the function ''​acceptable''​ which takes that into account? ​(Hintthe code is just as simple as the original one) 
-<code scala> + 
-def intersect(line1Double => Double, line2: Double => Double)(start: Int, stop: Int): Boolean = { +
-   ??? +
-+
-</​code>​+