# HG changeset patch # User Christian Urban # Date 1673705596 0 # Node ID d59404a41d5f34791455ce3d127d64824d5f25c7 # Parent d9f8245d08619353d694ee714532bd7fb2a5afed updated diff -r d9f8245d0861 -r d59404a41d5f cws/build --- 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" diff -r d9f8245d0861 -r d59404a41d5f cws/core_cw01.pdf Binary file cws/core_cw01.pdf has changed diff -r d9f8245d0861 -r d59404a41d5f cws/core_cw02.pdf Binary file cws/core_cw02.pdf has changed diff -r d9f8245d0861 -r d59404a41d5f cws/core_cw03.pdf Binary file cws/core_cw03.pdf has changed diff -r d9f8245d0861 -r d59404a41d5f cws/main_cw01.pdf Binary file cws/main_cw01.pdf has changed diff -r d9f8245d0861 -r d59404a41d5f cws/main_cw02.pdf Binary file cws/main_cw02.pdf has changed diff -r d9f8245d0861 -r d59404a41d5f cws/main_cw02.tex --- 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 diff -r d9f8245d0861 -r d59404a41d5f cws/main_cw03.pdf Binary file cws/main_cw03.pdf has changed diff -r d9f8245d0861 -r d59404a41d5f cws/main_cw04.pdf Binary file cws/main_cw04.pdf has changed diff -r d9f8245d0861 -r d59404a41d5f cws/main_cw05.pdf Binary file cws/main_cw05.pdf has changed diff -r d9f8245d0861 -r d59404a41d5f cws/resit.tex --- 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} diff -r d9f8245d0861 -r d59404a41d5f cws/upload --- 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" diff -r d9f8245d0861 -r d59404a41d5f main_templates2/resit.scala --- /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] = ??? + + +} diff -r d9f8245d0861 -r d59404a41d5f main_templates2/wordle.scala --- /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] = ??? + + +} diff -r d9f8245d0861 -r d59404a41d5f main_testing1/drumb_test.sh --- 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