Add new courses

This commit is contained in:
Andrew Trieu
2024-01-17 10:51:32 +02:00
committed by Andrew Trieu
parent 6ba01de84b
commit 6ee81b8321
51 changed files with 1036 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,125 @@
/*Exercise 1
Student name: Trieu Huynh Ba Nguyen
Student number: 000405980 */
// Task 1: Provide two variables/values showing difference between immutable and mutable types
def Task1() = {
// An immutable variable is a variable whose value cannot be changed once it is assigned.
val immutable = "immutable"
println("Immutable: " + immutable)
// A mutable variable is a variable whose value can be changed once it is assigned.
var mutable = "mutable"
println("Mutable: " + mutable)
mutable = "changed"
println("Changed mutable: " + mutable)
// immutable = "changed" // Error: This will not compile
// println("Changed immutable: " + immutable)
}
// Task 2: Provide an example where Scala automatically infers the Data Types of a Boolean, Double, Int and String variables
def Task2() = {
// getClass() is a method that returns the class of the object
var boolean = true
var double = 1.2345
var int = 12345
var string = "scala"
println(boolean.getClass())
println(double.getClass())
println(int.getClass())
println(string.getClass())
}
// Task 3: Create an immutable variable of type String holding your “Last Name” with the help of multiple immutable variables of type Char
def Task3() = {
val s = 's'
val c = 'c'
val a = 'a'
val l = 'l'
val name = s"$s$c$a$l$a"
println(name)
}
// Task 4: Create a value of type Int holding your age and place it inside the String “I am learning scala at the age of __years”
def Task4() = {
// String interpolation can be used to embed expressions, variables, and method calls in strings.
val age = 20
println(s"I am learning scala at the age of $age years")
}
// Task 5: What is a definition of Expression in Scala? Write your answer in the comment supported with example
def Task5() = {
// An expression is a code cluster of variables, values, operators, and method calls that computes and returns a value.
// Example:
val x = println("This is an expression")
x
}
// Task 6: Write any example showing Chained IF expression resulting to a single value of Int Type
def Task6() = {
val x = 5
val y = 10
val z = 15
val result = if (x > y) {
if (x > z) {
x
} else {
z
}
} else {
if (y > z) {
y
} else {
z
}
}
result
}
// Task 7: Write a Code Block returning a value of type string by concatenating your “First Name”and “Last Name”
def Task7 = {
val firstName = "Andrew"
val lastName = "Trieu"
val fullName = {
s"$firstName $lastName"
}
fullName
}
// Task 8: Define a function that takes 2 values of type Int and returns a single value of type String after summation. E.g. the return String should be “The sum of 1 and 2 is: 3”
def Task8() = {
def sum(a: Int, b: Int): String = {
s"The sum of $a and $b is: ${a + b}"
}
sum(123, 456)
}
// Main function
def main(args: Array[String]): Unit = {
println("Task 1:")
Task1()
println("\nTask 2:")
Task2()
println("\nTask 3:")
Task3()
println("\nTask 4:")
Task4()
println("\nTask 5:")
Task5()
println("\nTask 6:")
println(Task6())
println("\nTask 7:")
println(Task7)
println("\nTask 8:")
println(Task8())
}

View File

@@ -0,0 +1,41 @@
package com.rockthejvm
object Exercise_1 extends App{
// I am comment
/*
* I am a multiline comment
*
* */
val number = 3 // constant
number = 5
val string1 = "Scala"
val string2 = "Programming"
val result = string1 + string2 // string concatination
val interpolatedString = s"I am sitting at seat number $number"
val expersseion = 2 + 3
val IfExpressions = if (number > 3) "greater" else "smaller"
val block = {
val ChainedExpression =
if (number > 3)
'A' else if (number < 3)
'B' else if (number == 3)
"Bla bla"
}
def myFirstFunction(First : Int, Second : String) : String = {
val result = First + " " + Second
return result
}
var number1: Int = 5 // its valuce can be updated
number1 = 6
}

