--- a/cws/build Mon Dec 26 16:49:53 2022 +0000
+++ b/cws/build Sat Jan 14 14:13:16 2023 +0000
@@ -1,7 +1,7 @@
#!/bin/bash
set -euo pipefail
-fls=${1:-"core_cw01.tex core_cw02.tex core_cw03.tex main_cw01.tex main_cw02.tex main_cw03.tex main_cw04.tex main_cw05.tex"}
+fls=${1:-"core_cw01.tex core_cw02.tex core_cw03.tex main_cw01.tex main_cw02.tex main_cw03.tex main_cw04.tex main_cw05.tex resit.tex"}
for f in $fls; do
echo -e "making $f"
Binary file cws/core_cw01.pdf has changed
Binary file cws/core_cw02.pdf has changed
Binary file cws/core_cw03.pdf has changed
Binary file cws/main_cw01.pdf has changed
Binary file cws/main_cw02.pdf has changed
--- a/cws/main_cw02.tex Mon Dec 26 16:49:53 2022 +0000
+++ b/cws/main_cw02.tex Sat Jan 14 14:13:16 2023 +0000
@@ -43,7 +43,7 @@
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
+the command line with the option \texttt{-cp wordle.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{M2}. If you want to find out what
@@ -77,7 +77,7 @@
\newpage
-\subsection*{Main Part 2 (6 Marks, file wordle.scala)}
+\subsection*{Main Part 2 (7 Marks, file wordle.scala)}
You probably know the game of Wordle\footnote{\url{https://en.wikipedia.org/wiki/Wordle}}
where you are supposed to guess a five-letter word. The feedback for guesses can help
Binary file cws/main_cw03.pdf has changed
Binary file cws/main_cw04.pdf has changed
Binary file cws/main_cw05.pdf has changed
--- a/cws/resit.tex Mon Dec 26 16:49:53 2022 +0000
+++ b/cws/resit.tex Sat Jan 14 14:13:16 2023 +0000
@@ -11,12 +11,12 @@
%% should ask to lower case the words.
-\section*{Resit: Evil Wordle Game (Scala, 6 Marks)}
+\section*{Resit: Evil Wordle Game (Scala, 7 Marks)}
\noindent
You are asked to implement a Scala program for making the popular Wordle game as difficult
-as possible. The deadline for your submission is on 4th August at 16:00. There will be no
+as possible. The deadline for your submission is on 24th January at 23:00. There will be no
automated tests for the resit, but there are plenty of testcases in the template and the
task description. \bigskip
@@ -46,7 +46,7 @@
\newpage
-\subsection*{Resit (6 Marks, file wordle.scala)}
+\subsection*{Resit (7 Marks, file wordle.scala)}
You probably know the game of Wordle\footnote{\url{https://en.wikipedia.org/wiki/Wordle}}
where you are supposed to guess a five-letter word. The feedback for guesses can help
@@ -75,6 +75,7 @@
file locally, but in the submitted version use \texttt{Source.fromURL}
instead of \texttt{Source.fromFile}.
+
\subsection*{Tasks}
\begin{itemize}
@@ -82,25 +83,31 @@
URL-string as argument and requests the corresponding file. The function should
return the word list appropriately broken up into lines.
The result should be a list of strings (the lines in the file). In case
- the url does not produce a file, return the empty list.\\
- \mbox{}\hfill [0.25 Marks]
+ the url does not produce a file, return the empty list.
-\item[(2)] Implement a polymorphic function \pcode{removeN}, which removes $n$ occurences of an
- element from a list (if this element is less than $n$ times pressent, then remove all occurences).
+ In what follows we will use \texttt{secrets} to refer to the list of words listed
+ in \texttt{wordle.txt}.
+
+ \mbox{}\hfill [0.5 Marks]
+
+\item[(2)] Implement a polymorphic function \pcode{removeN}, which removes $n$ occurrences of an
+ element from a list (if this element is less than $n$ times present, then remove all occurrences).
For example
\begin{lstlisting}[numbers=none]
-removeN(List(1,2,3,2,1), 3, 2) => List(1, 2, 2, 1)
-removeN(List(1,2,3,2,1), 2, 1) => List(1, 3, 2, 1)
-removeN(List(1,2,3,2,1), 2, 2) => List(1, 3, 1)
-removeN(List(1,2,3,2,1), 1, 1) => List(2, 3, 2, 1)
-removeN(List(1,2,3,2,1), 1, 3) => List(2, 3, 2)
-removeN(List(1,2,3,2,1), 0, 2) => List(1, 2, 3, 2, 1)
+removeN(List(1,2,3,2,1), 3, 2) => List(1, 2, 2, 1)
+removeN(List(1,2,3,2,1), 2, 1) => List(1, 3, 2, 1)
+removeN(List(1,2,3,2,1), 2, 2) => List(1, 3, 1)
+removeN(List(1,2,3,2,1), 1, 1) => List(2, 3, 2, 1)
+removeN(List(1,2,3,2,1), 1, 3) => List(2, 3, 2)
+removeN(List(1,2,3,2,1), 0, 2) => List(1, 2, 3, 2, 1)
+removeN(List("1","2","3","2","1"), "1", 1)
+ => List("2","3","2","1")
\end{lstlisting}
Make sure you only remove at most $n$ occurrences of the element from the list.
-This function should work for lists of intergers but also lists of chars, strings etc.\\
- \mbox{}\hfill [0.25 Marks]
+This function should work for lists of integers but also lists of chars, strings etc.\\
+ \mbox{}\hfill [0.5 Marks]
\item[(3)] Implement a function \pcode{score} that calculates the
feedback for a word against a secret word using the rules of the
@@ -136,7 +143,7 @@
If they are not the same, but the letter is in the pool, then return \pcode{Present} and also remove
this letter from the pool in the next recursive call of \pcode{aux}. Otherwise return \pcode{Absent} for the
corresponding position. The function \pcode{score} is a wrapper for the function \pcode{aux}
- calling \pcode{aux} with the appropriate arguments (recall what is calculated with \pcode{pool}).\mbox{}\hfill [1.5 Marks]
+ calling \pcode{aux} with the appropriate arguments (recall what is calculated with \pcode{pool}).\mbox{}\hfill [2 Marks]
\item[(4)] Implement a function \pcode{eval} that gives an integer value to each of the
\pcode{Tip}s such that
@@ -182,11 +189,12 @@
where \pcode{secrets} is the list generated under Task 1.
In all cases above the iscore of the resulting secrets is 0, but this does not need to be the case
-in general.\\
+in general.
+
\mbox{}\hfill [1.5 Marks]
\item[(6)] The secrets generated in Task 5 are the ones with the lowest score
- with respect to the word, or the secrets that are furthest ``away'' from the
+ with respect to the word. You can think of these as the secrets that are furthest ``away'' from the
given word. This is already quite evil for a secret word---remember we can choose
a secret \emph{after} a user has given a first word. Now we want to make it
even more evil by choosing words that have the most obscure letters. For this we
@@ -209,7 +217,9 @@
\item[(7)] In this task we want to use the output of \pcode{evil}, rank each string in the
generated set and then filter out the strings that are ranked highest (the ones with the most obscure letters).
This list of strings often contains only a single word, but in general there might be more (see below).
- First implement a function \pcode{rank} that takes a frequency map (from 6) and a string as arguments and
+ First implement a function \pcode{rank} that takes a frequency map (from 6) and a string as arguments.
+ In the testcases, the frequency map is generated for all words in \texttt{secrets}, that is the
+ whole list in \texttt{wordle.txt}. The function
generates a rank by summing up all frequencies of the letters in the string. For example
\begin{lstlisting}[numbers=none]
@@ -229,36 +239,9 @@
ranked_evil(secrets, "zippy") => List(chuff)
\end{lstlisting}
-This means if the user types in "abbey" then the most evil word to choose as secret is "whizzy" (according to
+This means if the user types in "abbey" then the most evil word to choose as secret is ``whizz'' (according to
our calculations). This word has a zero \pcode{iscore} and the most obscure letters.
-%
-%\color{red}
-%\section*{Correction with \texttt{ranked\_evil}}
-%
-%The testcases above are actually not the maximum, but the minimum! I will make sure
-%that the task will count as solved when either the minimum (as above) or the maximum (as intended)
-%is used. The correct solutions for the above testcases using the maximum are:
-%\color{black}
-%
-%\begin{lstlisting}[numbers=none]
-%ranked_evil(secrets, "beats") => List(fuzzy)
-%ranked_evil(secrets, "vitae") => List(fuzzy)
-%ranked_evil(secrets, "bento") => List(fuzzy)
-%ranked_evil(secrets, "belts") => List(fuzzy)
-%\end{lstlisting}
-%
-%\noindent \textcolor{red}{Some further testcases for the maximum are:}
-%
-%\begin{lstlisting}[numbers=none]
-%ranked_evil(secrets, "abbey") => List(whizz)
-%ranked_evil(secrets, "afear") => List(buzzy)
-%ranked_evil(secrets, "zincy") => List(jugum)
-%ranked_evil(secrets, "zippy") => List(chuff)
-%\end{lstlisting}
-%
-%
-
\mbox{}\hfill [1 Mark]
\end{itemize}
--- a/cws/upload Mon Dec 26 16:49:53 2022 +0000
+++ b/cws/upload Sat Jan 14 14:13:16 2023 +0000
@@ -1,7 +1,7 @@
#!/bin/bash
set -euo pipefail
-fls=${1:-"core_cw01.pdf core_cw02.pdf core_cw03.pdf main_cw01.pdf main_cw02.pdf main_cw03.pdf main_cw04.pdf main_cw05.pdf"}
+fls=${1:-"core_cw01.pdf core_cw02.pdf core_cw03.pdf main_cw01.pdf main_cw02.pdf main_cw03.pdf main_cw04.pdf main_cw05.pdf resit.pdf"}
for f in $fls; do
echo -e "uploading $f"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_templates2/resit.scala Sat Jan 14 14:13:16 2023 +0000
@@ -0,0 +1,78 @@
+// Resit about Evil Wordle
+//==========================
+
+
+object Resit {
+
+import io.Source
+import scala.util._
+
+// ADD YOUR CODE BELOW
+//======================
+
+
+//(1)
+def get_wordle_list(url: String) : List[String] = ???
+
+// val secrets = get_wordle_list("https://nms.kcl.ac.uk/christian.urban/wordle.txt")
+// secrets.length // => 12972
+// secrets.filter(_.length != 5) // => Nil
+
+//(2)
+def removeN[A](xs: List[A], elem: A, n: Int) : List[A] = ???
+
+
+// removeN(List(1,2,3,2,1), 3, 1) // => List(1, 2, 2, 1)
+// removeN(List(1,2,3,2,1), 2, 1) // => List(1, 3, 2, 1)
+// removeN(List(1,2,3,2,1), 1, 1) // => List(2, 3, 2, 1)
+// removeN(List(1,2,3,2,1), 0, 2) // => List(1, 2, 3, 2, 1)
+
+// (3)
+abstract class Tip
+case object Absent extends Tip
+case object Present extends Tip
+case object Correct extends Tip
+
+
+def pool(secret: String, word: String) : List[Char] = ???
+
+def aux(secret: List[Char], word: List[Char], pool: List[Char]) : List[Tip] = ???
+
+def score(secret: String, word: String) : List[Tip] = ???
+
+
+// score("chess", "caves") // => List(Correct, Absent, Absent, Present, Correct)
+// score("doses", "slide") // => List(Present, Absent, Absent, Present, Present)
+// score("chess", "swiss") // => List(Absent, Absent, Absent, Correct, Correct)
+// score("chess", "eexss") // => List(Present, Absent, Absent, Correct, Correct)
+
+// (4)
+def eval(t: Tip) : Int = ???
+
+def iscore(secret: String, word: String) : Int = ???
+
+//iscore("chess", "caves") // => 21
+//iscore("chess", "swiss") // => 20
+
+// (5)
+def lowest(secrets: List[String], word: String, current: Int, acc: List[String]) : List[String] = ???
+
+def evil(secrets: List[String], word: String) : List[String] = ???
+
+
+//evil(secrets, "stent").length
+//evil(secrets, "hexes").length
+//evil(secrets, "horse").length
+//evil(secrets, "hoise").length
+//evil(secrets, "house").length
+
+// (6)
+def frequencies(secrets: List[String]) : Map[Char, Double] = ???
+
+// (7)
+def rank(frqs: Map[Char, Double], s: String) : Double = ???
+
+def ranked_evil(secrets: List[String], word: String) : List[String] = ???
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_templates2/wordle.scala Sat Jan 14 14:13:16 2023 +0000
@@ -0,0 +1,78 @@
+// Main Part 2 about Evil Wordle
+//===============================
+
+
+object M2 {
+
+import io.Source
+import scala.util._
+
+// ADD YOUR CODE BELOW
+//======================
+
+
+//(1)
+def get_wordle_list(url: String) : List[String] = ???
+
+// val secrets = get_wordle_list("https://nms.kcl.ac.uk/christian.urban/wordle.txt")
+// secrets.length // => 12972
+// secrets.filter(_.length != 5) // => Nil
+
+//(2)
+def removeN[A](xs: List[A], elem: A, n: Int) : List[A] = ???
+
+
+// removeN(List(1,2,3,2,1), 3, 1) // => List(1, 2, 2, 1)
+// removeN(List(1,2,3,2,1), 2, 1) // => List(1, 3, 2, 1)
+// removeN(List(1,2,3,2,1), 1, 1) // => List(2, 3, 2, 1)
+// removeN(List(1,2,3,2,1), 0, 2) // => List(1, 2, 3, 2, 1)
+
+// (3)
+abstract class Tip
+case object Absent extends Tip
+case object Present extends Tip
+case object Correct extends Tip
+
+
+def pool(secret: String, word: String) : List[Char] = ???
+
+def aux(secret: List[Char], word: List[Char], pool: List[Char]) : List[Tip] = ???
+
+def score(secret: String, word: String) : List[Tip] = ???
+
+
+// score("chess", "caves") // => List(Correct, Absent, Absent, Present, Correct)
+// score("doses", "slide") // => List(Present, Absent, Absent, Present, Present)
+// score("chess", "swiss") // => List(Absent, Absent, Absent, Correct, Correct)
+// score("chess", "eexss") // => List(Present, Absent, Absent, Correct, Correct)
+
+// (4)
+def eval(t: Tip) : Int = ???
+
+def iscore(secret: String, word: String) : Int = ???
+
+//iscore("chess", "caves") // => 21
+//iscore("chess", "swiss") // => 20
+
+// (5)
+def lowest(secrets: List[String], word: String, current: Int, acc: List[String]) : List[String] = ???
+
+def evil(secrets: List[String], word: String) : List[String] = ???
+
+
+//evil(secrets, "stent").length
+//evil(secrets, "hexes").length
+//evil(secrets, "horse").length
+//evil(secrets, "hoise").length
+//evil(secrets, "house").length
+
+// (6)
+def frequencies(secrets: List[String]) : Map[Char, Double] = ???
+
+// (7)
+def rank(frqs: Map[Char, Double], s: String) : Double = ???
+
+def ranked_evil(secrets: List[String], word: String) : List[String] = ???
+
+
+}
--- a/main_testing1/drumb_test.sh Mon Dec 26 16:49:53 2022 +0000
+++ b/main_testing1/drumb_test.sh Sat Jan 14 14:13:16 2023 +0000
@@ -23,15 +23,13 @@
}
# purity test
-
function scala_vars {
- (egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' c$out 2> /dev/null 1> /dev/null)
+ (sed 's/immutable/ok/g' c$out > cb$out;
+ egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' cb$out 2> /dev/null 1> /dev/null)
}
-
-
# compilation test
echo -e "drumb.scala runs?" >> $out