Lab 2. Scala syntax and function definition

Objectives:

  • get yourself familiar with Scala syntax basics
  • 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

2.1. Write a tail-recursive function that computes the factorial of a natural number. Start from the code stub below:

def fact (n: Int): Int = {
   def aux_fact(i: Int, acc: Int): Int = 
       if (???) acc
       else ???
   ???
}

2.2. Implement a tail-recursive function that computes the greatest common divisor of a natural number:

def gcd(a: Int, b: Int): Int = ???

2.3. Write a tail-recursive function takes an integer $ n$ and computes the value $ 1 + 2^2 + 3^2 + \ldots + (n-1)^2 + n^2$ . (Hint: use inner functions).

def sumSquares(n: Int): Int = ???

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.

def sumNats(start: Int, stop: Int): Int = ???
def tailSumNats(start: Int, stop: Int): Int = ???

2.5. (!) Write a function which takes an initial value $ x$ and a range of values $ x_0, x_1, \ldots, x_n$ and computes $ ((x - x_0) - x_1) - \ldots x_n$ . Use the most appropriate type of recursion for this task.

def subtractRange(x: Int, start: Int, stop: Int): Int = ???

2.6. (!) Write a function which takes an initial value $ x$ and a range of values $ x_0, x_1, \ldots, x_n$ and computes $ x_0 - (x_1 - (x_2 - (\ldots - (x_n - x)\ldots )$ . Use the most appropriate type of recursion for this task.

A very fast way to numerically compute $ \sqrt{a}$ , often used as a standard sqrt(.) implementation, relies 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 $ x_0 = 1$ .
  • Compute $ x_{n+1} = \displaystyle\frac{1}{2}(x_n+\frac{a}{x_n})$

2.4. Implement the function improve which takes an estimate $ x_n$ of $ \sqrt{a}$ and improves it (computes $ x_{n+1}$ ).

def improve(xn: Double, a: Double): Double = ???

2.5. Implement the function nthGuess which starts with $ x_0 = 1$ and computes the nth estimate $ x_n$ of $ \sqrt{a}$ :

def nth_guess(n: Int, a: Double): Double = ???

Note that:

  • for smaller $ a$ , there is no need to compute $ n$ estimations as $ (x_n)_n$ converges quite fast to $ \sqrt{a}$ .

2.6. Thus, implement the function acceptable which returns true iff $ \mid x_n^2 - a \mid \leq 0.001$ . (Hint, google the abs function in Scala. Don't forget to import scala.math._).

  def acceptable(xn: Double, a: Double): Boolean = ???

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:

def mySqrt(a: Double): Double = {
   def improve(xn: Double): Double = ???
   def acceptable(xn: Double): Boolean = ???
 
   def tailSqrt(estimate: Double): Double = ???
 
   ???
}

2.8. (!) Try out your code for: 2.0e50 (which is $ 2.0\cdot 10^{50}$ ) or 2.0e-50. The code will likely take a very long time to finish. The reason is that $ xn^2 - a$ will suffer from rounding error which may be larger than 0.001. Can you find a different implementation for the function acceptable which takes that into account? (Hint: the code is just as simple as the original one).