View File

@@ -0,0 +1,135 @@
/*Exercise 1
Student name: Trieu Huynh Ba Nguyen
Student number: 000405980 */
// Task 1: Write a Scala program that defines a function called addition which takes two integer arguments and returns their sum using recursion.
def addition(x: Int, y: Int): Int = {
if (y == 0) x
else addition(x + 1, y - 1)
}
// Task2: Write a Scala program that defines a function called subtraction which takes two integer arguments and returns their difference by using the addition function defined above.
def subtraction(x: Int, y: Int): Int = {
addition(x, -y)
}
// Task 3: Write a Scala program that defines a function called multiplication which takes two integer arguments and returns their product by using the addition function defined above.
def multiplication(x: Int, y: Int): Int = {
if (y == 0 || x == 0) 0
else addition(x, multiplication(x, y - 1))
}
// Task 4:Write a Scala program that defines a function called division which takes two integer arguments and returns their quotient by using the subtraction functions defined above. If the second argument is zero, return an error message.
def division(x: Int, y: Int): Int = {
if (y == 0) {
print("Error: Division by zero - ")
0
} else if (x == 0) 0
else if (x < y) 0
else addition(1, division(subtraction(x, y), y))
}
// Task 5: Write a Scala program that defines a function called factorial which takes a non-negative integer as its argument and returns its factorial. Use recursion to implement the function.
def factorial(x: Int): Int = {
if (x < 0) {
print("Error: Negative number - ")
0
} else if (x == 0) 1
else multiplication(x, factorial(x - 1))
}
// Task 6: Write a Scala program that defines a function called isPrime which takes a non-negative integer as its argument and returns true if the number is prime, and false otherwise.
def isPrime(x: Int): Boolean = {
if (x < 0) {
print("Error: Negative number - ")
false
} else if (x == 0 || x == 1) false
else {
var i = 2
while (i < x) {
if (x % i == 0) return false
i += 1
}
true
}
}
// Task 7: How the memory is impacted by loops and recursions? Explain your answer with supportive examples.
def memoryImpact(): Unit = {
println(
"Memory impact by loops and recursions are different. Recursion uses a function call stack to store the set of new local variables and parameters on each function call. On the other hand, we have looping that doesn't use any stack. Hence, recursion incurs more memory cost since they add the overhead of stacking/unstacking operation. For larger inputs, recursion might lead to stack overflow."
)
// Example 1: Loop
def loop(x: Int): Int = {
var counter = 0
for (i <- 1 to x) {
counter += i
}
counter
}
loop(100)
// Example 2: Recursion
def recursion(x: Int): Int = {
if (x == 0) 0
else x + recursion(x - 1)
}
recursion(100)
}
// Task 8: What is a difference between local scope and global scope of variables (i.e. var/val)? Support your arguments with examples. [Hint: “Closure” concept in Class Lectures]
def scope(): Unit = {
println(
"Local scope is the scope of a variable that is defined inside a function. Global scope is the scope of a variable that is defined outside a function. Local scope is only accessible inside the function that it is defined in. Global scope is accessible in all functions. For example, if we define a variable x inside a function, we can only access it inside that function. If we define a variable x outside a function, we can access it in all functions."
)
val x = 10
// Example 1: Local scope
def localScope(): Unit = {
val y = 5
println(x)
println(y)
}
localScope()
// Example 2: Global scope
def globalScope(): Unit = {
println(x)
// println(y) // Error: x is not defined
}
globalScope()
}
def main(args: Array[String]): Unit = {
println("Task 1:")
println(addition(5, 3))
println(addition(5, 0))
println(addition(0, 3))
println("\nTask 2:")
println(subtraction(5, 3))
println(subtraction(3, 5))
println("\nTask 3:")
println(multiplication(5, 3))
println(multiplication(5, 0))
println(multiplication(0, 3))
println("\nTask 4:")
println(division(40, 18))
println(division(5, 3))
println(division(5, 0))
println(division(0, 3))
println(division(3, 5))
println("\nTask 5:")
println(factorial(5))
println(factorial(3))
println(factorial(0))
println(factorial(-5))
println("\nTask 6:")
println(isPrime(2))
println(isPrime(8))
println(isPrime(11))
println(isPrime(17))
println(isPrime(20))
println(isPrime(0))
println(isPrime(-5))
println("\nTask 7:")
memoryImpact()
println("\nTask 8:")
scope()
}

