updated
authorChristian Urban <christian.urban@kcl.ac.uk>
Mon, 06 Nov 2023 14:18:26 +0000
changeset 477 a4e1f63157d8
parent 476 7550c816187a
child 478 191cd1de93f1
updated
Attic/resit.scala
core_testing1/collatz_test.sh
core_testing2/docdiff_test.sh
core_testing3/postfix_test.sh
cws/core_cw01.pdf
cws/core_cw02.pdf
cws/core_cw03.pdf
cws/main_cw01.pdf
cws/main_cw02.pdf
cws/main_cw03.pdf
cws/main_cw04.pdf
cws/main_cw04.tex
cws/main_cw05.pdf
handouts/pep-ho.pdf
main_solution4-old/main_solution4/knight1.scala
main_solution4-old/main_solution4/knight2.scala
main_solution4-old/main_solution4/knight3.scala
main_solution4-old/main_solution4/knight4.scala
main_solution4/knight1.scala
main_solution4/knight2.scala
main_solution4/knight3.scala
main_solution4/knight4.scala
main_templates2/resit.scala
main_templates3/re.scala
main_testing2/wordle_test.sh
main_testing3/re_test.sh
main_testing4/shogun_test.sh
main_testing5/bf_test.sh
main_testing5/bfc_test.sh
mk_jars
pics/lichess.png
pics/salary3.png
slides/slides01.pdf
slides/slides01.tex
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Attic/resit.scala	Mon Nov 06 14:18:26 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] = ???
+
+
+}
--- a/core_testing1/collatz_test.sh	Sat Nov 04 18:53:37 2023 +0000
+++ b/core_testing1/collatz_test.sh	Mon Nov 06 14:18:26 2023 +0000
@@ -15,7 +15,7 @@
 # compilation tests
 
 function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile "$1" 2> c$out 1> c$out)
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile -f -color never -Xprint:parser "$1" 2> c$out 1> c$out)
 }
 
 # functional tests
--- a/core_testing2/docdiff_test.sh	Sat Nov 04 18:53:37 2023 +0000
+++ b/core_testing2/docdiff_test.sh	Mon Nov 06 14:18:26 2023 +0000
@@ -14,7 +14,7 @@
 # compilation tests
 
 function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile "$1" 2> c$out 1> c$out)
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile -Xprint:parser "$1" 2> c$out 1> c$out)
 }
 
 # functional tests
--- a/core_testing3/postfix_test.sh	Sat Nov 04 18:53:37 2023 +0000
+++ b/core_testing3/postfix_test.sh	Mon Nov 06 14:18:26 2023 +0000
@@ -13,7 +13,7 @@
 # compilation tests
 
 function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile "$1" 2> c$out 1> c$out)
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile -Xprint:parser "$1" 2> c$out 1> c$out)
 }
 
 # functional tests
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
Binary file cws/main_cw03.pdf has changed
Binary file cws/main_cw04.pdf has changed
--- a/cws/main_cw04.tex	Sat Nov 04 18:53:37 2023 +0000
+++ b/cws/main_cw04.tex	Mon Nov 06 14:18:26 2023 +0000
@@ -48,7 +48,7 @@
 
 \mbox{}\\[-18mm]\mbox{}
 
-\section*{Main Part 4:\\ Implementing the Shogun Board Game (7 Marks)}
+\section*{Main Part 4:\\ Implementing the Shogun Board Game (8 Marks)}
 
 \mbox{}\hfill\textit{``The problem with object-oriented languages is they’ve got all this implicit,}\\
 \mbox{}\hfill\textit{environment that they carry around with them. You wanted a banana but}\\
@@ -388,12 +388,13 @@
   containing all these fields. Similarly in the other cases.
 \end{itemize}
 
-For example on the left board below, \texttt{eval} is called with the white
+For example in the left board below, \texttt{eval} is called with the white
 piece in the centre and the move \texttt{RU} generates then a set of
-new pieces corresponding to the blue fileds. The difference on the
+new pieces corresponding to the blue fields. The difference with the
 right board is that \texttt{eval} is called with a red piece and therefore the
 field (4, 8) is not reachable anymore because it is already occupied by
-another red piece.
+another red piece. But (7, 5) becomes reachable because it is occupied
+by a piece of the opposite colour.
 
 \begin{center}
 \begin{tabular}{cc}  
@@ -408,11 +409,11 @@
 \fill[blue!50] (5,5) rectangle ++ (1,1);
 \fill[blue!50] (3,7) rectangle ++ (1,1);
 \fill[blue!50] (4,6) rectangle ++ (1,1);
-\fill[blue!50] (6,4) rectangle ++ (1,1);
+%\fill[blue!50] (6,4) rectangle ++ (1,1);
 \fill[blue!50] (7,3) rectangle ++ (1,1);
 
 % black pieces
-\foreach\x/\y/\e in {1/1/1,2/1/3,3/1/2,4/1/3,6/1/3,7/1/1,8/1/2}
+\foreach\x/\y/\e in {2/1/3,3/1/2,4/1/3,6/1/3,7/1/1,7/5/2}
   \pic[fill=white] at (\x,\y) {piece={\e}};
 % white pieces
 \foreach\x/\y/\e in {1/8/4,2/8/2,3/8/4,5/8/4,6/8/2,7/8/3,8/8/1}
@@ -444,10 +445,10 @@
 \fill[blue!50] (7,3) rectangle ++ (1,1);
 
 % black pieces
-\foreach\x/\y/\e in {1/1/1,2/1/3,3/1/2,4/1/3,6/1/3,7/1/1,8/1/2}
+\foreach\x/\y/\e in {1/1/1,2/1/3,3/1/2,4/1/3,6/1/3,7/1/1,7/5/2}
   \pic[fill=white] at (\x,\y) {piece={\e}};
 % white pieces
-\foreach\x/\y/\e in {1/8/4,2/8/2,3/8/4,5/8/4,6/8/2,7/8/3,8/8/1}
+\foreach\x/\y/\e in {1/8/4,2/8/2,3/8/4,5/8/4,6/8/2,7/8/3}
   \pic[fill=red] at (\x,\y)     {piece={\e}};
 \pic[fill=white] at (5.0,1.0) {king={1}};
 \pic[fill=red]   at (4.0,8.0) {king={2}};
@@ -466,15 +467,17 @@
 \end{center}\hfill[3 Marks]
 
 \item[(2)] Implement an \texttt{all\_moves} function that calculates for a
