cws/main_cw02.tex
changeset 349 682611a0fb89
parent 333 24bc76d97db2
child 350 c5ad0e3f2a6d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cws/main_cw02.tex	Wed Nov 04 14:46:03 2020 +0000
@@ -0,0 +1,213 @@
+% !TEX program = xelatex
+\documentclass{article}
+\usepackage{../style}
+\usepackage{disclaimer}
+\usepackage{../langs}
+
+\begin{document}
+
+
+%% should ask to lower case the words.
+
+\section*{Part 7 (Scala, 7 Marks)}
+
+
+\noindent
+You are asked to implement a Scala program for recommending movies
+according to a ratings list. This part is due on \cwSEVENa{} at 5pm.\bigskip
+
+\IMPORTANTNONE{}
+
+\noindent
+Also note that the running time of each part will be restricted to a
+maximum of 30 seconds on my laptop.
+
+\DISCLAIMER{}
+
+
+\subsection*{Reference Implementation}
+
+Like the C++ part, the Scala part works like this: you push your files
+to GitHub and receive (after sometimes a long delay) some automated
+feedback. In the end we will take a snapshot of the submitted files
+and apply an automated marking script to them.\medskip
+
+\noindent
+In addition, the Scala part comes with reference
+implementations in form of \texttt{jar}-files. This allows you to run
+any test cases on your own computer. For example you can call Scala on
+the command line with the option \texttt{-cp danube.jar} and then
+query any function from the template file. Say you want to find out
+what the function \texttt{} produces: for this you just need
+to prefix it with the object name \texttt{CW7b}.  If you want to find out what
+these functions produce for the list \texttt{List("a", "b", "b")},
+you would type something like:
+
+\begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small]
+$ scala -cp danube.jar
+scala> val ratings_url =
+     | """https://nms.kcl.ac.uk/christian.urban/ratings.csv"""
+
+scala> CW7b.get_csv_url(ratings_url)
+val res0: List[String] = List(1,1,4 ...)
+\end{lstlisting}%$
+
+\subsection*{Hints}
+
+\noindent
+Use \texttt{.split(",").toList} for splitting
+strings according to commas (similarly for the newline character \mbox{$\backslash$\texttt{n}}),
+\texttt{.getOrElse(..,..)} allows to query a Map, but also gives a
+default value if the Map is not defined, a Map can be `updated' by
+using \texttt{+}, \texttt{.contains} and \texttt{.filter} can test whether
+an element is included in a list, and respectively filter out elements in a list,
+\texttt{.sortBy(\_.\_2)} sorts a list of pairs according to the second
+elements in the pairs---the sorting is done from smallest to highest,
+\texttt{.take(n)} for taking some elements in a list (takes fewer if the list
+contains less than \texttt{n} elements).
+
+
+\newpage
+
+
+\subsection*{Part (7 Marks, file danube.scala)}
+
+You are creating Danube.co.uk which you hope will be the next big thing
+in online movie renting. You know that you can save money by
+anticipating what movies people will rent; you will pass these savings
+on to your users by offering a discount if they rent movies that
+Danube.co.uk recommends.  
+
+Your task is to generate \emph{two} movie recommendations for every
+movie a user rents. To do this, you calculate what other
+renters, who also watched this movie, suggest by giving positive ratings.
+Of course, some suggestions are more popular than others. You need to find
+the two most-frequently suggested movies. Return fewer recommendations,
+if there are fewer movies suggested.
+
+The calculations will be based on the small datasets which the research lab
+GroupLens provides for education and development purposes.
+
+\begin{center}
+\url{https://grouplens.org/datasets/movielens/}
+\end{center}
+
+\noindent
+The slightly adapted CSV-files should be downloaded in your Scala
+file from the URLs:
+
+
+\begin{center}
+\begin{tabular}{ll}  
+  \url{https://nms.kcl.ac.uk/christian.urban/ratings.csv} & (940 KByte)\\
+  \url{https://nms.kcl.ac.uk/christian.urban/movies.csv}  & (280 KByte)\\
+\end{tabular}
+\end{center}
+
+\noindent
+The ratings.csv file is organised as userID, 
+movieID, and rating (which is between 0 and 5, with \emph{positive} ratings
+being 4 and 5). The file movie.csv is organised as
+movieID and full movie name. Both files still contain the usual
+CSV-file header (first line). In this part you are asked
+to implement functions that process these files. If bandwidth
+is an issue for you, download the files locally, but in the submitted
+version use \texttt{Source.fromURL} instead of \texttt{Source.fromFile}.
+
+\subsection*{Tasks}
+
+\begin{itemize}
+\item[(1)] Implement the function \pcode{get_csv_url} which takes an
+  URL-string as argument and requests the corresponding file. The two
+  URLs of interest are \pcode{ratings_url} and \pcode{movies_url},
+  which correspond to CSV-files mentioned above.  The function should
+  return the CSV-file appropriately broken up into lines, and the
+  first line should be dropped (that is omit the header of the CSV-file).
+  The result is a list of strings (the lines in the file). In case
+  the url does not produce a file, return the empty list.\\
+  \mbox{}\hfill [1 Mark]
+
+\item[(2)] Implement two functions that process the (broken up)
+  CSV-files from (1). The \pcode{process_ratings} function filters out all
+  ratings below 4 and returns a list of (userID, movieID) pairs. The
+  \pcode{process_movies} function returns a list of (movieID, title) pairs.
+  Note the input to these functions will be the output of the function
+  \pcode{get_csv_url}.\\
+  \mbox{}\hfill [1 Mark]
+%\end{itemize}  
+%  
+%
+%\subsection*{Part 3 (4 Marks, file danube.scala)}
+%
+%\subsection*{Tasks}
+%
+%\begin{itemize}
+\item[(3)] Implement a kind of grouping function that calculates a Map
+  containing the userIDs and all the corresponding recommendations for
+  this user (list of movieIDs). This should be implemented in a
+  tail-recursive fashion using a Map as accumulator. This Map is set to
+  \pcode{Map()} at the beginning of the calculation. For example
+
+\begin{lstlisting}[numbers=none]
+val lst = List(("1", "a"), ("1", "b"),
+               ("2", "x"), ("3", "a"),
+               ("2", "y"), ("3", "c"))
+groupById(lst, Map())
+\end{lstlisting}
+
+returns the ratings map
+
+\begin{center}
+  \pcode{Map(1 -> List(b, a), 2 -> List(y, x), 3 -> List(c, a))}.
+\end{center}
+
+\noindent
+In which order the elements of the list are given is unimportant.\\
+\mbox{}\hfill [1 Mark]
+
+\item[(4)] Implement a function that takes a ratings map and a movieID
+  as arguments.  The function calculates all suggestions containing the
+  given movie in its recommendations. It returns a list of all these
+  recommendations (each of them is a list and needs to have the given
+  movie deleted, otherwise it might happen we recommend the same movie
+  ``back''). For example for the Map from above and the movie
+  \pcode{"y"} we obtain \pcode{List(List("x"))}, and for the movie
+  \pcode{"a"} we get \pcode{List(List("b"), List("c"))}.\\
+  \mbox{}\hfill [1 Mark]
+
+\item[(5)] Implement a suggestions function which takes a ratings map
+  and a movieID as arguments. It calculates all the recommended movies
+  sorted according to the most frequently suggested movie(s) sorted
+  first. This function returns \emph{all} suggested movieIDs as a list of
+  strings.\\
+  \mbox{}\hfill [1 Mark]
+
+\item[(6)]  
+  Implement then a recommendation function which generates a maximum
+  of two most-suggested movies (as calculated above). But it returns
+  the actual movie name, not the movieID. If fewer movies are recommended,
+  then return fewer than two movie names.\\
+  \mbox{}\hfill [1 Mark]
+
+\item[(7)] Calculate the recommendations for all movies according to
+ what the recommendations function in (6) produces (this
+ can take a few seconds). Put all recommendations into a list 
+ (of strings) and count how often the strings occur in
+ this list. This produces a list of string-int pairs,
+ where the first component is the movie name and the second
+ is the number of how many times they were recommended. 
+ Sort all the pairs according to the number
+ of times they were recommended (most recommended movie name 
+ first).\mbox{}\hfill [1 Mark]
+  
+\end{itemize}
+
+\end{document} 
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: t
+%%% End: 
+
+
+