View File

@@ -0,0 +1,35 @@
package com.rockthejvm
object Exercise_2 extends App {
//claculating factroial with loops
def factorialWithLoop(n: Int) = {
var f=1
for (i <- 1 to n) {
f = f * i
}
f
}
println("Loop: Factorial is : " + factorialWithLoop(3))
//fictorial(3) * fictorial(2) * fictorial(1) * fictorial(0) = 6
//claculating factroial with loops
def factorialWithRecursion(n: Int): Int = {
if (n == 0) 1
else n * factorialWithRecursion(n - 1) // 3-1 = 2
// 2-1 = 1
// 1- 1 = 0
}
println("Recursion: Factorial is : " + factorialWithRecursion(3))
/*
* HINT for Task 1
* For two intergers m & n
* /*
Recursion: adding 1, n times and
then at the end adding m to it
*/
* */
}

View File

@@ -0,0 +1,100 @@
/*Exercise 3
Student name: Trieu Huynh Ba Nguyen
Student number: 000405980 */
object Exercise_3 extends App {
// Task 1: Write a higher-order function called operateOnList that takes a list of integers and a function oddToEven (that convert odd integer to even) as an arguments, and applies the function to each element in the list, returning a new list of results with all even integers.
def oddToEven(x: Int): Int = {
if (x % 2 == 0) x
else x + 1
}
def operateOnList(list: List[Int], f: Int => Int): List[Int] = {
list.map(f)
}
val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
println("Task 1: " + operateOnList(list, oddToEven))
// Task 2: Write a function called filterAndMap that takes a list of strings, a predicate function greaterLength (that filters the string which has length greater than 6), and a mapping function concat (that concatenates the length of string with the string i.e. “string6”) as arguments, and returns a new list of transformed elements that meet the given predicate.
def greaterLength(x: String): Boolean = {
if (x.length > 6) true
else false
}
def concat(x: String): String = {
x + x.length
}
def filterAndMap(
list: List[String],
f: String => Boolean,
g: String => String
): List[String] = {
list.filter(f).map(g)
}
val list2 = List(
"LUT",
"University",
"Lahti",
"Lappeenranta",
"Finland",
"Engineering",
"Software",
"Scala"
)
println("Task 2: " + filterAndMap(list2, greaterLength, concat))
/* Create a higher-order polymorphic function listTransformation in Scala that works with any data type and any transformation function. It should takes in two arguments:
- List (A list of values of any data type)
- transformFunc (A function that transforms each element in the list into another element of the same or a different type)
Example 1: a list of strings, a transformation function that transforms a string to string length
Example 2: a list of integers, a transformation function that transforms an integer to its double value
After implementing the function, you should test it with at least two different examples to demonstrate its versatility and flexibility.*/
def listTransformation[A, B](
list: List[A],
transformFunc: A => B
): List[B] = {
list.map(transformFunc)
}
val list3 = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
def double(x: Int): Int = {
x * 2
}
def stringLength(x: String): Int = {
x.length
}
println("Task 3: " + listTransformation(list3, double))
println("Task 3: " + listTransformation(list2, stringLength))
/* Create a program that demonstrates the use of currying and partially applied functions. I should have the following three components:
- A curried function that takes in three arguments of type Int and returns their product.
- A partially applied function that uses the curried function to multiply two numbers by a fixed constant.
- A main function that demonstrates the use of the curried and partially applied functions with different arguments.
After implementing the program, you should test it with at least three different examples */
def curriedFunction(x: Int)(y: Int)(z: Int): Int = {
x * y * z
}
val partiallyAppliedFunction = curriedFunction(5) _
def main(x: Int, y: Int, z: Int): Unit = {
println("Task 4: " + curriedFunction(x)(y)(z))
println("Task 4: " + partiallyAppliedFunction(y)(z))
}
main(2, 3, 4)
main(3, 4, 5)
main(4, 5, 6)
}