-  piece and a board, \textit{all} pieces on legal onward positions. For this
+  piece and a board, \textit{all} possible onward positions. For this
   you have to call \texttt{eval} for all possible moves \texttt{m} (that is \texttt{U},
-  \texttt{D}, \ldots, \texttt{DL}). An example for all moves for the red piece on (4, 4) are
-  shown in \eqref{moves} on page \pageref{moves}.\\ 
+  \texttt{D}, \ldots, \texttt{DL}). An example for all moves for the red piece on (4, 4) is
+  shown in \eqref{moves} on page \pageref{moves}. Be careful about possible modifications
+  you need to apply to the board  before you call the \texttt{eval} function.
+  Also for this task ignore the fact that a king cannot move onto an attacked field.\\ 
   \mbox{}\hfill[1 Mark]
 
 \item[(3)] Implement a function \texttt{attacked} that takes a colour and a board
   and calculates all pieces of the opposite side that are attacked. For example
-  below on the left are all the attacked pieces by red, and on the right for white:
+  below in the left board are all the attacked pieces by red, and on the right all for white:
 
 \begin{center}
 \begin{tabular}{cc}      
@@ -490,11 +493,11 @@
 \fill[blue!50] (6,0) rectangle ++ (1,1);
 
 
-% black pieces
+% red pieces
 \foreach\x/\y/\e in {6/1/3,4/4/4,5/3/4,6/5/3}
   \pic[fill=red] at (\x,\y) {piece={\e}};
 % white pieces
-\foreach\x/\y/\e in {8/4/2,4/1/2,8/7/3}
+\foreach\x/\y/\e in {8/4/1,4/1/2,8/7/3,6/7/2}
   \pic[fill=white] at (\x,\y)     {piece={\e}};
 
 \pic[fill=red] at (4,2) {king={2}};
@@ -518,13 +521,13 @@
   \fill[gray!\blend] (\x,\y) rectangle ++ (1,1);
 }
 \fill[blue!50] (5,0) rectangle ++ (1,1);
-
+\fill[blue!50] (5,4) rectangle ++ (1,1);
 
-% black pieces
+% red pieces
 \foreach\x/\y/\e in {6/1/3,4/4/4,5/3/4,6/5/3}
   \pic[fill=red] at (\x,\y) {piece={\e}};
 % white pieces
-\foreach\x/\y/\e in {8/4/2,4/1/2,8/7/3}
+\foreach\x/\y/\e in {8/4/1,4/1/2,8/7/3,6/7/2}
   \pic[fill=white] at (\x,\y)     {piece={\e}};
 
 \pic[fill=red] at (4,2) {king={2}};
@@ -555,6 +558,83 @@
   and the piece on (5, 3) is protected by three red pieces ((6, 1), (4, 2), and (6, 5)).
   \\
   \mbox{}\hfill[1 Mark]
+
+\item[(6)] Implement a function \texttt{legal\_moves} that behaves like \texttt{all\_moves} from (2) for
+  pawns, but for kings, in addition, makes sure that they do not move to an attacked field.
+  For example in the board below on the left, there are three possible fields the white king can
+  reach, but all of them are attacked by red pieces. In the board on the right where the
+  white king has an energy of 1, there is only one legal move, namely to move to field (8, 1).
+  The field (7, 2) is reachable, but is attacked; similarly capturing the red piece on field (6, 1) is
+  not possible because it is protected by at least another red piece.
+
+  \begin{center}
+  \begin{tabular}{cc}    
+  \begin{tikzpicture}[scale=0.45,every node/.style={scale=0.45}]    
+% chessboard
+\draw[very thick,gray] (0,0) rectangle (8,8);
+\foreach\x in {0,...,7}\foreach\y in {7,...,0}
+{
+  \pgfmathsetmacro\blend{Mod(\x+\y,2)==0?75:25} 
+  \fill[gray!\blend] (\x,\y) rectangle ++ (1,1);
+}
+\fill[blue!50] (5,1) rectangle ++ (1,1);
+\fill[blue!50] (6,2) rectangle ++ (1,1);
+\fill[blue!50] (7,1) rectangle ++ (1,1);
+
+
+% red pieces
+\foreach\x/\y/\e in {6/1/3,4/4/4,5/3/4,6/5/3}
+  \pic[fill=red] at (\x,\y) {piece={\e}};
+% white pieces
+\foreach\x/\y/\e in {8/4/1,4/1/2,8/7/3,6/7/2}
+  \pic[fill=white] at (\x,\y)     {piece={\e}};
+
+\pic[fill=red] at (4,2) {king={2}};
+\pic[fill=white] at (7,1) {king={2}};
+
+% numbers
+\foreach\x in {1,...,8}
+{\draw (\x - 0.5, -0.4) node {\x};
+}
+\foreach\y in {1,...,8}
+{\draw (-0.4, \y - 0.6, -0.4) node {\y};
+}
+\end{tikzpicture}  &
+ \begin{tikzpicture}[scale=0.45,every node/.style={scale=0.45}]    
+% chessboard
+\draw[very thick,gray] (0,0) rectangle (8,8);
+\foreach\x in {0,...,7}\foreach\y in {7,...,0}
+{
+  \pgfmathsetmacro\blend{Mod(\x+\y,2)==0?75:25} 
+  \fill[gray!\blend] (\x,\y) rectangle ++ (1,1);
+}
+\fill[blue!50] (5,0) rectangle ++ (1,1);
+\fill[blue!50] (6,1) rectangle ++ (1,1);
+\fill[blue!50] (7,0) rectangle ++ (1,1);
+
+
+% red pieces
+\foreach\x/\y/\e in {6/1/3,4/4/4,5/3/3,6/5/3}
+  \pic[fill=red] at (\x,\y) {piece={\e}};
+% white pieces
+\foreach\x/\y/\e in {8/4/1,4/1/2,8/7/3,6/7/2}
+  \pic[fill=white] at (\x,\y)     {piece={\e}};
+
+\pic[fill=red] at (4,2) {king={2}};
+\pic[fill=white] at (7,1) {king={1}};
+
+% numbers
+\foreach\x in {1,...,8}
+{\draw (\x - 0.5, -0.4) node {\x};
+}
+\foreach\y in {1,...,8}
+{\draw (-0.4, \y - 0.6, -0.4) node {\y};
+}
+\end{tikzpicture}                      
+\end{tabular}                     
+\end{center}
+\mbox{}\\ \mbox{}\hfill[1 Mark]
+
 \end{itemize}
 
 \end{document}
