Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | |||
fp2023:lab02 [2023/03/10 19:49] bogdan.butnariu added solutions |
fp2023:lab02 [2024/03/15 10:48] (current) pdmatei |
||
---|---|---|---|
Line 19: | Line 19: | ||
</code> | </code> | ||
- | <hidden> | ||
- | <code scala> | ||
- | def fact (n: Int): Int = { | ||
- | def aux_fact(n: Int, acc: Int): Int = | ||
- | if (n == 0) acc | ||
- | else aux_fact(n - 1, acc * n) | ||
- | aux_fact(n, 1) | ||
- | } | ||
- | </code> | ||
- | </hidden> | ||
**2.2.** Implement a tail-recursive function that computes the greatest common divisor of a natural number: | **2.2.** Implement a tail-recursive function that computes the greatest common divisor of a natural number: | ||
Line 36: | Line 26: | ||
</code> | </code> | ||
- | <hidden> | ||
- | <code scala> | ||
- | def gcd(a: Int, b: Int): Int = | ||
- | if (b == 0) a | ||
- | else gcd(b, a % b) | ||
- | </code> | ||
- | </hidden> | ||
**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). | **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). | ||
Line 49: | Line 32: | ||
def sumSquares(n: Int): Int = ??? | def sumSquares(n: Int): Int = ??? | ||
</code> | </code> | ||
- | |||
- | <hidden> | ||
- | <code scala> | ||
- | def sumSquares(n: Int): Int = { | ||
- | def powerTwo(n: Int) = n * n | ||
- | |||
- | def aux_squares(n: Int, acc: Int): Int = | ||
- | if (n == 0) acc | ||
- | else aux_squares(n - 1, acc + powerTwo(n)) | ||
- | aux_squares(n, 0) | ||
- | } | ||
- | </code> | ||
- | </hidden> | ||
**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.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. | ||
Line 68: | Line 38: | ||
def tailSumNats(start: Int, stop: Int): Int = ??? | def tailSumNats(start: Int, stop: Int): Int = ??? | ||
</code> | </code> | ||
- | |||
- | <hidden> | ||
- | <code scala> | ||
- | def sumNats(start: Int, stop: Int): Int = { | ||
- | if (start > stop) 0 | ||
- | else start + sumNats(start + 1, stop) | ||
- | } | ||
- | |||
- | def tailSumNats(start: Int, stop: Int) = { | ||
- | def aux(crt: Int, acc: Int): Int = { | ||
- | if (crt > stop) acc | ||
- | else aux(crt + 1, acc + crt) | ||
- | } | ||
- | aux(start, 0) | ||
- | } | ||
- | </code> | ||
- | </hidden> | ||
**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. | **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. | ||
Line 91: | Line 44: | ||
def subtractRange(x: Int, start: Int, stop: Int): Int = ??? | def subtractRange(x: Int, start: Int, stop: Int): Int = ??? | ||
</code> | </code> | ||
- | |||
- | <hidden> | ||
- | <code scala> | ||
- | def subtractRange1(x: Int, start: Int, stop: Int): Int = { | ||
- | def loop(i: Int, acc: Int): Int = | ||
- | if (i > stop) 0 | ||
- | else loop(i+1, acc - i) | ||
- | loop(start,x) | ||
- | } | ||
- | </code> | ||
- | </hidden> | ||
**2.6.** (!) 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_0 - (x_1 - (x_2 - (\ldots - (x_n - x)\ldots )]. Use the most appropriate **type of recursion** for this task. | **2.6.** (!) 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_0 - (x_1 - (x_2 - (\ldots - (x_n - x)\ldots )]. Use the most appropriate **type of recursion** for this task. | ||
- | <hidden> | ||
- | <code scala> | ||
- | def subtractRange2(x: Int, start: Int, stop: Int): Int = { | ||
- | if (start > stop) x | ||
- | else start - subtractRange2(x, start + 1, stop) | ||
- | } | ||
- | </code> | ||
- | </hidden> | ||
===== Newton's Square Root method ===== | ===== Newton's Square Root method ===== | ||
Line 124: | Line 58: | ||
def improve(xn: Double, a: Double): Double = ??? | def improve(xn: Double, a: Double): Double = ??? | ||
</code> | </code> | ||
- | |||
- | <hidden> | ||
- | <code scala> | ||
- | def improve(xn: Double, a: Double): Double = | ||
- | (1.toDouble / 2) * (xn + a / xn) | ||
- | </code> | ||
- | </hidden> | ||
**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}]: | **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}]: | ||
Line 136: | Line 63: | ||
def nth_guess(n: Int, a: Double): Double = ??? | def nth_guess(n: Int, a: Double): Double = ??? | ||
</code> | </code> | ||
- | |||
- | <hidden> | ||
- | <code scala> | ||
- | def nth_guess(n: Int, a: Double): Double = { | ||
- | def aux(n: Int, xn: Double): Double = | ||
- | if (n == 0) xn | ||
- | else aux(n - 1, improve(xn, a)) | ||
- | aux(n, 1) | ||
- | } | ||
- | </code> | ||
- | </hidden> | ||
Note that: | Note that: | ||
Line 155: | Line 71: | ||
def acceptable(xn: Double, a: Double): Boolean = ??? | def acceptable(xn: Double, a: Double): Boolean = ??? | ||
</code> | </code> | ||
- | |||
- | <hidden> | ||
- | <code scala> | ||
- | def acceptable(xn: Double, a: Double): Boolean = | ||
- | (xn * xn - a).abs <= 0.001 | ||
- | </code> | ||
- | </hidden> | ||
**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: | **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: | ||
Line 174: | Line 83: | ||
} | } | ||
</code> | </code> | ||
- | |||
- | <hidden> | ||
- | <code scala> | ||
- | def mySqrt(a: Double): Double = { | ||
- | def improve(xn: Double): Double = (1.toFloat / 2) * (xn + a / xn) | ||
- | |||
- | def acceptable(xn: Double): Boolean = (xn * xn - a).abs <= 0.001 | ||
- | |||
- | def tailSqrt(estimate: => Double): Double = | ||
- | if (acceptable(estimate)) estimate | ||
- | else tailSqrt(improve(estimate)) | ||
- | |||
- | tailSqrt(1) | ||
- | } | ||
- | </code> | ||
- | </hidden> | ||
**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 a very long time to finish. The reason is that $math[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). | **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 a very long time to finish. The reason is that $math[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). | ||
- | <hidden> | ||
- | <code scala> | ||
- | def acceptableGood(xn: Double): Boolean = | ||
- | (xn * xn/a - 1).abs <= 0.001 | ||
- | </code> | ||
- | </hidden> | ||