--- a/cws/cw02.tex Mon Nov 02 13:10:02 2020 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-% !TEX program = xelatex
-\documentclass{article}
-\usepackage{../style}
-\usepackage{disclaimer}
-\usepackage{../langs}
-
-\begin{document}
-
-
-%% should ask to lower case the words.
-
-\section*{Part 7 (Scala)}
-
-\mbox{}\hfill\textit{``What one programmer can do in one month,}\\
-\mbox{}\hfill\textit{two programmers can do in two months.''}\smallskip\\
-\mbox{}\hfill\textit{ --- Frederick P.~Brooks (author of The Mythical Man-Month)}\bigskip\medskip
-
-\noindent
-You are asked to implement Scala programs for measuring similarity in
-texts, and for recommending movies according to a ratings list. The
-preliminary part~(4\%) is due on \cwSEVEN{} at 4pm; the core part is due
-on \cwSEVENa{} at 4pm. Note the core part might include material you
-have not yet seen in the first two lectures. \bigskip
-
-\IMPORTANT{}
-
-\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 docdiff.jar} and then
-query any function from the template file. Say you want to find out
-what the function \texttt{occurrences} produces: for this you just need
-to prefix it with the object name \texttt{CW7a} (and \texttt{CW7b}
-respectively for \texttt{danube.jar}). 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 docdiff.jar
-
-scala> CW7a.occurrences(List("a", "b", "b"))
-...
-\end{lstlisting}%$
-
-\subsection*{Hints}
-
-\noindent
-\textbf{For Preliminary Part:} useful operations involving regular
-expressions:
-\[\texttt{reg.findAllIn(s).toList}\]
-\noindent finds all
-substrings in \texttt{s} according to a regular regular expression
-\texttt{reg}; useful list operations: \texttt{.distinct}
-removing duplicates from a list, \texttt{.count} counts the number of
-elements in a list that satisfy some condition, \texttt{.toMap}
-transfers a list of pairs into a Map, \texttt{.sum} adds up a list of
-integers, \texttt{.max} calculates the maximum of a list.\bigskip
-
-\noindent
-\textbf{For Core Part:} use \texttt{.split(",").toList} for splitting
-strings according to commas (similarly $\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*{Preliminary Part (4 Marks, file docdiff.scala)}
-
-It seems source code plagiarism---stealing and submitting someone
-else's code---is a serious problem at other
-universities.\footnote{Surely, King's students, after all their
- instructions and warnings, would never commit such an offence. Yes?}
-Detecting such plagiarism is time-consuming and disheartening for
-lecturers at those universities. To aid these poor souls, let's
-implement in this part a program that determines the similarity
-between two documents (be they source code or texts in English). A
-document will be represented as a list of strings.
-
-
-\subsection*{Tasks}
-
-\begin{itemize}
-\item[(1)] Implement a function that `cleans' a string by finding all
- (proper) words in this string. For this use the regular expression
- \texttt{\textbackslash{}w+} for recognising words and the library function
- \texttt{findAllIn}. The function should return a document (a list of
- strings).\\
- \mbox{}\hfill [1 Mark]
-
-\item[(2)] In order to compute the overlap between two documents, we
- associate each document with a \texttt{Map}. This Map represents the
- strings in a document and how many times these strings occur in the
- document. A simple (though slightly inefficient) method for counting
- the number of string-occurrences in a document is as follows: remove
- all duplicates from the document; for each of these (unique)
- strings, count how many times they occur in the original document.
- Return a Map associating strings with occurrences. For example
-
- \begin{center}
- \pcode{occurrences(List("a", "b", "b", "c", "d"))}
- \end{center}
-
- produces \pcode{Map(a -> 1, b -> 2, c -> 1, d -> 1)} and
-
- \begin{center}
- \pcode{occurrences(List("d", "b", "d", "b", "d"))}
- \end{center}
-
- produces \pcode{Map(d -> 3, b -> 2)}.\hfill[1 Mark]
-
-\item[(3)] You can think of the Maps calculated under (2) as memory-efficient
- representations of sparse ``vectors''. In this subtask you need to
- implement the \emph{product} of two such vectors, sometimes also called
- \emph{dot product} of two vectors.\footnote{\url{https://en.wikipedia.org/wiki/Dot_product}}
-
- For this dot product, implement a function that takes two documents
- (\texttt{List[String]}) as arguments. The function first calculates
- the (unique) strings in both. For each string, it multiplies the
- corresponding occurrences in each document. If a string does not
- occur in one of the documents, then the product for this string is zero. At the end
- you need to add up all products. For the two documents in (2) the dot
- product is 7, because
-
- \[
- \underbrace{1 * 0}_{"a"} \;\;+\;\;
- \underbrace{2 * 2}_{"b"} \;\;+\;\;
- \underbrace{1 * 0}_{"c"} \;\;+\;\;
- \underbrace{1 * 3}_{"d"} \qquad = 7
- \]
-
- \hfill\mbox{[1 Mark]}
-
-\item[(4)] Implement first a function that calculates the overlap
- between two documents, say $d_1$ and $d_2$, according to the formula
-
- \[
- \texttt{overlap}(d_1, d_2) = \frac{d_1 \cdot d_2}{max(d_1^2, d_2^2)}
- \]
-
- where $d_1^2$ means $d_1 \cdot d_1$ and so on.
- You can expect this function to return a \texttt{Double} between 0 and 1. The
- overlap between the lists in (2) is $0.5384615384615384$.
-
- Second, implement a function that calculates the similarity of
- two strings, by first extracting the substrings using the clean
- function from (1)
- and then calculating the overlap of the resulting documents.\\
- \mbox{}\hfill\mbox{[1 Mark]}
-\end{itemize}\bigskip
-
-
-\subsection*{Core Part (6 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]
-\end{itemize}
-
-\end{document}
-
-%%% Local Variables:
-%%% mode: latex
-%%% TeX-master: t
-%%% End:
--- /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:
+
+
+
Binary file main_solution1/drumb.jar has changed
Binary file main_solution2/danube.jar has changed
--- a/main_solution2/danube.scala Mon Nov 02 13:10:02 2020 +0000
+++ b/main_solution2/danube.scala Wed Nov 04 14:46:03 2020 +0000
@@ -160,20 +160,37 @@
// => List(Shawshank Redemption, Forrest Gump (1994))
// recommendations(ratings_map, movies_map, "4")
-// => Nil (there are three ratings fro this movie in ratings.csv but they are not positive)
+// => Nil (there are three ratings for this movie in ratings.csv but they are not positive)
+
+// (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).
+
+def occurrences(xs: List[String]): List[(String, Int)] =
+ for (x <- xs.distinct) yield (x, xs.count(_ == x))
+
+def most_recommended(recs: Map[String, List[String]],
+ movs: Map[String, String]) : List[(String, Int)] = {
+ val all = (for (name <- movs.toList.map(_._1)) yield {
+ recommendations(recs, movs, name)
+ }).flatten
+ val occs = occurrences(all)
+ occs.sortBy(_._2).reverse
+}
-// If you want to calculate the recomendations for all movies.
-// Will take a few seconds calculation time.
+//most_recommended(ratings_map, movies_map).take(3)
+// =>
+// List((Matrix,698),
+// (Star Wars: Episode IV - A New Hope (1977),402),
+// (Jerry Maguire (1996),382))
-//val all = for (name <- movie_names.map(_._1)) yield {
-// recommendations(ratings_map, movies_map, name)
-//}
-
-// helper functions
-//List().take(2
-//List(1).take(2)
-//List(1,2).take(2)
-//List(1,2,3).take(2)
}
Binary file main_solution3/re.jar has changed
Binary file main_solution4/knight2.jar has changed
Binary file main_solution4/knight3.jar has changed
Binary file main_solution5/bf.jar has changed
Binary file main_solution5/bfc.jar has changed
Binary file main_templates1/drumb.jar has changed
Binary file main_templates2/danube.jar has changed
--- a/main_templates2/danube.scala Mon Nov 02 13:10:02 2020 +0000
+++ b/main_templates2/danube.scala Wed Nov 04 14:46:03 2020 +0000
@@ -157,18 +157,30 @@
// => Nil (there are three ratings for this movie in ratings.csv but they are not positive)
-// If you want to calculate the recommendations for all movies,
-// then use this code (it will take a few seconds calculation time).
+
+// (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).
-//val all = for (name <- movie_names.map(_._1)) yield {
-// recommendations(ratings_map, movies_map, name)
-//}
+def most_recommended(recs: Map[String, List[String]],
+ movs: Map[String, String]) : List[(String, Int)] = ???
+
-// helper functions
-//List().take(2)
-//List(1).take(2)
-//List(1,2).take(2)
-//List(1,2,3).take(2)
+// testcase
+//
+//most_recommended(ratings_map, movies_map).take(3)
+// =>
+// List((Matrix,698),
+// (Star Wars: Episode IV - A New Hope (1977),402),
+// (Jerry Maguire (1996),382))
+
}
Binary file main_templates3/re.jar has changed
Binary file main_templates4/knight2.jar has changed
Binary file main_templates4/knight3.jar has changed
Binary file main_templates5/bf.jar has changed
Binary file main_templates5/bfc.jar has changed
--- a/mk_jars Mon Nov 02 13:10:02 2020 +0000
+++ b/mk_jars Wed Nov 04 14:46:03 2020 +0000
@@ -14,3 +14,9 @@
done
cd ..
done
+
+hg commit -m "updated jars"
+
+# producing solutions and templates
+# tar -zxvf templates.tgz pre_templates* main_templates*
+# tar -zcvf templates.tgz pre_templates* main_templates*
Binary file pre_solution1/collatz.jar has changed
Binary file pre_solution2/docdiff.jar has changed
Binary file pre_solution3/postfix.jar has changed
Binary file pre_solution3/postfix2.jar has changed
Binary file pre_templates1/collatz.jar has changed
Binary file pre_templates2/docdiff.jar has changed
Binary file pre_templates3/postfix.jar has changed
Binary file pre_templates3/postfix2.jar has changed
Binary file pre_templates4/knight1.jar has changed