\documentclass[10pt]{article}

\usepackage{latexsym}
\usepackage{amssymb}
\usepackage{code}
\usepackage{graphicx}

\usepackage{listings}



\usepackage[english]{babel}
%\usepackage{blindtext}
%\usepackage{fontspec}
%\setmainfont{Arial}

%\renewcommand{\familydefault}{\sfdefault}
%\usepackage{blindtext}
\pagenumbering{arabic}  % Arabic page numbers GM July 2000

\usepackage{authoraftertitle}
\usepackage{fancyhdr}
% Clear the header and footer
\fancyhead{}
\fancyfoot{}
%\lhead{\includegraphics[height=0.7cm]{../logo/nyp-logo-int.png} }
\rhead{\scriptsize \MyTitle}
%\lfoot{\scriptsize Specialist Diploma in Business \& Big Data Analytics\\ Copyright
%  \copyright\ Nanyang Polytechnic. All Rights Reserved.}
\rfoot{\thepage}
\pagestyle{fancy}


\renewcommand{\topfraction}{0.95}
\renewcommand{\textfraction}{0.02}
\renewcommand{\floatpagefraction}{0.95}


\bibliographystyle{plain}

%%\textwidth      150mm \textheight     210mm \oddsidemargin  -2mm \evensidemargin -2mm

\renewcommand{\baselinestretch}{0.987}

\setlength{\parskip}{0.0in}


\newcommand{\Nturns}{\, \vdash_{\mbox{\scriptsize lnf}} \,}