View File

@@ -0,0 +1,75 @@
package com.rockthejvm
object Exercise_3 extends App{
//Lists
// List of Strings
val fruits: List[String] = List("apples", "oranges", "pears")
// List of Integers
val nums: List[Int] = List(1, 2, 3, 4)
// Empty List.
val empty: List[Nothing] = List()
// Two dimensional list
val dim: List[List[Int]] =
List(
List(1, 0, 0),
List(0, 1, 0),
List(0, 0, 1)
)
// A regular function that takes two integers and returns their sum
def add(a: Int, b: Int): Int = {
a + b
}
// A higher-order function that takes a function and two integers as arguments, applies the function to the integers, and returns the result
def apply(f: (Int, Int) => Int, a: Int, b: Int): Int = {
f(a, b)
}
// A function that takes two integers and returns their product
def multiply(a: Int, b: Int): Int = {
a * b
}
// Call the regular add function with two arguments
val sum = add(2, 3)
println(sum) // Output: 5
// Call the higher-order apply function with the add function and two arguments
val result1 = apply(add, 2, 3)
println(result1) // Output: 5
// Call the higher-order apply function with the multiply function and two arguments
val result2 = apply(multiply, 2, 3)
println(result2) // Output: 6
//----------------------------------------------------------------
//Task 1
def operateOnList(list: List[Int], f: Int => Int): List[Int] = ???
//Task 2
def filterAndMap(list: List[String], predicate: String => Boolean, mapping: String => String): List[String] = ???
//Task 3
def listTransformation[A, B](list: List[A], transformFunc: A => B): List[B] = ???
//Inputs & Expected Outputs for Task 3
//Example 1
val stringList = List("apple", "banana", "orange")
// Output: List(5, 6, 6)
//Example 2
val numberList = List(1, 2, 3, 4, 5)
// Output: List(1, 4, 9, 16, 25)
//Task 4
//[HINT: Lecture Slides 14-18]
//----------------------------------------------------------------
}

View File