Binary file cws/main_cw05.pdf has changed
Binary file handouts/pep-ho.pdf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_solution4-old/main_solution4/knight1.scala	Mon Nov 06 14:18:26 2023 +0000
@@ -0,0 +1,171 @@
+// Part 1 about finding and counting Knight's tours
+//==================================================
+
+object M4a {   // for preparing the jar
+
+type Pos = (Int, Int)    // a position on a chessboard 
+type Path = List[Pos]    // a path...a list of positions
+
+
+// for measuring time in the JAR
+def time_needed[T](code: => T) : T = {
+  val start = System.nanoTime()
+  val result = code
+  val end = System.nanoTime()
+  println(f"Time needed: ${(end - start) / 1.0e9}%3.3f secs.")
+  result
+}
+
+// for printing a board
+def print_board(dim: Int, path: Path): Unit = {
+  println()
+  for (i <- 0 until dim) {
+    for (j <- 0 until dim) {
+      print(f"${path.reverse.indexOf((j, dim - i - 1))}%3.0f ")
+    }
+    println()
+  } 
+}
+
+def is_legal(dim: Int, path: Path, x: Pos): Boolean = 
+  0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
+
+// testcases
+//assert(is_legal(8, Nil, (3, 4)) == true)
+//assert(is_legal(8, List((4, 1), (1, 0)), (4, 1)) == false)
+//assert(is_legal(2, Nil, (0, 0)) == true)
+
+
+def add_pair(x: Pos, y: Pos): Pos = 
+  (x._1 + y._1, x._2 + y._2)
+
+def moves(x: Pos): List[Pos] = 
+  List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
+       (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair(x, _))
+
+def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
+  moves(x).filter(is_legal(dim, path, _))
+
+
+
+// testcases
+//assert(legal_moves(8, Nil, (2,2)) == 
+//  List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4)))
+//assert(legal_moves(8, Nil, (7,7)) == List((6,5), (5,6)))
+//assert(legal_moves(8, List((4,1), (1,0)), (2,2)) == 
+//  List((3,4), (4,3), (3,0), (0,1), (0,3), (1,4)))
+//assert(legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6)))
+//assert(legal_moves(8, Nil, (0,1)) == List((1,3), (2,2), (2,0)))
+//assert(legal_moves(1, Nil, (0,0)) == List())
+//assert(legal_moves(2, Nil, (0,0)) == List())
+//assert(legal_moves(3, Nil, (0,0)) == List((1,2), (2,1)))
+
+
+def tcount_tours(dim: Int, path: Path): Int = {
+  if (path.length == dim * dim) 1
+  else 
+    (for (x <- legal_moves(dim, path, path.head)) yield tcount_tours(dim, x::path)).sum
+}
+
+def count_tours(dim: Int, path: Path) =
+  time_needed(tcount_tours(dim: Int, path: Path))
+
+
+def tenum_tours(dim: Int, path: Path): List[Path] = {
+  if (path.length == dim * dim) List(path)
+  else 
+    (for (x <- legal_moves(dim, path, path.head)) yield tenum_tours(dim, x::path)).flatten
+}
+
+def enum_tours(dim: Int, path: Path) =
+  time_needed(tenum_tours(dim: Int, path: Path))
+
+// test cases
+
+/*
+def count_all_tours(dim: Int) = {
+  for (i <- (0 until dim).toList; 
+       j <- (0 until dim).toList) yield count_tours(dim, List((i, j)))
+}
+
+def enum_all_tours(dim: Int): List[Path] = {
+  (for (i <- (0 until dim).toList; 
+        j <- (0 until dim).toList) yield enum_tours(dim, List((i, j)))).flatten
+}
+
+
+println("Number of tours starting from (0, 0)")
+
+for (dim <- 1 to 5) {
+  println(s"${dim} x ${dim} " + time_needed(0, count_tours(dim, List((0, 0)))))
+}
+
+println("Number of tours starting from all fields")
+
+for (dim <- 1 to 5) {
+  println(s"${dim} x ${dim} " + time_needed(0, count_all_tours(dim)))
+}
+
+for (dim <- 1 to 5) {
+  val ts = enum_tours(dim, List((0, 0)))
+  println(s"${dim} x ${dim} ")   
+  if (ts != Nil) {
+    print_board(dim, ts.head)
+    println(ts.head)
+  }
+}
+*/
+
+
+def first(xs: List[Pos], f: Pos => Option[Path]): Option[Path] = xs match {
+  case Nil => None
+  case x::xs => {
+    val result = f(x)
+    if (result.isDefined) result else first(xs, f)
+  }
+}
+
+// test cases
+//def foo(x: (Int, Int)) = if (x._1 > 3) Some(List(x)) else None
+//
+//first(List((1, 0),(2, 0),(3, 0),(4, 0)), foo)
+//first(List((1, 0),(2, 0),(3, 0)), foo)
+
+
+def tfirst_tour(dim: Int, path: Path): Option[Path] = {
+  if (path.length == dim * dim) Some(path)
+  else
+    first(legal_moves(dim, path, path.head), (x:Pos) => tfirst_tour(dim, x::path))
+}
+
+def first_tour(dim: Int, path: Path) = 
+  time_needed(tfirst_tour(dim: Int, path: Path))
+
+
+/*
+for (dim <- 1 to 8) {
+  val t = first_tour(dim, List((0, 0)))
+  println(s"${dim} x ${dim} " + (if (t == None) "" else { print_board(dim, t.get) ; "" }))
+}
+*/
+
+// 15 secs for 8 x 8
+//val ts1 = time_needed(first_tour(8, List((0, 0))).get)
+//??val ts1 = time_needed(first_tour(8, List((7, 7))).get)
+
+// no result for 4 x 4
+//val ts2 = time_needed(0, first_tour(4, List((0, 0))))
+
+// 0.3 secs for 6 x 6
+//val ts3 = time_needed(0, first_tour(6, List((0, 0))))
+
+// 15 secs for 8 x 8
+//time_needed(0, print_board(8, first_tour(8, List((0, 0))).get))
+
+
+
+
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_solution4-old/main_solution4/knight2.scala	Mon Nov 06 14:18:26 2023 +0000
@@ -0,0 +1,93 @@
+// Part 2 about finding a single tour using the Warnsdorf Rule
+//=============================================================
+
+object M4b { // for preparing the jar
+
+type Pos = (Int, Int)
+type Path = List[Pos]
+
+
+// for measuring time in the JAR
+def time_needed[T](code: => T) : T = {
+  val start = System.nanoTime()
+  val result = code
+  val end = System.nanoTime()
+  println(f"Time needed: ${(end - start) / 1.0e9}%3.3f secs.")
+  result
+}
+
+
+def print_board(dim: Int, path: Path): Unit = {
+  println()
+  for (i <- 0 until dim) {
+    for (j <- 0 until dim) {
+      print(f"${path.reverse.indexOf((i, j))}%4.0f ")
+    }
+    println()
+  } 
+}
+
+def add_pair(x: Pos, y: Pos): Pos = 
+  (x._1 + y._1, x._2 + y._2)
+
+def is_legal(dim: Int, path: Path, x: Pos): Boolean = 
+  0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
+
+def moves(x: Pos): List[Pos] = 
+  List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
+       (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair(x, _))
+
+def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
+  moves(x).filter(is_legal(dim, path, _))
+ 
+def ordered_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
+  legal_moves(dim, path, x).sortBy((x) => legal_moves(dim, path, x).length)
+
+import scala.annotation.tailrec
+
+@tailrec
+def first(xs: List[Pos], f: Pos => Option[Path]): Option[Path] = xs match {
+  case Nil => None
+  case x::xs => {
+    val result = f(x)
+    if (result.isDefined) result else first(xs, f)
+  }
+}
+
+
+def tfirst_closed_tour_heuristics(dim: Int, path: Path): Option[Path] = {
+  if (path.length == dim * dim && moves(path.head).contains(path.last)) Some(path)
+  else
+    first(ordered_moves(dim, path, path.head), (x: Pos) => tfirst_closed_tour_heuristics(dim, x::path))
+}
+
+def first_closed_tour_heuristics(dim: Int, path: Path) =
+ time_needed(tfirst_closed_tour_heuristics(dim: Int, path: Path))
+
+def first_closed_tour_heuristic(dim: Int, path: Path) =
+ time_needed(tfirst_closed_tour_heuristics(dim: Int, path: Path))
+
+// heuristic cannot be used to search for closed tours on 7 x 7 an beyond
+//for (dim <- 1 to 6) {
+//  val t = time_needed(0, first_closed_tour_heuristics(dim, List((dim / 2, dim / 2))))
+//  println(s"${dim} x ${dim} closed: " + (if (t == None) "" else { print_board(dim, t.get) ; "" }))
+//}
+
+
+def tfirst_tour_heuristics(dim: Int, path: Path): Option[Path] = {
+  if (path.length == dim * dim) Some(path)
+  else
+    first(ordered_moves(dim, path, path.head), (x: Pos) => tfirst_tour_heuristics(dim, x::path))
+}
+
+
+def first_tour_heuristics(dim: Int, path: Path) = 
+  time_needed(tfirst_tour_heuristics(dim: Int, path: Path))
+
+def first_tour_heuristic(dim: Int, path: Path) = 
+  time_needed(tfirst_tour_heuristics(dim: Int, path: Path))
+
+// will be called with boards up to 30 x 30
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_solution4-old/main_solution4/knight3.scala	Mon Nov 06 14:18:26 2023 +0000
@@ -0,0 +1,73 @@
+// Part 3 about finding a single tour using the Warnsdorf Rule
+//=============================================================
+
+object M4c { // for preparing the jar
+
+type Pos = (Int, Int)
+type Path = List[Pos]
+
+
+// for measuring time in the JAR
+def time_needed[T](code: => T) : T = {
+  val start = System.nanoTime()
+  val result = code
+  val end = System.nanoTime()
+  println(f"Time needed: ${(end - start) / 1.0e9}%3.3f secs.")
+  result
+}
+
+
+def print_board(dim: Int, path: Path): Unit = {
+  println()
+  for (i <- 0 until dim) {
+    for (j <- 0 until dim) {
+      print(f"${path.reverse.indexOf((i, j))}%4.0f ")
+    }
+    println()
+  } 
+}
+
+def add_pair(x: Pos, y: Pos): Pos = 
+  (x._1 + y._1, x._2 + y._2)
+
+def is_legal(dim: Int, path: Path, x: Pos): Boolean = 
+  0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
+
+def moves(x: Pos): List[Pos] = 
+  List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
+       (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair(x, _))
+
+def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
+  moves(x).filter(is_legal(dim, path, _))
+ 
+def ordered_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
+  legal_moves(dim, path, x).sortBy((x) => legal_moves(dim, path, x).length)
+
+import scala.annotation.tailrec
+
+@tailrec
+def tour_on_mega_board_aux(dim: Int, paths: List[Path]): Option[Path] = paths match {
+  case Nil => None
+  case (path::rest) =>
+    if (path.length == dim * dim) Some(path)
+    else tour_on_mega_board_aux(dim, ordered_moves(dim, path, path.head).map(_::path) ::: rest)
+}
+
+def ttour_on_mega_board(dim: Int, path: Path): Option[Path] =
+  tour_on_mega_board_aux(dim, List(path))
+
+
+def tour_on_mega_board(dim: Int, path: Path) =
+  time_needed(ttour_on_mega_board(dim: Int, path: Path))
+
+
+// testcases
+//print_board(70, tour_on_mega_board(70, List((0, 0))).get)
+
+
+}
+
+
+//val dim = 66 //75
+M4c.print_board(30, M4c.tour_on_mega_board(30, List((0, 0))).get)
+M4c.print_board(66, M4c.tour_on_mega_board(66, List((0, 0))).get)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_solution4-old/main_solution4/knight4.scala	Mon Nov 06 14:18:26 2023 +0000
@@ -0,0 +1,53 @@
+// Part 4 about finding a single tour on "mutilated" chessboards
+//==============================================================
+
+object M4d { // for preparing the jar
+
+type Pos = (Int, Int)
+type Path = List[Pos]
+
+def print_board(dim: Int, path: Path): Unit = {
+  println()
+  for (i <- 0 until dim) {
+    for (j <- 0 until dim) {
+      print(f"${path.reverse.indexOf((i, j))}%4.0f ")
+    }
+    println()
+  } 
+}
+
+def add_pair(x: Pos, y: Pos): Pos = 
+  (x._1 + y._1, x._2 + y._2)
+
+def is_legal(dim: Int, path: Path, x: Pos): Boolean = 
+  0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
+
+def moves(x: Pos): List[Pos] = 
+  List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
+       (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair(x, _))
+
+def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
+  moves(x).filter(is_legal(dim, path, _))
+ 
+import scala.annotation.tailrec
+
+@tailrec
+def first(xs: List[Pos], f: Pos => Option[Path]): Option[Path] = xs match {
+  case Nil => None
+  case x::xs => {
+    val result = f(x)
+    if (result.isDefined) result else first(xs, f)
+  }
+}
+
+
+def one_tour_pred(dim: Int, path: Path, n: Int, pred: Pos => Boolean): Option[Path] = {
+  if (path.length == n) Some(path)
+  else
+    first(legal_moves(dim, path, path.head).filter(pred), (x: Pos) => one_tour_pred(dim, x::path, n, pred))
+}
+
+//print_board(8, one_tour_pred(8, List((0, 0)), 40, x => x._1 < 5).get)
+
+
+}
--- a/main_solution4/knight1.scala	Sat Nov 04 18:53:37 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-// Part 1 about finding and counting Knight's tours
-//==================================================
-
-object M4a {   // for preparing the jar
-
-type Pos = (Int, Int)    // a position on a chessboard 
-type Path = List[Pos]    // a path...a list of positions
-
-
-// for measuring time in the JAR
-def time_needed[T](code: => T) : T = {
-  val start = System.nanoTime()
-  val result = code
-  val end = System.nanoTime()
-  println(f"Time needed: ${(end - start) / 1.0e9}%3.3f secs.")
-  result
-}
-
-// for printing a board
-def print_board(dim: Int, path: Path): Unit = {
-  println()
-  for (i <- 0 until dim) {
-    for (j <- 0 until dim) {
-      print(f"${path.reverse.indexOf((j, dim - i - 1))}%3.0f ")
-    }
-    println()
-  } 
-}
-
-def is_legal(dim: Int, path: Path, x: Pos): Boolean = 
-  0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
-
-// testcases
-//assert(is_legal(8, Nil, (3, 4)) == true)
-//assert(is_legal(8, List((4, 1), (1, 0)), (4, 1)) == false)
-//assert(is_legal(2, Nil, (0, 0)) == true)
-
-
-def add_pair(x: Pos, y: Pos): Pos = 
-  (x._1 + y._1, x._2 + y._2)
-
-def moves(x: Pos): List[Pos] = 
-  List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
-       (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair(x, _))
-
-def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
-  moves(x).filter(is_legal(dim, path, _))
-
-
-
-// testcases
-//assert(legal_moves(8, Nil, (2,2)) == 
-//  List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4)))
-//assert(legal_moves(8, Nil, (7,7)) == List((6,5), (5,6)))
-//assert(legal_moves(8, List((4,1), (1,0)), (2,2)) == 
-//  List((3,4), (4,3), (3,0), (0,1), (0,3), (1,4)))
-//assert(legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6)))
-//assert(legal_moves(8, Nil, (0,1)) == List((1,3), (2,2), (2,0)))
-//assert(legal_moves(1, Nil, (0,0)) == List())
-//assert(legal_moves(2, Nil, (0,0)) == List())
-//assert(legal_moves(3, Nil, (0,0)) == List((1,2), (2,1)))
-
-
-def tcount_tours(dim: Int, path: Path): Int = {
-  if (path.length == dim * dim) 1
-  else 
-    (for (x <- legal_moves(dim, path, path.head)) yield tcount_tours(dim, x::path)).sum
-}
-
-def count_tours(dim: Int, path: Path) =
-  time_needed(tcount_tours(dim: Int, path: Path))
-
-
-def tenum_tours(dim: Int, path: Path): List[Path] = {
-  if (path.length == dim * dim) List(path)
-  else 
-    (for (x <- legal_moves(dim, path, path.head)) yield tenum_tours(dim, x::path)).flatten
-}
-
-def enum_tours(dim: Int, path: Path) =
-  time_needed(tenum_tours(dim: Int, path: Path))
-
-// test cases
-
-/*
-def count_all_tours(dim: Int) = {
-  for (i <- (0 until dim).toList; 
-       j <- (0 until dim).toList) yield count_tours(dim, List((i, j)))
-}
-
-def enum_all_tours(dim: Int): List[Path] = {
-  (for (i <- (0 until dim).toList; 
-        j <- (0 until dim).toList) yield enum_tours(dim, List((i, j)))).flatten
-}
-
-
-println("Number of tours starting from (0, 0)")
-
-for (dim <- 1 to 5) {
-  println(s"${dim} x ${dim} " + time_needed(0, count_tours(dim, List((0, 0)))))
-}
-
-println("Number of tours starting from all fields")
-
-for (dim <- 1 to 5) {
-  println(s"${dim} x ${dim} " + time_needed(0, count_all_tours(dim)))
-}
-
-for (dim <- 1 to 5) {
-  val ts = enum_tours(dim, List((0, 0)))
-  println(s"${dim} x ${dim} ")   
-  if (ts != Nil) {
-    print_board(dim, ts.head)
-    println(ts.head)
-  }
-}
-*/
-
-
-def first(xs: List[Pos], f: Pos => Option[Path]): Option[Path] = xs match {
-  case Nil => None
-  case x::xs => {
-    val result = f(x)
-    if (result.isDefined) result else first(xs, f)
-  }
-}
-
-// test cases
-//def foo(x: (Int, Int)) = if (x._1 > 3) Some(List(x)) else None
-//
-//first(List((1, 0),(2, 0),(3, 0),(4, 0)), foo)
-//first(List((1, 0),(2, 0),(3, 0)), foo)
-
-
-def tfirst_tour(dim: Int, path: Path): Option[Path] = {
-  if (path.length == dim * dim) Some(path)
-  else
-    first(legal_moves(dim, path, path.head), (x:Pos) => tfirst_tour(dim, x::path))
-}
-
-def first_tour(dim: Int, path: Path) = 
-  time_needed(tfirst_tour(dim: Int, path: Path))
-
-
-/*
-for (dim <- 1 to 8) {
-  val t = first_tour(dim, List((0, 0)))
-  println(s"${dim} x ${dim} " + (if (t == None) "" else { print_board(dim, t.get) ; "" }))
-}
-*/
-
-// 15 secs for 8 x 8
-//val ts1 = time_needed(first_tour(8, List((0, 0))).get)
-//??val ts1 = time_needed(first_tour(8, List((7, 7))).get)
-
-// no result for 4 x 4
-//val ts2 = time_needed(0, first_tour(4, List((0, 0))))
-
-// 0.3 secs for 6 x 6
-//val ts3 = time_needed(0, first_tour(6, List((0, 0))))
-
-// 15 secs for 8 x 8
-//time_needed(0, print_board(8, first_tour(8, List((0, 0))).get))
-
-
-
-
-
-}
-
-
--- a/main_solution4/knight2.scala	Sat Nov 04 18:53:37 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-// Part 2 about finding a single tour using the Warnsdorf Rule
-//=============================================================
-
-object M4b { // for preparing the jar
-
-type Pos = (Int, Int)
-type Path = List[Pos]
-
-
-// for measuring time in the JAR
-def time_needed[T](code: => T) : T = {
-  val start = System.nanoTime()
-  val result = code
-  val end = System.nanoTime()
-  println(f"Time needed: ${(end - start) / 1.0e9}%3.3f secs.")
-  result
-}
-
-
-def print_board(dim: Int, path: Path): Unit = {
-  println()
-  for (i <- 0 until dim) {
-    for (j <- 0 until dim) {
-      print(f"${path.reverse.indexOf((i, j))}%4.0f ")
-    }
-    println()
-  } 
-}
-
-def add_pair(x: Pos, y: Pos): Pos = 
-  (x._1 + y._1, x._2 + y._2)
-
-def is_legal(dim: Int, path: Path, x: Pos): Boolean = 
-  0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
-
-def moves(x: Pos): List[Pos] = 
-  List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
-       (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair(x, _))
-
-def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
-  moves(x).filter(is_legal(dim, path, _))
- 
-def ordered_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
-  legal_moves(dim, path, x).sortBy((x) => legal_moves(dim, path, x).length)
-
-import scala.annotation.tailrec
-
-@tailrec
-def first(xs: List[Pos], f: Pos => Option[Path]): Option[Path] = xs match {
-  case Nil => None
-  case x::xs => {
-    val result = f(x)
-    if (result.isDefined) result else first(xs, f)
-  }
-}
-
-
-def tfirst_closed_tour_heuristics(dim: Int, path: Path): Option[Path] = {
-  if (path.length == dim * dim && moves(path.head).contains(path.last)) Some(path)
-  else
-    first(ordered_moves(dim, path, path.head), (x: Pos) => tfirst_closed_tour_heuristics(dim, x::path))
-}
-
-def first_closed_tour_heuristics(dim: Int, path: Path) =
- time_needed(tfirst_closed_tour_heuristics(dim: Int, path: Path))
-
-def first_closed_tour_heuristic(dim: Int, path: Path) =
- time_needed(tfirst_closed_tour_heuristics(dim: Int, path: Path))
-
-// heuristic cannot be used to search for closed tours on 7 x 7 an beyond
-//for (dim <- 1 to 6) {
-//  val t = time_needed(0, first_closed_tour_heuristics(dim, List((dim / 2, dim / 2))))
-//  println(s"${dim} x ${dim} closed: " + (if (t == None) "" else { print_board(dim, t.get) ; "" }))
-//}
-
-
-def tfirst_tour_heuristics(dim: Int, path: Path): Option[Path] = {
-  if (path.length == dim * dim) Some(path)
-  else
-    first(ordered_moves(dim, path, path.head), (x: Pos) => tfirst_tour_heuristics(dim, x::path))
-}
-
-
-def first_tour_heuristics(dim: Int, path: Path) = 
-  time_needed(tfirst_tour_heuristics(dim: Int, path: Path))
-
-def first_tour_heuristic(dim: Int, path: Path) = 
-  time_needed(tfirst_tour_heuristics(dim: Int, path: Path))
-
-// will be called with boards up to 30 x 30
-
-
-}
--- a/main_solution4/knight3.scala	Sat Nov 04 18:53:37 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-// Part 3 about finding a single tour using the Warnsdorf Rule
-//=============================================================
-
-object M4c { // for preparing the jar
-
-type Pos = (Int, Int)
-type Path = List[Pos]
-
-
-// for measuring time in the JAR
-def time_needed[T](code: => T) : T = {
-  val start = System.nanoTime()
-  val result = code
-  val end = System.nanoTime()
-  println(f"Time needed: ${(end - start) / 1.0e9}%3.3f secs.")
-  result
-}
-
-
-def print_board(dim: Int, path: Path): Unit = {
-  println()
-  for (i <- 0 until dim) {
-    for (j <- 0 until dim) {
-      print(f"${path.reverse.indexOf((i, j))}%4.0f ")
-    }
-    println()
-  } 
-}
-
-def add_pair(x: Pos, y: Pos): Pos = 
-  (x._1 + y._1, x._2 + y._2)
-
-def is_legal(dim: Int, path: Path, x: Pos): Boolean = 
-  0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
-
-def moves(x: Pos): List[Pos] = 
-  List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
-       (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair(x, _))
-
-def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
-  moves(x).filter(is_legal(dim, path, _))
- 
-def ordered_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
-  legal_moves(dim, path, x).sortBy((x) => legal_moves(dim, path, x).length)
-
-import scala.annotation.tailrec
-
-@tailrec
-def tour_on_mega_board_aux(dim: Int, paths: List[Path]): Option[Path] = paths match {
-  case Nil => None
-  case (path::rest) =>
-    if (path.length == dim * dim) Some(path)
-    else tour_on_mega_board_aux(dim, ordered_moves(dim, path, path.head).map(_::path) ::: rest)
-}
-
-def ttour_on_mega_board(dim: Int, path: Path): Option[Path] =
-  tour_on_mega_board_aux(dim, List(path))
-
-
-def tour_on_mega_board(dim: Int, path: Path) =
-  time_needed(ttour_on_mega_board(dim: Int, path: Path))
-
-
-// testcases
-//print_board(70, tour_on_mega_board(70, List((0, 0))).get)
-
-
-}
-
-
-//val dim = 66 //75
-M4c.print_board(30, M4c.tour_on_mega_board(30, List((0, 0))).get)
-M4c.print_board(66, M4c.tour_on_mega_board(66, List((0, 0))).get)
--- a/main_solution4/knight4.scala	Sat Nov 04 18:53:37 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-// Part 4 about finding a single tour on "mutilated" chessboards
-//==============================================================
-
-object M4d { // for preparing the jar
-
-type Pos = (Int, Int)
-type Path = List[Pos]
-
-def print_board(dim: Int, path: Path): Unit = {
-  println()
-  for (i <- 0 until dim) {
-    for (j <- 0 until dim) {
-      print(f"${path.reverse.indexOf((i, j))}%4.0f ")
-    }
-    println()
-  } 
-}
-
-def add_pair(x: Pos, y: Pos): Pos = 
-  (x._1 + y._1, x._2 + y._2)
-
-def is_legal(dim: Int, path: Path, x: Pos): Boolean = 
-  0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
-
-def moves(x: Pos): List[Pos] = 
-  List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
-       (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair(x, _))
-
-def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
-  moves(x).filter(is_legal(dim, path, _))
- 
-import scala.annotation.tailrec
-
-@tailrec
-def first(xs: List[Pos], f: Pos => Option[Path]): Option[Path] = xs match {
-  case Nil => None
-  case x::xs => {
-    val result = f(x)
-    if (result.isDefined) result else first(xs, f)
-  }
-}
-
-
-def one_tour_pred(dim: Int, path: Path, n: Int, pred: Pos => Boolean): Option[Path] = {
-  if (path.length == n) Some(path)
-  else
-    first(legal_moves(dim, path, path.head).filter(pred), (x: Pos) => one_tour_pred(dim, x::path, n, pred))
-}
-
-//print_board(8, one_tour_pred(8, List((0, 0)), 40, x => x._1 < 5).get)
-
-
-}
--- a/main_templates2/resit.scala	Sat Nov 04 18:53:37 2023 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-// 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] = ???
-
-
-}
--- a/main_templates3/re.scala	Sat Nov 04 18:53:37 2023 +0000
+++ b/main_templates3/re.scala	Mon Nov 06 14:18:26 2023 +0000
@@ -17,39 +17,34 @@
 def ALT(r1: Rexp, r2: Rexp) = ALTs(List(r1, r2))
 def SEQ(r1: Rexp, r2: Rexp) = SEQs(List(r1, r2))
 
-
 // some convenience for typing regular expressions
-import scala.language.implicitConversions    
-import scala.language.reflectiveCalls 
 
 def charlist2rexp(s: List[Char]): Rexp = s match {
   case Nil => ONE
   case c::Nil => CHAR(c)
   case c::s => SEQ(CHAR(c), charlist2rexp(s))
 }
-implicit def string2rexp(s: String): Rexp = charlist2rexp(s.toList)
+
+import scala.language.implicitConversions
 
-implicit def RexpOps (r: Rexp) = new {
+given Conversion[String, Rexp] = (s => charlist2rexp(s.toList))
+
+extension (r: Rexp) {
   def | (s: Rexp) = ALT(r, s)
   def % = STAR(r)
   def ~ (s: Rexp) = SEQ(r, s)
 }
 
-implicit def stringOps (s: String) = new {
-  def | (r: Rexp) = ALT(s, r)
-  def | (r: String) = ALT(s, r)
-  def % = STAR(s)
-  def ~ (r: Rexp) = SEQ(s, r)
-  def ~ (r: String) = SEQ(s, r)
-}
+// some examples for the conversion and extension:
 
-// examples for the implicits:
-// ALT(CHAR('a'), CHAR('b'))
 // val areg : Rexp = "a" | "b"
-
-// SEQ(CHAR('a'), CHAR('b')) 
+//  => ALTs(List(CHAR('a'), CHAR('b')))
+//
 // val sreg : Rexp = "a" ~ "b"
-
+//  => SEQs(List(CHAR('a'), CHAR('b'))) 
+//
+// val star_reg : Rexp = ("a" ~ "b").%
+//  => STAR(SEQs(List(CHAR('a'), CHAR('b')))) 
 
 // ADD YOUR CODE BELOW
 //======================
--- a/main_testing2/wordle_test.sh	Sat Nov 04 18:53:37 2023 +0000
+++ b/main_testing2/wordle_test.sh	Mon Nov 06 14:18:26 2023 +0000
@@ -16,7 +16,7 @@
 # compilation tests
 
 function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile "$1" 2> c$out 1> c$out)
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile -Xprint:parser "$1" 2> c$out 1> c$out)
 }
 
 # functional tests
