updated
authorChristian Urban <christian.urban@kcl.ac.uk>
Sat, 14 Jan 2023 14:13:16 +0000
changeset 459 d59404a41d5f
parent 458 d9f8245d0861
child 460 39ec5c112312
updated
cws/build
cws/core_cw01.pdf
cws/core_cw02.pdf
cws/core_cw03.pdf
cws/main_cw01.pdf
cws/main_cw02.pdf
cws/main_cw02.tex
cws/main_cw03.pdf
cws/main_cw04.pdf
cws/main_cw05.pdf
cws/resit.tex
cws/upload
main_templates2/resit.scala
main_templates2/wordle.scala
main_testing1/drumb_test.sh
--- 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