@@ -0,0 +1,88 @@
/*Exercise 3
Student name: Trieu Huynh Ba Nguyen
Student number: 000405980 */
object Exercise_4 extends App {
/* Task 0: Sequences, Sets & Maps built-in Functions Practice
 Create a list of integer nums containing the numbers 1 to 10.
 Use the map method to create a new list squares that contains the squares of each
number in nums.
 Use the filter method to create a new list evenSquares that contains only the even
squares from the squares list.
 Create a set evenSet that contains the even numbers from the nums list.
 Use the foldLeft method to calculate the sum of all the elements in the evenSet.
 Create a map squaresMap that maps each number in nums to its square.
 Use the getOrElse method on the squaresMap to get the square of the number 11. If
the number is not present in the map, return 0. */
val nums = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val squares = nums.map(x => x * x)
val evenSquares = squares.filter(x => x % 2 == 0)
val evenSet = nums.toSet.filter(x => x % 2 == 0)
val sum = evenSet.foldLeft(0)((x, y) => x + y)
val squaresMap = nums.map(x => (x, x * x)).toMap
val squareOf11 = squaresMap.getOrElse(11, 0)
println("Task 0: " + nums)
println("Task 0: " + squares)
println("Task 0: " + evenSquares)
println("Task 0: " + evenSet)
println("Task 0: " + sum)
println("Task 0: " + squaresMap)
println("Task 0: " + squareOf11)
/* Task 1: Write a function removeDuplicatesthat removes duplicates from a sequence of strings.
This function should take a sequence of strings seq as input and uses the foldLeft method to
accumulate a new sequence newSeq that contains only the unique elements from the input
sequence. */
def removeDuplicates(seq: Seq[String]): Seq[String] = {
seq.foldLeft(Seq[String]())((newSeq, x) =>
if (newSeq.contains(x)) newSeq else newSeq :+ x
)
}
val seq = Seq("hello", "world", "hello", "scala", "world")
println("Task 1: " + removeDuplicates(seq))
/* Task 2: Write a function findCommonElements that finds the common elements in two
different sets. This function should takes two sets set1 and set2 of elements of type A as input
and returns a new set that contains the elements that are common to both input sets. */
def findCommonElements[A](set1: Set[A], set2: Set[A]): Set[A] = {
set1.foldLeft(Set[A]())((newSet, x) =>
if (set2.contains(x)) newSet + x else newSet
)
}
val set1 = Set(1, 2, 3, 4, 5)
val set2 = Set(3, 4, 5, 6, 7)
println("Task 2: " + findCommonElements(set1, set2))
/* Task 3: Write a function removeKeys that removes elements from an immutable map. The
function should take a map and a list of keys to remove as input and return a new map that
does not contain the specified keys. */
def removeKeys[K, V](map: Map[K, V], keys: List[K]): Map[K, V] = {
keys.foldLeft(map)((newMap, x) => newMap - x)
}
val map = Map(1 -> "one", 2 -> "two", 3 -> "three", 4 -> "four")
println("Task 3: " + removeKeys(map, List(1, 2, 3)))
/* Task 4: Write a Scala program that reads a text file and counts the occurrence of each word in
the file. You should use an immutable map to store the word frequencies. */
def countWords(fileName: String): Map[String, Int] = {
val source = scala.io.Source.fromFile(fileName)
val words = source.mkString.split("\\s+")
source.close()
words.foldLeft(Map[String, Int]())((map, x) =>
if (map.contains(x)) map + (x -> (map(x) + 1)) else map + (x -> 1)
)
}
// Print each word on its own line
println("Task 4:")
print(countWords("text.txt").mkString("\n"))
}

View File

@@ -0,0 +1,65 @@
package com.rockthejvm
object Exercise_4 extends App{
////////////////////////Sequence Behavior/////////////////////////
val seq = Seq("a", "b", "c", "d", "e")
val seq2 = Seq("a", "b", "c", "d", "e", "f")
val seq3 = Seq("a", "b", "c", "d", "e", "e")
//seq(n)
println(seq(2)) // prints "c"
//seq.length
println(seq.length) // prints "5"
//seq.lengthCompare(s2)
println(seq.lengthCompare(seq2)) // prints -1 (-1 if <, +1 if >, 0 if ==)
//seq.indexOf(x)
println(seq3.indexOf("e")) //prints "4"
//seq.lastIndexOf(x)
println(seq3.lastIndexOf("e")) //prints "5"
//........................continue practicing.........................
//Task 0
// 1. Create a list of integers nums containing the numbers 1 to 10.
val nums = (1 to 10).toList
// 2. Use the map method to create a new list squares that contains the squares of each number in nums.
val squares = nums.map(n => n * n)
// 3. Use the filter method to create a new list evenSquares that contains only the even squares from the squares list.
val evenSquares = squares.filter(n => n % 2 == 0)
// 4. Create a set evenSet that contains the even numbers from the nums list.
val evenSet = nums.filter(n => n % 2 == 0).toSet
// 5. Use the foldLeft method to calculate the sum of all the elements in the evenSet.
val sum = evenSet.foldLeft(0)(_ + _)
// 6. Create a map squaresMap that maps each number in nums to its square.
val squaresMap = nums.map(n => n -> (n * n)).toMap
// 7. Use the getOrElse method on the squaresMap to get the square of the number 11. If the number is not present in the map, return 0.
val squareOf11 = squaresMap.getOrElse(11, 0)
///Task1
def removeDuplicates(seq: Seq[String]): Seq[String] = {
???
}
///Task2
def findCommonElements[A](set1: Set[A], set2: Set[A]): Set[A] = {
???
}
///Task3
def removeKeys[K, V](map: Map[K, V], keys: List[K]): Map[K, V] = {
???
}
///Task4
//import scala.io.Source
// 1 Read the input file into a string
// 2 Split the input string into words
// 3 Count the occurrence of each word using an immutable map
// 4 Print the word count for each word
}