--- a/main_testing3/re_test.sh	Sat Nov 04 18:53:37 2023 +0000
+++ b/main_testing3/re_test.sh	Mon Nov 06 14:18:26 2023 +0000
@@ -13,7 +13,7 @@
 # compilation tests
 
 function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile "$1" 2> c$out 1> c$out)
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile -Xprint:parser "$1" 2> c$out 1> c$out)
 }
 
 # functional tests
--- a/main_testing4/shogun_test.sh	Sat Nov 04 18:53:37 2023 +0000
+++ b/main_testing4/shogun_test.sh	Mon Nov 06 14:18:26 2023 +0000
@@ -18,7 +18,7 @@
 # compilation tests
 
 function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile "$1" 2> c$out 1> c$out)
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile -color never -Xprint:parser "$1" 2> c$out 1> c$out)
 }
 
 # functional tests
@@ -169,6 +169,12 @@
 fi
 
 
+# legal moves
+if [ $tsts1 -eq 0 ]
+then
+  echo -e " Task 6: automated test cases not yet done" >> $out
+fi
+
 echo -e "" >> $out
 echo -e "" >> $out
 
--- a/main_testing5/bf_test.sh	Sat Nov 04 18:53:37 2023 +0000
+++ b/main_testing5/bf_test.sh	Mon Nov 06 14:18:26 2023 +0000
@@ -14,7 +14,7 @@
 # compilation tests
 
 function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile "$1" 2> c$out 1> c$out)
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile -Xprint:parser "$1" 2> c$out 1> c$out)
 }
 
 # functional tests
