In this exercice, we will write functions that manipulate text (Peter Pan, here). The goal is to get familiar with Scala and higher-order functions.
In this exercice, we do not want to use the traditional loops for and while, except if stated overwise
Using your IDE, create a new Scala project. Then, create a new Scala object called
TextReader.
In Scala, the
object keyword is used to create a class that has exactly one instance.
Add the
main method in your code. You should have something like:
object TextReader {
def main(args: Array[String]): Unit = {
}
}
Check you can run Scala by printing the traditional
Hello, World!
object TextReader {
def main(args: Array[String]): Unit = {
println("Hello, World!")
}
}
Follow this
link and download the book
Peter Pan.
Then, we want to read the lines of this file and put the lines into a list. We can use the following:
val lines = Source.fromFile(path)("UTF-8").getLines.toList
You will have to import
Source with
import scala.io.Source.
Print the first element of this list.
Although the length function exists in Scala, recode it using a recursive function. You can use if/else and the isEmpty method.
Compare that you get the same result as the native length method.
(Optional) Try to write the same function with pattern matching.
def length(l: List[String]): Int = {
if (l.isEmpty) {
0
} else {
length(l.tail) + 1
}
}
Now, we want to get statistics about this text. Write a function that returns the total number of caracters. Here, use only higher-order functions (no for/while and recursive functions).
def totalChars(l: List[String]): Int = {
l.map(_.length).reduce(_ + _)
}
Write a function to get the number of lines containing the word Peter (String has a method contains).
def getNumberLinesPeter(l : List[String]): Int = {
l.filter(_.contains("Peter")).length
}
Using curryfication, generalize the previous function so that it accepts any word (not just Peter) and return the matching function.
def getNumberLinesWord(word: String)(l: List[String]) : Int = {
l.filter(_.contains(word)).length
}
Using only higher-order functions, apply the following transformation to each line:
- If the line contains love, turn it into the Char +
- Else if the line contains hate, turn it into the Char -
- Else, turn it into the Char =
Then, remove the
= and print what remains on a single line. You should get something like:
+++--+-++---.
def printPlusMinus(l: List[String]) = {
l.map(x => if (x.contains("love")) '+' else if (x.contains("hate")) '-' else '=').filter(x => x != '=').foreach(print)
}
(hard) Using only higher-order functions, get the most frequent letter in the text, excluding the space. If you want to transform something into a list, you can use the .toList method.
We propose the following algorithm:
- Turn all the lines into a list of Char.
- Merge all the lists into a single one.
- Remove all spaces
- Group all the similar letters together.
- Turn the Map into a list and for each group of letter, keep only its length
- Using a reduce, find the most used character
Be careful with the types at each step (an IDE helps a lot, here).
def mostCommonLetter(l: List[String]) : Char = {
l.map(_.toList).flatten.filter(_ != ' ').groupBy(x => x).toList
.map(x => (x._1, x._2.length))
.reduce((x, y) => if (x._2 < y._2) y else x)._1
}