View File

@@ -0,0 +1,31 @@
{\rtf1\ansi\ansicpg1252\cocoartf2639
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\paperw11900\paperh16840\margl1440\margr1440\vieww17600\viewh13000\viewkind0
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0
\f0\b\fs32 \cf0 Answers to Questions from the last class:\
\
1. Storing multiple datatypes into a Seq:\
\f1\b0 https://stackoverflow.com/questions/42049763/scala-array-with-different-data-types\
\
2.
\f0\b Some()
\f1\b0 \
https://freecontent.manning.com/using-option-in-scala-part-1-introduction/\
https://www.educba.com/scala-some/\
\
3.
\f0\b foldLeft() vs. foldRight()\
\f1\b0 https://oldfashionedsoftware.com/2009/07/10/scala-code-review-foldleft-and-foldright/\
\
\
\
\
\f0\b \
\
}

View File

@@ -0,0 +1,122 @@
object Exercise_5 extends App {
/*
Task 1: Type Parameterization
Implement a generic function that can compute the average of a list of values of any numeric
type in a recursive manner. The function should take a list of type A and return a value of type
A, where A is any numeric type such as int, float, or double. The function should be tested
with different input lists and the output should be verified to ensure that the average is
computed correctly for each list
*/
def average[A](list: List[A])(implicit num: Numeric[A]): Double = {
// Recursive function to compute the sum of a list of values of type A
def sum(list: List[A]): A = list match {
case Nil => num.zero
case head :: tail => num.plus(head, sum(tail))
}
num.toDouble(sum(list)) / list.length
}
println(average(List(1, 2, 3, 4, 5, 6))) // 3.5
println(average(List(4.5, 5.6, 6.7, 7.8, 8.9, 9.1))) // 7.1
println(average(List(1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f))) // 3.85
/*
Task 2: Variance
Define a class hierarchy of animals, with a base class Animal and two derived classes Bird and
Mammal. Add a method makeSound to each class that returns a string representing the sound
the animal makes. Implement a function makeAllSounds that takes a list of animals and
returns a list of strings representing the sounds each animal makes. Use covariance to ensure
that the return type of the makeAllSounds function is a list of strings, even though the input
list may contain objects of different classes. Test the function with a list of birds and a list of
mammals to ensure that the sounds are correctly returned for each animal
*/
abstract class Animal {
def makeSound(): String
}
class Bird extends Animal {
override def makeSound(): String = "Chirp!"
}
class Mammal extends Animal {
override def makeSound(): String = "Moo!"
}
def makeAllSounds(animals: List[Animal]): List[String] = {
animals.map(animal => animal.makeSound())
}
val birds = List(new Bird, new Bird, new Bird)
val mammals = List(new Mammal, new Mammal, new Mammal)
println(makeAllSounds(birds)) // List(Chirp!, Chirp!, Chirp!)
println(makeAllSounds(mammals)) // List(Moo!, Moo!, Moo!)
/*
Task 3: Type Constraints
Create a typeclass that represents a collection of objects that can be sorted. The typeclass
should have a single recursive function sort that takes a list of objects and returns a sorted list.
Implement instances of the typeclass for several types, including integers, floating-point
numbers, and strings. Use type constraints to ensure that the objects in the list have a total
ordering, which is necessary for sorting. Test the sort function with input lists of different types
and sizes to ensure that it correctly sorts the lists according to the total ordering defined for
each type.
*/
trait Sortable[T] {
def sort(list: List[T]): List[T]
}
object Sortable {
def apply[T](implicit sortable: Sortable[T]): Sortable[T] = sortable
implicit val intSortable: Sortable[Int] = new Sortable[Int] {
def sort(list: List[Int]): List[Int] = list.sorted
}
implicit val doubleSortable: Sortable[Double] = new Sortable[Double] {
def sort(list: List[Double]): List[Double] = list.sorted
}
implicit val stringSortable: Sortable[String] = new Sortable[String] {
def sort(list: List[String]): List[String] = list.sorted
}
}
println(
Sortable[Int].sort(List(8, 9, 4, 3, 6, 5, 2, 1, 7))
) // List(1, 2, 3, 4, 5, 6, 7, 8, 9)
println(
Sortable[Double].sort(List(8.8, 9.9, 4.4, 3.3, 6.6, 5.5, 2.2, 1.1, 7.7))
) // List(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9)
println(
Sortable[String].sort(
List("bb", "cc", "aa", "ee", "gg", "hh", "dd", "ii", "ff")
)
) // List(aa, bb, cc, dd, ee, ff, gg, hh, ii)
/*
Task 4: Pattern Matching
Write a function isPalindrome that takes a string as input and returns true if the string is a
palindrome (i.e., it reads the same backward as forward), and false otherwise. Use pattern
matching to implement the function.
[Hint: You can use pattern matching to match the first and last characters of the string, and
recursively match the substring between them until the string is empty or has one character
left.]
*/
def isPalindrome(string: String): Boolean = string match {
case "" => true
case _ if string.length == 1 => true
case _ if string.head == string.last =>
isPalindrome(string.substring(1, string.length - 1))
case _ => false
}
println(isPalindrome("rotator")) // true
println(isPalindrome("scala")) // false
println(isPalindrome("madam")) // true
println(isPalindrome("rovaniemi")) // false
}