--- a/main_testing5/bfc_test.sh	Sat Nov 04 18:53:37 2023 +0000
+++ b/main_testing5/bfc_test.sh	Mon Nov 06 14:18:26 2023 +0000
@@ -13,7 +13,7 @@
 # compilation tests
 
 function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile "$1" 2> c$out 1> c$out)
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala-cli compile -Xprint:parser "$1" 2> c$out 1> c$out)
 }
 
 # functional tests
--- a/mk_jars	Sat Nov 04 18:53:37 2023 +0000
+++ b/mk_jars	Mon Nov 06 14:18:26 2023 +0000
@@ -1,7 +1,7 @@
 #!/bin/bash
 set -e
 
-subdirs=${1:-"core_solution1 core_solution2 core_solution3 main_solution1 main_solution2 main_solution3 main_solution4 main_solution5"} 
+subdirs=${1:-"core_solution1 core_solution2 core_solution3 main_solution2 main_solution3 main_solution4 main_solution5"} 
 
 for sd in $subdirs; do
   cd $sd
Binary file pics/lichess.png has changed
Binary file pics/salary3.png has changed
Binary file slides/slides01.pdf has changed
--- a/slides/slides01.tex	Sat Nov 04 18:53:37 2023 +0000
+++ b/slides/slides01.tex	Mon Nov 06 14:18:26 2023 +0000
@@ -110,7 +110,7 @@
     %Office: & N\liningnums{7.07} (North Wing, Bush House)\bigskip\\
     Slides \& Code: & KEATS\bigskip\\
 