\newcommand{\tr}[1]{}
%%\newcommand{\tr}[1]{#1}
%%\newcommand{\nottr}[1]{#1}
\newcommand{\nottr}[1]{}

%\newcommand{\implies}{\supset}
\newcommand{\clabel}[1]{\mbox{(#1)}}
\newcommand{\rat}[1]{\rightarrowtail_{#1}}
\newcommand{\arr}{\rightarrow}
\newcommand{\arrow}{\rightarrow}
\newcommand{\Arr}{\Rightarrow}
\newcommand{\atsign}{@}
\newcommand{\simparrow}[0]{\Longleftrightarrow}
\newcommand{\proparrow}[0]{\Longrightarrow}
\newcommand{\comment}[1]{}
\newcommand{\ignore}[1]{}
%\newcommand{\kl}[1]{{\bf KL:#1}} %%%{\marginpar{\sc kl}{\bf #1}}
\newcommand{\kl}[1]{}
\newcommand{\ms}[1]{{\bf MS:#1}}       %%{\marginpar{\sc ms}{\bf #1}}
%%\newcommand{\jw}[1]{\marginpar{\sc jw}{\bf #1}}
%% \newcommand{\answer}[1]{#1}

\newcommand{\pjs}[1]{}
%%\newcommand{\ms}[1]{}
\newcommand{\jw}[1]{}
%%\newcommand{\kl}[1]{}


\newcommand{\pow}{\^{}}
\newcommand{\venv}{\Delta}
\newcommand{\mleq}{\mbox{\tt leq}}
\newcommand{\mmleq}{\leq}
\newcommand{\mas}{\mbox{\tt as}}
\newcommand{\mfix}{\mu}

\newcommand{\mysection}[1]{\vspace*{-2mm}\section{#1}\vspace*{-1mm}}
\newcommand{\mysubsection}[1]{\vspace*{-1mm}\subsection{#1}\vspace*{-1mm}}

\newcounter{cnt}
\newtheorem{ex}{Example}
%\newenvironment{example}{
%        \begin{ex}\rm}%
%    {\hfill$\Box$\end{ex}}

\newenvironment{nexample}{
        \begin{ex}\rm}%
        {\end{ex}}

%%\newtheorem{rem}{Remark}
%%\renewenvironment{remark}{
%%        \begin{rem}\rm}%
%%    {\hfill$\Box$\end{rem}}

%%\newenvironment{myexample}{
%%        \begin{ex}\rm}%
%%  {\hfill $\Diamond$\end{ex}}
%\newenvironment{example}{
%        \begin{example}\rm}%
%    {\end{example}}

\newenvironment{ttline}{\begin{trivlist}\item \tt}{\end{trivlist}}
\newenvironment{ttprog}{\begin{trivlist}\small\item \tt
        \begin{tabbing}}{\end{tabbing}\end{trivlist}}


\newcommand{\figcode}[1]
        {\begin{figure*}[t]#1
        \end{figure*}}


\title{%ITD353 Massively Parallel Computing for Big Data \\
  Introduction to Scala }
%\author{Kenny Zhuo Ming Lu\\
%  \multicolumn{1}{p{.7\textwidth}}{\centering
%  \emph{School of Information Technology \\ Nanyang Polytechnic \\
%    180 Ang Mo Kio Avenue 8, Singapore 569830}}
%}


\begin{document}
\maketitle \makeatactive
\thispagestyle{fancy}

\lstset{language=Python}

%\begin{abstract}
%\end{abstract}


\section{Learning Outcomes} \label{sec:aims}
\begin{itemize}
 \item Start Scala REPL in Scala application development
 \item Execute and observe Scala programs Scala application
   development
 \item Comprehend all the Scala languages features and the program semantics when reviewing Scala source codes
 \item Develop data transformation scripts using Scala
\end{itemize}




\section{Scala Features}
\begin{enumerate}
\item Scala is an \underline{o~~~~~~~~~~~~~~} oriented and \underline{f~~~~~~~~~~~~~~} language. 
\item Scala is a \underline{~~~~~~~~~~~~~~} typed language.
\end{enumerate}

\section{First Scala Program - Hello World}
\begin{enumerate}
\item Check out the source codes.
  \begin{enumerate}
  \item go to Github and download the {\tt scala.zip} from 
\end{enumerate}
\begin{code}
      $ cd learning-scala/codes
\end{code}
\item Examine the script {\tt Script.scala}  in {\tt helloworld}.
\item Execute the script with the following
\begin{code}
$ scala Script.scala
\end{code}
\item Examine the code {\tt Main.scala} in {\tt helloworld}.
\item Compile the code
\begin{code}
$ scalac Main.scala
\end{code}
\item Execute the compiled code
\begin{code}
$ scala Main
\end{code}
\end{enumerate}

\section{Scala REPL}
\begin{enumerate}
\item Start a terminal in Linux or command line in Windows, type 
 \begin{code}
  $ scala
  \end{code}
 Note that the \$ sign is the command prompt, you should not include it as
 part of the command.
\item Exit Scala REPL by typing 
 \begin{code}
 scala> :quit
 \end{code}
 Note that the {\tt scala>} sign is the Scala REPL prompt, you should not include it as
 part of the command.
\end{enumerate}
%$

\section{Variables, Values and Assignment Statement}
In a Scala REPL
\begin{enumerate}
\item Declare a variable with name ``first\_name'' and assign a string
  value as ``robin''.
\item Declare a value with name ``last\_name'' and assign a string
  value as ``Williams''.
\item Update the variable ``first\_name'' to a new string value
  ``Robin''
\item If you were to update the value ``last\_name'' to a new string
  ``Hood'', what will happen?
\end{enumerate}
\comment{
\subsection{Sample Answer}
\begin{code}
scala> var first_name = "robin"
first_name: String = robin

scala> val last_name = "Williams"
last_name: String = Williams

scala> first_name = "Robin"
first_name: String = Robin

scala> last_name = "Hood"
<console>:12: error: reassignment to val
       last_name = "Hood"
                 ^
\end{code}
}
\section{Print Statement}
In a Scala REPL
\begin{enumerate}
\item Print the variable ``first\_name'' and value ``last\_name'' individually
\item Use template, print the following
\begin{code}
Robin William (1951 - 2014) 
\end{code}
You need to make use of the variable ``first\_name'' and value ``last\_name'',
and put 1951 and 2014 into the two additional variables. For instance,
assuming you have defined ``first\_name'' and ``last\_name''.
\begin{code}
val bYear = 1951
val dYear = 2014
println(s"$first_name $last_name ($bYear - $dYear)")
\end{code}

\end{enumerate}
\comment{
\subsection{Sample Answer}
\begin{code}
scala>  val bYear = 1951
bYear: Int = 1951

scala>  val dYear = 2014
dYear: Int = 2014

scala> println(s"$first_name $last_name ($bYear - $dYear)")
Robin Williams (1951 - 2014)
\end{code}
}

\section{If-else}

\begin{enumerate}
\item Type the following code snippet in the Scala REPL and observe the output.
\begin{code}
val i = 1
if (i / 2 >= 0.5) {
  println(s" ${i} / 2 is greater than or equal to  0.5") } 
else { 
   println(s"${i} / 2 is less than 0.5") 
}
\end{code}
\end{enumerate}


\section{List and List operation}

\begin{enumerate}
\item Declare a list of integer {\tt l1} with integers 1, 2, 3 and 4.
\item Declare a second list {\tt l2} whose elements are the odd values of {\tt
    l1} incremented by 1.
\item Find out the head and the tail of {\tt l2}.
\item Reverse {\tt l2}.
\item Concatenate {\tt l1} and {\tt l2}
\item Compute the sum of {\tt l1}
\end{enumerate}

\comment{
\subsection{Sample Answer}
\begin{code}
scala> val l1 = List(1,2,3,4)
l1: List[Int] = List(1, 2, 3, 4)

scala> val l2 = for { x <- l1; if x \% 2 == 1} yield (x + 1)// or
l2: List[Int] = List(2, 4)

scala> val l2a = l1.filter ( x => x \% 2 == 1 ).map( x => x + 1)
l2a: List[Int] = List(2, 4)

scala> l2.head
res0: Int = 2

scala> l2.tail
res1: List[Int] = List(4)

scala> l2.reverse
res2: List[Int] = List(4, 2)

scala> l1 ++ l2
res3: List[Int] = List(1, 2, 3, 4, 2, 4)

scala> l1.foldLeft(0)( (s,x) => s + x )
res4: Int = 10
\end{code}
}

\section{Object Oriented Programming}

\begin{enumerate}
\item In the terminal, change the working directory to {\tt
    {}~/git/learning-scala/codes/oop}.
\item Examine the code {\tt OOP.scala}, are you able to identify the
  class constructors, member fields, member methods? Are you able to
  identify the class inheritence? 
\begin{code}
class Person(n:String,i:String) {
	private val name:String = n
	private val id:String   = i
	def getName():String = name
	def getId():String = id
}

trait NightOwl {
	def stayUpLate():Unit
}

class Student(n:String, i:String, g:Double) extends Person(n,i) with NightOwl {
	private var gpa = g
	def getGPA() = gpa
	def setGPA(g:Double) =
	{
		gpa = g
	}
	override def stayUpLate():Unit =
	{
		println("woohoo")
	}
}

class Staff(n:String, i:String, sal:Double) extends Person(n,i) {
	private var salary = sal
	def getSalary() = salary
	def setSalary(sal:Double) =
	{
		salary = sal
	}
}
\end{code}
\item Load the class in the Scala REPL and test it out
\begin{code}
scala> :load OOP.scala
Loading OOP.scala...
defined class Person
defined trait NightOwl
defined class Student
defined class Staff

scala> val tom = new Student("Tom", "X1235", 4.0)
tom: Student = Student@601c1dfc

scala> val jerry = new Staff("Jerry", "T0001", 500000.0)
jerry: Staff = Staff@650fbe32

scala> tom.stayUpLate
woohoo
\end{code}
\end{enumerate}

\section{Functional Programming in Scala}
\begin{enumerate}
\item In the terminal, change the working directory to {\tt
    {}~/git/learning-scala/codes/fp}.
\item Examine the code {\tt Exp.scala}, are you able to identify the
  sealed trait, the case class, and the pattern matching?
\begin{code}
sealed trait Exp
case class Val(v:Int) extends Exp
case class Plus(e1:Exp, e2:Exp) extends Exp

def simp(e:Exp):Exp = e match
{
	case Val(v) => e
	case Plus(Val(0), e2) => e2
	case Plus(e1,e2) => Plus(simp(e1), simp(e2))
}
\end{code}

\item Run it with Scala REPL
\begin{code}
$ scala
scala> :load Exp.scala
scala> val e = Plus(Val(0), Plus(Val(1), Val(2)))
e: Plus = Plus(Val(0),Plus(Val(1),Val(2)))

scala> simp(e)
res0: Exp = Plus(Val(1),Val(2))
\end{code}
%$
\item Note that $x - 0 = x$, $x * 1 = x$, $x / 1 = x$ for all $x$, can
  we extend our {\tt Exp} data type and the simplification {\tt simp} to handle minus, multiplication, and division?
\item Note that the simplification is not througout, e.g. 
\begin{code}
scala> val e2 = Plus(Val(0), Plus(Val(0),Val(2)))
e2: Plus = Plus(Val(0),Plus(Val(0),Val(2)))

scala> simp(e2)
res1: Exp = Plus(Val(0),Val(2))
\end{code}
How can we fix it?
\end{enumerate}

\comment{
\subsection{Sample Answer}

\begin{code}
sealed trait Exp
case class Val(v:Int) extends Exp
case class Plus(e1:Exp, e2:Exp) extends Exp
case class Minus(e1:Exp, e2:Exp) extends Exp
case class Mult(e1:Exp, e2:Exp) extends Exp
case class Div(e1:Exp, e2:Exp) extends Exp

def simp(e:Exp):Exp = e match
{
        case Val(v)            => e
        case Plus(Val(0), e2)  => e2
        case Plus(e1, Val(0))  => e1
        case Plus(e1,e2)       => Plus(simp(e1), simp(e2))
        case Minus(e1, Val(0)) => e1
        case Minus(e1, e2)     => Minus(simp(e1), simp(e2))
        case Mult(Val(1), e2)  => e2
        case Mult(e1, Val(1))  => e1
        case Mult(e1, e2)      => Mult(simp(e1), simp(e2))
        case Div(e1, Val(1))   => e1
        case Div(e1, e2)       => Div(simp(e1), simp(e2))
}

def simpFix(e:Exp):Exp =
{
        val e2 = simp(e)
        if (e == e2)
        {
                e
        }
        else
        {
                simpFix(e2)
        }
}
\end{code}
}


%\item Implement An Interpreter of Lambda Calculus 


\section{Data Processing}

\subsection{CSV}

Given a CSV file as follows,
\begin{code}
user1,account1,230
user2,account2,130
user3,account3,40
user4,account4,34
user5,account5,23
user6,account6,20
user7,account7,199
user8,account8,324
user9,account9,159
user10,account10,123
\end{code}

The following Scala code loads the CSV file from the file system and
replaces the commas by ``$|$'' , prints out the lines on the standard
output and writes the lines into an output file

\begin{code}
object DataProc extends App {
  import java.io._
  val inFile = io.Source.fromFile("./input.csv")
  val outFile = new PrintWriter(new File("./output.txt" ))
  for (line <- inFile.getLines) {
    val cols = line.split(",").map(_.trim)
    println(s"${cols(0)}|${cols(1)}|${cols(2)}")
    outFile.write(s"${cols(0)}|${cols(1)}|${cols(2)}\n")
  }
  inFile.close
  outFile.close
}
\end{code}


The output.txt will looks like
\begin{code}
user1|account1|230
user2|account2|130
user3|account3|40
user4|account4|34
user5|account5|23
user6|account6|20
user7|account7|199
user8|account8|324
user9|account9|159
user10|account10|123
\end{code}


\begin{enumerate}
 \item  Modify the above code to find and write the min, max, mean,
   median of the account balance (the third column). The output.txt
   should look like
\begin{code}
min: 20
max: 324
mean: 128
median: 126
\end{code}
  Hint: to convert a string value into integer, you may use the {\tt
    toInt} method
  following
\begin{code}
scala> val x = "1"
x: String = 1
scala> x.toInt
res0: Int = 1
\end{code}
 \item In the last task, if your implementation of finding the min,
   max, mean and median requires the use of for-loop, can you rewrite
   it using {\tt map}, {\tt sortWith} and {\tt foldLeft}?
\end{enumerate}


\subsection{JSON}

JSON is another popular data type format. Many libraries allow us to map a relation between a
Scala data structure and a JSON object. One of them is {\tt gson}.

The following example code demonstrates how a Scala case class {\tt
  Contact} (A phone contact) be converted to and from JSON objects.

\begin{code}
import com.google.gson.Gson

object JSONExample extends App {
    case class Contact(firstName: String, lastName: String, phone: Int)
    val ironman = new Contact("Tony", "Stark", 12345678)
    val gson = new Gson
    println(gson.toJson(ironman))
    val cap = gson.fromJson("""
        {"firstName":"Steve","lastName":"Roger","phone":0}
    """, classOf[Contact]
    )
    println(gson.toJson(cap))
}
\end{code}

Using {\tt scala} directly to interpret the {\tt
  JSONExample.scala} file won't work, because gson demands the existence of the
class for conversion, (in this case, the class {\tt Contact} needs to
be compiled first before the conversion taking place. We first compile
then run
\begin{code}
  $ scalac JSONExample.scala  -cp gson-2.3.1.jar
  $ scala -cp ./gson-2.3.1.jar:. JSONExample
\end{code}
We see the following output
\begin{code}
{"firstName":"Tony","lastName":"Stark","phone":12345678}
{"firstName":"Steve","lastName":"Roger","phone":0}
\end{code}

Based on the example above, write a Scala program to turn the
  following JSON file
  \begin{code}
{
   "library": [	
      {
         "id":"01",
         "language": "Java",
         "edition": "third",
         "author": "Herbert Schildt"
      },	
      {
         "id":"07",
         "language": "C++",
         "edition": "second",
         "author": "E.Balagurusamy"
      }
   ]
}
  \end{code}
  Into a CSV file
  \begin{code}
    01,Java,third,Herbert Schildt
    07,C++,second,E.Balagurursamy
  \end{code}  

%
Hint, you may considering using the following data type to transform
the JSON object into CSV format
\begin{code}
    case class Book(id:String, language:String, edition:String, author:String)
    case class Library(books:Array[Book])
  \end{code}


Other implementations of JSON conversion in Scala can be found in the
following 
\begin{enumerate}
\item
\begin{verbatim}
https://app.assembla.com/spaces/liftweb/wiki/JSON_Support
\end{verbatim}
\item
\begin{verbatim}
https://www.playframework.com/documentation/2.6.x/ScalaJson
\end{verbatim}
\end{enumerate}


\subsection{Regex}

Regular expression is a powerful embeded language to match extract
sequence of items, for instance strings. For instance the following
regex extract all anchored link from a HTML page.
\begin{code}
<a href=\"([^.]*)\"[^>]*>
\end{code}
Note that the sub pattern
\begin{code}
  href=\"([^\"]*)\"
\end{code}
performs most of the extraction. The parantheses define a capturing group which captures and stores the
link for output usage. The sub pattern
\begin{code}
 [\^"]*
\end{code}
matches string of any length as
long as it does not contain the double quote.

By embedding the above regex in our Scala code as follows, we are able
to extract all links in a HTML page.
\begin{code}
import java.io._
object LinkExtractor extends App {

    val inFile = io.Source.fromFile("./page.html")
    val outFile = new PrintWriter(new File("./output.txt" ))
    val anchor = """.*<a href=\"([^"]*)\"[^>]*>.*""".r
    val links = for (line <- inFile.getLines)  {
        line match {
            case anchor(link) => 
                outFile.write(s"${link}\n")
            case _ => () 
        }
    }
    inFile.close
    outFile.close
}
\end{code}
%$

Note that there is a problem with the above implementation, it only
extracts the first match in every line if there exists a match. To
explore all sub matches in a line, we need to use the {\tt findAllIn}
method.
\begin{code}

import java.io._
object LinkExtractor2 extends App {
    val inFile = io.Source.fromFile("./page.html")
    val outFile = new PrintWriter(new File("./output.txt" ))
    val anchor = """<a href=\"([^"]*)\"[^>]*>""".r
    val links = for (line <- inFile.getLines) {
        for (link <- anchor.findAllIn(line)) {
            outFile.write(s"${link}\n")
        }
    }
    inFile.close
    outFile.close
}
\end{code}
%$

For all the valid syntax of regex and testing of regex, please refer to
\begin{verbatim}
https://regex101.com/
\end{verbatim}

\subsection{Stop words removal}
Stop words such as ``the'', ``a'', ``is'' are too common to make a
different in text analytics model. It is a common practice to remove
them from the corpuses before processing. The following Scala script
does the remove by refering to a predefine set of stop words.
\begin{code}
import java.io._

object StopWords extends App {
  val inFile = io.Source.fromFile("./input.txt")
  val outFile = new PrintWriter(new File("./output.txt" ))
  // TODO: read the stop words from a file.
  val stop_words = List("and", "is", "it", "are", "in", "rt", "what", "from",
                "her", "to", "their", "you", "me", "his", "http", "that", "they", "by",
                "he", "a", "on", "for", "i", "of", "this", "she", "the", "my", "at").toSet
  for (line <- inFile.getLines) {
    val words = line.toLowerCase.split(" ").map(_.trim)
    val no_stopwords = words.filter( w => !stop_words.contains(w))
    outFile.write(no_stopwords.mkString(" ") + "\n")
  }
  inFile.close
  outFile.close
}
\end{code} 
%
Given the {\tt input.txt} file contains the following 
\begin{code}
The quick brown fox jumps over the lazy dog
\end{code}
the {\tt output.txt} file will be generated with the following content
\begin{code}
quick brown fox jumps over lazy dog
\end{code}

Your task is to modify the above script so that the stop words are
read from a file {\tt stopwords.txt} instead of being hard-coded in
the script. 

\subsection{Word count}
To generate infographic with word cloud, we have to count the number
of occurrences of all the words appearing in the corpuses.  For
instance, the word count of the following file
\begin{code}
hey diddle diddle
the cat and the fiddle
the cow jumped over the
 moon
the little dog laughed
to see such sport
and the dish ran away
 with the spoon
\end{code}

Will be 
\begin{code}
,2
moon,1
jumped,1
cow,1
ran,1
dog,1
such,1
dish,1
to,1
spoon,1
sport,1
over,1
diddle,2
little,1
with,1
cat,1
see,1
hey,1
away,1
and,2
laughed,1
the,7
fiddle,1
\end{code}

There are two possible implementation of the word count. The first
implementation uses imperative style (similar to Java) 
\begin{code}
import java.io._
import scala.collection._
object WordCount extends App {
  val inFile = io.Source.fromFile("./input.txt")
  val outFile = new PrintWriter(new File("./output.txt" ))
  var dict = Map[String,Int]()
  for (line <- inFile.getLines) {
    val words = line.split(" ")
    for (w <- words) {
      dict.get(w) match {
        case None => dict = dict + ((w,1))
        case Some(counts) => dict = dict + ((w,counts + 1))
      }
    }
  }
  val wordCount = dict.toList
  for ( wc <- wordCount ) {
    outFile.write(s"${wc._1},${wc._2}\n")
  }
  inFile.close
  outFile.close
}
\end{code}
The second implementation uses functional programming (map and fold) 
\begin{code}
import java.io._
import scala.collection._
object WordCountFun extends App {
  val inFile = io.Source.fromFile("./input.txt")
  val outFile = new PrintWriter(new File("./output.txt" ))
  val words = inFile.getLines.toList.flatMap( line => line.split(" ") )
  val empty_dict = Map[String,List[Int]]()
  val wordCount = words.map(w => (w,1))
          .foldLeft(empty_dict)( (dict,t) => t match {
            case (w,one) => dict.get(w) match {
              case None => dict + ((w,List(one)))
              case Some(ones) => dict + ((w,ones ++ List(one)))
            }
          })
          .toList
          .map( wl => wl match {
            case (w,l) => (w,l.sum)
          })
  for ( wc <- wordCount ) {
    outFile.write(s"${wc._1},${wc._2}\n")
  }
  inFile.close
  outFile.close
}
\end{code}


\subsection{TF-IDF}

\begin{itemize}
 \item TF-IDF stands for Term frequency - Inverse document
   frequency. It is a classic and powerful technique to search for
   interesting terms from a set of documents.
 \item TF is actually the word count. For instance, consider the
   following two values found in some input text file.
   \begin{code}
      apple smart phone
      android smart phone
   \end{code}
   The term frequency is 
   \begin{code}
     apple, 1
     android, 1
     phone, 2
     smart, 2
   \end{code}
 \item IDF is is the total number of documents/records divided by the
   total number of the documents/records containing the words. We
   apply logarithmic to the quotient.
  The IDF for the above example is 
 \begin{code}
    apple, log(2/1) 
    android, log(2/1)
    phone, log(2/2)
    smart, log(2/2) 
  \end{code}
   that is 
 \begin{code}
    apple, 0.693
    android, 0.693
    phone, 0
    smart, 0
  \end{code}
  \item TF-IDF is obtained by multiplying the TF with the IDF.
 \begin{code}
    apple, 0.693
    android, 0.693
    phone, 0
    smart, 0
  \end{code}
  This shows that apple and android are the interesting terms coming
  from the records.
 \item Please use Scala to develop a script to compute the
   TF-IDF of a given file containing text.
\end{itemize}


\end{document}