View File

@@ -0,0 +1,38 @@
package com.rockthejvm
object Exercise_5 extends App {
//Pattern Matching
case class Person(name: String, age: Int)
def greet(person: Person): String = person match {
case Person("Alice", _) => "Hello Alice!"
case Person(name, age) if age > 30 => s"Hello $name, you are over 30 years old."
case Person(name, _) => s"Hello $name."
}
val alice = Person("Alice", 25)
val bob = Person("Bob", 35)
println(greet(alice)) // "Hello Alice!"
println(greet(bob)) // "Hello Bob, you are over 30 years old."
//Varience
class Animal
class Dog extends Animal
class Cat extends Animal
class Cage[-A](animal: A)
val dogCage: Cage[Dog] = new Cage[Animal](new Animal)
/*
* In this example, we have defined a Cage class that takes a contravariant type parameter A.
* This means that a Cage[Animal] can be treated as a Cage[Dog] because Dog is a subtype of
* Animal.
* */
}

View File

@@ -0,0 +1,124 @@
object Exercise_6 extends App {
/*
Task 1
Create a function lookingForPrimesthat takes a list of integers and returns a list of Either type
values. If the integer is prime, return Right with the prime integer. If the integer is not prime,
return Left with an error message. Use map to apply this function to a list of integers and then
use foreach to print the results or error messages.
*/
print("Task 1: ")
def lookingForPrimes(list: List[Int]): List[Either[String, Int]] = {
list.map { num =>
if (num < 2) Left(s"$num is not a prime number")
else if (num == 2) Right(num)
else {
val isPrime = (2 until num).forall(num % _ != 0)
if (isPrime) Right(num) else Left(s"$num is not a prime number")
}
}
}
lookingForPrimes(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)).foreach {
case Left(msg) => println(msg)
case Right(num) => println(num)
}
/*
Task 2
Create a case class for a student that contains a name, age, and grade (an Option[Int]). Create
a list of students with some missing grade values. Use flatMap to extract the grade values from
each student, resulting in a list of Int values wrapped in Option. Then use filter to remove any
None values and then to find the average grade of the remaining students using built-in
function or recursion. (Important: No Loops)
*/
print("\nTask 2: ")
case class Student(name: String, age: Int, grade: Option[Int])
val students = List(
Student("Andrew", 20, Some(95)),
Student("Alfred", 21, Some(75)),
Student("David", 20, None),
Student("Roosa", 21, None),
Student("Noora", 20, Some(85)),
Student("Sami", 21, Some(65))
)
val grades = students.flatMap(_.grade)
val average = grades.sum / grades.length
println(average)
/*
Task 3
Create a function that takes two integers and returns an Either value. If the second integer is
zero, return Left with an error message. Otherwise, return Right with the result of dividing the
first integer by the second integer. Create a list of tuples containing pairs of integers, and use
a higher order function to apply this function to each pair, resulting in a list of Either values.
Then use partition to separate the Right values from the Left values, and use foldLeft to find
the sum of the Right values.
*/
print("\nTask 3: ")
def divide(a: Int, b: Int): Either[String, Int] = {
if (b == 0) Left("Cannot divide by zero")
else Right(a / b)
}
val tuples =
List((5, 2), (2, 3), (3, 0), (7, 8), (5, 0), (4, 7), (9, 3), (6, 0))
val (lefts, rights) =
tuples.map { case (a, b) => divide(a, b) }.partition(_.isLeft)
// Note: Right values are of integer type, so after division, they are rounded down to the nearest integer.
// For example, 5 / 2 = 2.5, but the result is 2
val sum = rights.foldLeft(0) { (acc, right) => acc + right.right.get }
println(sum)
/*
Task 4
Create a function that takes a list of Strings and returns an Option value. If any of the Strings
in the list contains the word "error", return None. Otherwise, return Some with the
concatenated string of all strings in the list. Use a higher order function to apply this function
to a list of Strings and then use match to handle the Option value. If Some, print the
concatenated string. If None, print an error message.
*/
print("\nTask 4: ")
def checkForErrors(list: List[String]): Option[String] = {
if (list.exists(_.toLowerCase.contains("error"))) None
else Some(list.mkString)
}
val stringsWithErrors = List(
"Nothing here",
"No error here",
"Definitely something here",
"This will pass",
"Here is an error"
)
val stringsWithoutErrors = List(
"Nothing here",
"Not here",
"Certainly nothing here",
"Definitely nothing here",
"Absolutely nothing here"
)
def handleCheck(List: List[String], f: List[String] => Option[String]) = {
f(List) match {
case Some(str) => println(str)
case None => println("There was an error")
}
}
handleCheck(stringsWithErrors, checkForErrors)
handleCheck(stringsWithoutErrors, checkForErrors)
}

View File

@@ -0,0 +1,57 @@
package com.rockthejvm
object Exercise_6 extends App{
//conventional way
def divide(a: Int, b: Int): Int = {
if (b == 0) {
throw new ArithmeticException("Cannot divide by zero")
}
a / b
}
try {
val result = divide(10, 0)
println(result)
} catch {
case e: ArithmeticException => println("Error: " + e.getMessage)
} finally {
println("Finished")
}
//functional way 1 - Using Option data type
def divide(a: Int, b: Int): Option[Int] = {
if (b == 0) {
None
} else {
Some(a / b)
}
}
val result = divide(10, 0)
//The result variable is of type Option[Int],
// so it can either contain a Some value with the result or None indicating an error.
result match {
case Some(value) => println(s"Result: $value")
case None => println("Error: Cannot divide by zero")
}
//functional way 2 - Using Either data type
def divide(a: Int, b: Int): Either[String, Int] = {
if (b == 0) {
Left("Cannot divide by zero")
} else {
Right(a / b)
}
}
val result = divide(10, 0)
//The result variable is of type Either[String, Int], so it can either contain
// a Right value with the result or Left indicating an error.
result match {
case Right(value) => println(s"Result: $value")
case Left(error) => println(s"Error: $error")
}
}