-    Office Hour: &  Fridays 11:00 -- 12:00\\
+    Office Hour: &  Fridays 13:00 -- 14:00\\
     Location: & N7.07 (North Wing, Bush House)\bigskip\\
 
     Pollev: & \texttt{\alert{https://pollev.com/cfltutoratki576}}\\  \\
@@ -141,11 +141,12 @@
 \includegraphics[scale=0.30]{../pics/guardian.jpg}\\[-3mm]
 \mbox{}\hspace{-2mm}\includegraphics[scale=0.38]{../pics/morgan.png}\\[-3mm]
 \includegraphics[scale=0.30]{../pics/suisse.png}\\
+Standard \& Poor's\\  
 {\large\bf ...}
 \end{tabular}
 \end{textblock}
 
-\begin{textblock}{6}(9,3)
+\begin{textblock}{6}(8,3)
 \begin{tabular}{l}
 \includegraphics[scale=0.20]{../pics/edf.png}\\[-1mm]
 \includegraphics[scale=0.08]{../pics/novell.png}\\[-1mm]
@@ -155,6 +156,13 @@
 \end{tabular}
 \end{textblock}
 
+\begin{textblock}{6}(11,3)
+\begin{tabular}{l}
+\includegraphics[scale=0.08]{../pics/lichess.png}\\[-1mm]
+{\footnotesize  lichess engine (open source)}  
+\end{tabular}
+\end{textblock}
+
 
 \begin{textblock}{12}(2,11)
   \footnotesize
@@ -259,18 +267,23 @@
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \begin{frame}[c]
-\frametitle{First Steps: Scala Tools}
+\frametitle{First Steps: \textcolor{red}{Scala 3} Tools}
 
+\mbox{}\\
+
+\begin{minipage}{1.1\textwidth}
 \begin{itemize}
-\item contains a REPL  
-\item I use VS Code and a Scala extension (M'place)
+\item contains a REPL $\Rightarrow$ but this year we use
+  \textcolor{red}{\texttt{scala-cli}}  
+\item I use VS Codium and a Scala extension (M'place)
 \begin{center}  
 \includegraphics[scale=0.10]{../pics/vscode.png}\\[-10mm]\mbox{}
 \end{center}\bigskip
   
 \item there is a plugin for Eclipse (called Scala IDE)\medskip
 \item there is also a plugin for IntelliJ\medskip
-\end{itemize}  
+\end{itemize}
+\end{minipage}
 
 \end{frame}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -297,12 +310,44 @@
 \end{frame}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\begin{frame}[c, fragile]
+\frametitle{This year Scala 3/ \textbf{\texttt{scala-cli}}}
+
+\mbox{}\\
+
+\begin{minipage}{1.3\textwidth}
+\begin{center}
+\textbf{\texttt{scala-cli}}
+$\quad\Rightarrow$ {\small\url{https://scala-cli.virtuslab.org/}}\bigskip
+\end{center}
+
+Installation problems:
+\begin{itemize}
+\item Oscar Sjostedt (\texttt{\small{}oscar.sjostedt@kcl.ac.uk})
+\item Nicole Lehchevska (\texttt{\small{}nicole.lehchevska@kcl.ac.uk})\bigskip
+\end{itemize}
+Github problems:
+\begin{itemize}
+\item Quan Tran (\texttt{\small{}anh.tran@kcl.ac.uk})\bigskip
+\end{itemize}
+Discussion forum:
+\begin{itemize}  
+\item Ruben Ticehurst-James (\texttt{\small{}ruben.ticehurst-james@kcl.ac.uk})  
+\end{itemize}
+\end{minipage}
+  
+\end{frame}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \begin{frame}[t]
 \frametitle{Why Scala?}
 
-\onslide<2->{%
+\only<2-4>{%
 \begin{center} 
 {\large\bf{}Money?}\bigskip\\  
 \begin{tabular}{@{}c@{}c@{}}
@@ -313,19 +358,28 @@
 \end{center}
 \RIGHTarrow{2}{2.0}{6.3}
 \DOWNarrow{2}{10.1}{4.4}
-}
-
 
 \small
 Elm, Rust, Haskell, Ocaml, F$\#$, Erlang, ML, Lisp (Racket)\ldots 
+}
 
 \only<3>{
+\begin{textblock}{2}(7.5,6.7)
+\includegraphics[scale=0.2]{../pics/salary3.png}
+\end{textblock}
+\RIGHTarrow{2}{2.0}{6.3}
+\DOWNarrow{2}{10.1}{4.4}}
+
+
+\only<4>{
 \begin{textblock}{6}(3.3,6.2)
 \begin{bubble}[6.5cm]
 \bf\huge\textcolor{RoyalBlue}{Functional Programming!}
 \end{bubble}
 \end{textblock}}
 
+
+
 \end{frame}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
 
@@ -342,12 +396,12 @@
 Elm, Haskell, Ocaml, F$\#$, Erlang, ML, Lisp (Racket)\ldots 
 
 \only<2>{
-\begin{textblock}{6}(1.3,6.2)
-\begin{bubble}[10cm]
-\normalsize``If you want to see which features will be in mainstream programming
+\begin{textblock}{8}(1.3,6.2)
+\begin{bubble}[12cm]
+\normalsize\it``If you want to see which features will be in mainstream programming
   languages tomorrow, then take a look at functional programming
   languages today.''\medskip\small\\
-  \hfill{}---Simon Peyton Jones (works at Microsoft)\\
+  \hfill{}---Simon Peyton Jones (works at Epic Games, used to work at Microsoft)\\
   \hfill{}main developer of the Glasgow Haskell Compiler
 \end{bubble}
 \end{textblock}}
@@ -898,7 +952,8 @@
 \begin{frame}[t,fragile]
 
 \begin{bubble}[10.5cm]
-  "PEP was my favourite module so far during these 2 years. It motivated me to apply and get a summer internship offer at S\&P Global as a Scala developer. The module content was more than enough for me to start working on the projects here at the company." -- Szabolcs Daniel Nagi (PEP 2021)
+\it  "PEP was my favourite module so far during these 2 years. It motivated me to apply and get a summer internship offer at S\&P Global as a Scala developer. The module content was more than enough for me to start working on the projects here at the company."\\
+  \mbox{}\hfill{}--- Szabolcs Daniel Nagi (PEP 2021)
 \end{bubble}  
 \end{frame}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
@@ -909,18 +964,18 @@
 \frametitle{Conclusion for Today}
 
 \begin{itemize}
-\item Scala is still under development, 2.13.1 came out in Sept.\\ 
-  (the compiler is terribly slow)\medskip
-\item {\bf\url{http://www.scala-lang.org/}}\bigskip
+\item This year we will be using Scala 3 with the \texttt{scala-cli} REPL!\\ 
+  \medskip
+\item {\bf\url{https://scala-cli.virtuslab.org/}}\bigskip
   
-\item it is a rather \textbf{\alert{deep}} language\ldots i.e.~gives
-  you a lot of rope to shoot yourself\bigskip
+\item Scala can be a rather \textbf{\alert{deep}} language\ldots i.e.~gives
+  you a lot of rope to shoot yourself.\bigskip
 
-\item learning functional programming is not easy\ldots{}when you have
+\item Learning functional programming is not easy\ldots{}when you have
   spent all of your career thinking in an imperative way, it is hard to
-  change\bigskip\medskip
+  change.\bigskip\medskip
   
-\item hope you have fun with Scala and the assignments
+\item Hope you have fun with Scala and the assignments.
 \end{itemize}
 \end{frame}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%