updated
authorChristian Urban <urbanc@in.tum.de>
Mon, 27 Jan 2020 10:18:13 +0000
changeset 329 8a34b2ebc8cc
parent 328 0e591f806290
child 330 c3d3461a5e77
updated
IDEAS
README
cws/cw02.tex
cws/cw03.pdf
cws/cw03.tex
handouts/pep-ho.pdf
handouts/pep-ho.tex
marking4/mk-advanced
marking4/mk-postfix
marking4/postfix_test.sh
marking4/postfix_test10.scala
marking4/postfix_test9.scala
misc/decompile
progs/lecture1.scala
progs/lecture2.scala
progs/lecture5.scala
progs/mandelbrot.scala
progs/sudoku.scala
solutions5/bf.jar
solutions5/bf.scala
testing1/collatz_test.sh
testing1/drumb.scala
testing2/danube.scala
testing3/knight_test.sh
testing3/knight_test7.scala
testing3/knight_test8.scala
testing4/re.scala
testing4/re_test.sh
testing5/bf_test4.scala
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IDEAS	Mon Jan 27 10:18:13 2020 +0000
@@ -0,0 +1,8 @@
+flight data
+
+https://blog.jonlu.ca/posts/aa-tracker?ref=rprog
+
+==============
+knight
+
+if one field is reachable from another in three moves
\ No newline at end of file
--- a/README	Tue Dec 03 11:07:09 2019 +0000
+++ b/README	Mon Jan 27 10:18:13 2020 +0000
@@ -3,7 +3,8 @@
 
 java -jar procyon-decompiler-0.5.36.jar -jar templates1/drumb.jar -o out
 
-
+-------------------------
+~/pep-material/moss/mossnet -l java -b ../base.java *.java
 -------------------------
 
 
--- a/cws/cw02.tex	Tue Dec 03 11:07:09 2019 +0000
+++ b/cws/cw02.tex	Mon Jan 27 10:18:13 2020 +0000
@@ -7,6 +7,8 @@
 \begin{document}
 
 
+%% should ask to lower case the words.
+
 \section*{Part 7 (Scala)}
 
 \mbox{}\hfill\textit{``What one programmer can do in one month,}\\
Binary file cws/cw03.pdf has changed
--- a/cws/cw03.tex	Tue Dec 03 11:07:09 2019 +0000
+++ b/cws/cw03.tex	Mon Jan 27 10:18:13 2020 +0000
@@ -348,8 +348,8 @@
 \noindent
 As you should have seen in the earlier parts, a naive search for tours beyond
 $8 \times 8$ boards and also searching for closed tours even on small
-boards takes too much time. There is a heuristic, called \emph{Warnsdorf's
-Rule} that can speed up finding a tour. This heuristic states that a
+boards takes too much time. There is a heuristics, called \emph{Warnsdorf's
+Rule} that can speed up finding a tour. This heuristics states that a
 knight is moved so that it always proceeds to the field from which the
 knight will have the \underline{fewest} onward moves.  For example for
 a knight on field $(1, 3)$, the field $(0, 1)$ has the fewest possible
@@ -386,7 +386,7 @@
   Warnsdorf’s Rule. That means moves with the fewest legal onward moves
   should come first (in order to be tried out first). \hfill[1 Mark]
   
-\item[(7)] Implement a \texttt{first\_closed\_tour\_heuristic}
+\item[(7)] Implement a \texttt{first\_closed\_tour\_heuristics}
   function that searches for a single
   \textbf{closed} tour on a $6\times 6$ board. It should try out
   onward moves according to
@@ -394,13 +394,13 @@
   a solution when started in the middle of the board (that is
   position $(dimension / 2, dimension / 2)$). \hfill[1 Mark]
 
-\item[(8)] Implement a \texttt{first\_tour\_heuristic} function
+\item[(8)] Implement a \texttt{first\_tour\_heuristics} function
   for boards up to
   $30\times 30$.  It is the same function as in (7) but searches for
   tours (not just closed tours). It might be called with any field on the
   board as starting field.\\
   %You have to be careful to write a
-  %tail-recursive function of the \texttt{first\_tour\_heuristic} function
+  %tail-recursive function of the \texttt{first\_tour\_heuristics} function
   %otherwise you will get problems with stack-overflows.\\
   \mbox{}\hfill[1 Mark]
 \end{itemize}    
Binary file handouts/pep-ho.pdf has changed
--- a/handouts/pep-ho.tex	Tue Dec 03 11:07:09 2019 +0000
+++ b/handouts/pep-ho.tex	Mon Jan 27 10:18:13 2020 +0000
@@ -42,6 +42,44 @@
 % https://www.matthewgerstman.com/map-filter-reduce/
 
 
+% Timing
+%
+% xs.map(x => (x, xs.count(_==x)))
+%
+% vs  xs.groupBy(identity)
+%
+% first is quadratic, while second is linear.
+
+% contrast map with a for loop in imperative languages
+%
+% Let’s use a simple example of calculating sales tax on an array of
+% prices.
+%
+%       const prices = [19.99, 4.95, 25, 3.50];
+%       let new_prices = [];
+%
+%       for(let i=0; i < prices.length; i++) {
+%          new_prices.push(prices[i] * 1.06);
+%       }
+%
+% We can achieve the same results using .map():
+%
+% const prices = [19.99, 4.95, 25, 3.50]; 
+% let new_prices = prices.map(price => price * 1.06);
+%
+% The syntax above is condensed so let’s walk through it a bit. The
+% .map() method takes a callback, which can be thought of as a function.
+% That’s what is between the parentheses. The variable price is the name
+% that will be used to identify each value. Since there’s only one
+% input, we can omit the usual parentheses around the parameters.
+
+% potentially a worked example? Tetris in scala.js
+%  
+% https://medium.com/@michael.karen/learning-modern-javascript-with-tetris-92d532bcd057
+%
+% Scala videos
+%    https://www.youtube.com/user/DrMarkCLewis
+
 \begin{document}
 \fnote{\copyright{} Christian Urban, King's College London, 2017, 2018, 2019}
 
@@ -1009,6 +1047,16 @@
 all aggregate functions are pre-defined and often you have to write your
 own recursive function for this.
 
+\subsection*{Always Produce a Result! No Exceptions!}
+%
+%Function should always produce a value. Exception is not thrown.
+%Whenever there is a possibility of non-value result (exception, void,
+%undefined, null, etc.), it should be incorporated in the result type.
+%Such types include but not limited to
+%
+%Option[T]
+
+
 \subsection*{Higher-Order Functions}
 
 Functions obviously play a central role in functional programming. Two simple
--- a/marking4/mk-advanced	Tue Dec 03 11:07:09 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-#!/bin/sh
-###set -e
-
-trap "exit" INT
-
-files=${1:-assignment20189-*}
-
-for sd in $files; do
-  cd $sd
-  echo $sd
-  touch .
-  cp ../../../marking4/postfix_test.sh .
-  cp ../../../marking4/postfix_test7.scala .
-  cp ../../../marking4/postfix_test8.scala .
-  cp ../../../marking4/postfix_test9.scala .
-  ./postfix_test.sh output
-  rm postfix_test.sh
-  rm postfix_test7.scala
-  rm postfix_test8.scala
-  rm postfix_test9.scala
-  cd ..
-done
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/marking4/mk-postfix	Mon Jan 27 10:18:13 2020 +0000
@@ -0,0 +1,25 @@
+#!/bin/sh
+###set -e
+
+trap "exit" INT
+
+files=${1:-assignment2019-*/Part8/*}
+
+for sd in $files; do
+  cd $sd
+  echo $sd
+  touch .
+  cp ../../../../../marking4/postfix_test.sh .
+  cp ../../../../../marking4/postfix_test7.scala .
+  cp ../../../../../marking4/postfix_test8.scala .
+  cp ../../../../../marking4/postfix_test9.scala .
+  ./postfix_test.sh output
+  rm postfix_test.sh
+  rm postfix_test7.scala
+  rm postfix_test8.scala
+  rm postfix_test9.scala
+  cd ..
+  cd ..
+done
+
+
--- a/marking4/postfix_test.sh	Tue Dec 03 11:07:09 2019 +0000
+++ b/marking4/postfix_test.sh	Mon Jan 27 10:18:13 2020 +0000
@@ -8,12 +8,12 @@
 
 
 echo -e "Below is the feedback and provisional marks for your submission" >> $out
-echo -e "the preliminary part for assignment 9.  Please note all marks are provisional until" >> $out
+echo -e "of Preliminar 9.  Please note all marks are provisional until" >> $out
 echo -e "ratified by the assessment board -- this is not an official" >> $out
 echo -e "results transcript." >> $out
-echo -e "" > $out
+echo -e "" >> $out
 
-# marks for CW9 part 2
+# marks for CW9 preliminary
 marks=$(( 0 ))
 
 
@@ -26,23 +26,25 @@
 # functional tests
 
 function scala_assert {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2")  #2> /dev/null 1> /dev/null) 
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" 2> /dev/null 1> /dev/null) 
 }
 
 # purity test
 
 function scala_vars {
-   (egrep '\bvar\b|\breturn\b|\.par|ListBuffer|mutable|new Array' "$1" 2> /dev/null 1> /dev/null)
+#   (egrep '\bvar\b|\breturn\b|\.par|ListBuffer|mutable|new Array' "$1" 2> /dev/null 1> /dev/null)
+    (egrep '\bvar\b|\breturn\b|ListBuffer|mutable|new Array' "$1" 2> /dev/null 1> /dev/null)
 }
 
 
+
 # var, return, ListBuffer test
 #
 echo -e "postfix.scala does not contain vars, returns, Arrays, ListBuffers etc?" | tee -a $out
 
 if (scala_vars postfix.scala)
 then
-  echo -e "  --> FAIL (make triple-sure your program conforms to the required format)\n" | tee -a $out  
+  echo -e "  --> FAIL\n" | tee -a $out  
   tsts0=$(( 1 ))
 else
   echo -e "  --> success" | tee -a $out  
@@ -101,7 +103,7 @@
      echo -e "  --> success" | tee -a $out
      marks=$(( marks + 1 ))
   else
-     echo "  --> ONE OF THE TESTS FAILED\n" | tee -a $out
+     echo -e "  --> ONE OF THE TESTS FAILED\n" | tee -a $out
   fi
 fi
 
@@ -115,7 +117,7 @@
 
 if (scala_vars postfix2.scala)
 then
-  echo -e "  --> FAIL (make triple-sure your program conforms to the required format)\n" | tee -a $out  
+  echo -e "  --> FAIL\n" | tee -a $out  
   tsts0=$(( 1 ))
 else
   echo -e "  --> success" | tee -a $out  
@@ -125,7 +127,6 @@
 
 # compilation test
 
-# compilation test
 if  [ $tsts0 -eq 0 ]
 then    
   echo -e "postfix2.scala runs?" | tee -a $out
@@ -151,7 +152,18 @@
   echo -e " syard(split(\"5 * 7 / 2\")) == List(\"5\", \"7\", \"*\", \"2\", \"/\")" | tee -a $out
   echo -e " syard(split(\"3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3\")) == " | tee -a $out
   echo -e "         List(\"3\", \"4\", \"8\", \"*\", \"5\", \"1\", \"-\", \"2\", \"3\", \"^\", \"^\", \"/\", \"+\")" | tee -a $out
-  echo -e " " | tee -a $out
+  
+  if (scala_assert "postfix2.scala" "postfix_test9.scala")
+  then
+      echo -e "  --> success" | tee -a $out
+      marks=$(( marks + 1 ))
+  else
+      echo -e "  --> ONE OF THE TESTS FAILED\n" | tee -a $out
+  fi
+fi
+
+if [ $tsts1 -eq 0 ]
+then
   echo -e " compute(syard(split(\"3 + 4 * ( 2 - 1 )\"))) == 7" | tee -a $out
   echo -e " compute(syard(split(\"10 + 12 * 33\"))) == 406" | tee -a $out
   echo -e " compute(syard(split(\"( 5 + 7 ) * 2\"))) == 24" | tee -a $out
@@ -163,10 +175,10 @@
   echo -e " compute(syard(split(\"( 4 ^ 3 ) ^ 2\"))) == 4096" | tee -a $out
   echo -e " compute(syard(split(\"( 3 + 1 ) ^ 2 ^ 3\"))) == 65536" | tee -a $out
   
-  if (scala_assert "postfix2.scala" "postfix_test9.scala")
+  if (scala_assert "postfix2.scala" "postfix_test10.scala")
   then
       echo -e "  --> success" | tee -a $out
-      marks=$(( marks + 2 ))
+      marks=$(( marks + 1 ))
   else
       echo -e "  --> ONE OF THE TESTS FAILED\n" | tee -a $out
   fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/marking4/postfix_test10.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -0,0 +1,13 @@
+import CW9b._
+
+
+assert(compute(syard(split("3 + 4 * ( 2 - 1 )"))) == 7)
+assert(compute(syard(split("10 + 12 * 33"))) == 406)
+assert(compute(syard(split("( 5 + 7 ) * 2"))) == 24)
+assert(compute(syard(split("5 + 7 / 2"))) == 8)
+assert(compute(syard(split("5 * 7 / 2"))) == 17)
+assert(compute(syard(split("9 + 24 / ( 7 - 3 )"))) == 15)
+assert(compute(syard(split("4 ^ 3 ^ 2"))) == 262144)
+assert(compute(syard(split("4 ^ ( 3 ^ 2 )"))) == 262144)
+assert(compute(syard(split("( 4 ^ 3 ) ^ 2"))) == 4096)
+assert(compute(syard(split("( 3 + 1 ) ^ 2 ^ 3"))) == 65536)
--- a/marking4/postfix_test9.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/marking4/postfix_test9.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -7,15 +7,3 @@
 assert(syard(split("5 * 7 / 2")) == List("5", "7", "*", "2", "/"))
 assert(syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3")) == List("3", "4", "8", "*", "5", "1", "-", "2", "3", "^", "^", "/", "+"))
 
-
-
-assert(compute(syard(split("3 + 4 * ( 2 - 1 )"))) == 7)
-assert(compute(syard(split("10 + 12 * 33"))) == 406)
-assert(compute(syard(split("( 5 + 7 ) * 2"))) == 24)
-assert(compute(syard(split("5 + 7 / 2"))) == 8)
-assert(compute(syard(split("5 * 7 / 2"))) == 17)
-assert(compute(syard(split("9 + 24 / ( 7 - 3 )"))) == 15)
-assert(compute(syard(split("4 ^ 3 ^ 2"))) == 262144)
-assert(compute(syard(split("4 ^ ( 3 ^ 2 )"))) == 262144)
-assert(compute(syard(split("( 4 ^ 3 ) ^ 2"))) == 4096)
-assert(compute(syard(split("( 3 + 1 ) ^ 2 ^ 3"))) == 65536)
--- a/misc/decompile	Tue Dec 03 11:07:09 2019 +0000
+++ b/misc/decompile	Mon Jan 27 10:18:13 2020 +0000
@@ -9,20 +9,37 @@
   (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala "$1" 2>> /dev/null 1>> /dev/null) 
 }
 
+
+#for sd in $files; do
+#  cd $sd/Part7
+#  echo $sd
+#  if (scala_compile docdiff.scala)
+#  then    
+#    scalac -g:notailcalls -d docdiff-decompiled.jar docdiff.scala
+#    java -jar ~/pep-material/procyon-decompiler-0.5.36.jar -ln -jar docdiff-decompiled.jar -o .
+#    rm CW7a.java
+#    mv CW7a$.java $sd-CW7a.java
+#  else
+#    echo -e "  --> SCALA DID NOT RUN docdiff.scala" 
+#  fi  
+#  cd ..
+#  cd ..
+#done
+
+
+
 for sd in $files; do
-  cd $sd/Part7
+  cd $sd/Part9
   echo $sd
-  if (scala_compile docdiff.scala)
+  if (scala_compile postfix2.scala)
   then    
-    scalac -g:notailcalls -d docdiff-decompiled.jar docdiff.scala
+    scalac -g:notailcalls -d docdiff-decompiled.jar postfix2.scala
     java -jar ~/pep-material/procyon-decompiler-0.5.36.jar -ln -jar docdiff-decompiled.jar -o .
-    rm CW7a.java
-    mv CW7a$.java $sd-CW7a.java
+    rm CW9b.java
+    mv CW9b$.java $sd-CW9b.java
   else
     echo -e "  --> SCALA DID NOT RUN docdiff.scala" 
   fi  
   cd ..
   cd ..
 done
-
-
--- a/progs/lecture1.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/progs/lecture1.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -425,7 +425,17 @@
 // - no vars, no ++i, no +=
 // - no mutable data-structures (no Arrays, no ListBuffers)
 
-// But what the heck....
+// But what the heck....lets try to count to 1 Mio in parallel
+
+var cnt = 0
+
+for(i <- (1 to 1000000).par) cnt += 1
+
+println(s"Should be 1 Mio: $cnt")
+
+
+
+// Or
 // Q: Count how many elements are in the intersections of 
 //    two sets?
 // A; IMPROPER WAY (mutable counter)
--- a/progs/lecture2.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/progs/lecture2.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -505,6 +505,14 @@
 combs("abc".toList, 2)
 
 
+// When writing recursive functions you have to
+// think about three points
+// 
+// - How to start with a recursive function
+// - How to communicate between recursive calls
+// - Exit conditions
+
+
 
 // A Recursive Web Crawler / Email Harvester
 //===========================================
--- a/progs/lecture5.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/progs/lecture5.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -2,13 +2,12 @@
 //=================
 
 
-
 // Laziness with style
 //=====================
 
 // The concept of lazy evaluation doesn’t really 
 // exist in non-functional languages. C-like languages
-// are strict. To see the difference, consider
+// are (sort of) strict. To see the difference, consider
 
 def square(x: Int) = x * x
 
@@ -16,12 +15,12 @@
 
 // This is called "strict evaluation".
 
-// In contrast, say we have a pretty expensive operation:
+// On the contrary, say we have a pretty expensive operation:
 
 def peop(n: BigInt): Boolean = peop(n + 1) 
 
 val a = "foo"
-val b = "bar"
+val b = "foo"
 
 if (a == b || peop(0)) println("true") else println("false")
 
@@ -48,7 +47,7 @@
 val primes = generatePrimes(LazyList.from(2))
 
 // the first 10 primes
-primes.take(10).toList
+primes.take(100).toList
 
 time_needed(1, primes.filter(_ > 100).take(3000).toList)
 time_needed(1, primes.filter(_ > 100).take(3000).toList)
@@ -113,14 +112,7 @@
 }
 
 
-def depth(r: Rexp) : Int = r match {
-  case ZERO => 0
-  case ONE => 0
-  case CHAR(_) => 0
-  case ALT(r1, r2) => Math.max(depth(r1), depth(r2)) + 1
-  case SEQ(r1, r2) => Math.max(depth(r1), depth(r2)) + 1 
-  case STAR(r1) => depth(r1) + 1
-}
+
 
 //example regular expressions
 val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
@@ -157,7 +149,17 @@
 
 
 enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(200).force
-enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(5_000_000)
+enum(LazyList(ZERO, ONE, CHAR('a'), CHAR('b'))).take(5_000_000).force
+
+
+def depth(r: Rexp) : Int = r match {
+  case ZERO => 0
+  case ONE => 0
+  case CHAR(_) => 0
+  case ALT(r1, r2) => Math.max(depth(r1), depth(r2)) + 1
+  case SEQ(r1, r2) => Math.max(depth(r1), depth(r2)) + 1 
+  case STAR(r1) => depth(r1) + 1
+}
 
 
 val is = 
@@ -176,7 +178,7 @@
 
 def length_string_list(lst: List[String]): Int = lst match {
   case Nil => 0
-  case x::xs => 1 + length_string_list(xs)
+  case _::xs => 1 + length_string_list(xs)
 }
 
 def length_int_list(lst: List[Int]): Int = lst match {
@@ -185,7 +187,7 @@
 }
 
 length_string_list(List("1", "2", "3", "4"))
-length_int_list(List(1, 2, 3, 4))
+length_string_list(List(1, 2, 3, 4))
 
 // you can make the function parametric in type(s)
 
@@ -193,7 +195,7 @@
   case Nil => 0
   case x::xs => 1 + length(xs)
 }
-length(List("1", "2", "3", "4"))
+length[String](List("1", "2", "3", "4"))
 length(List(1, 2, 3, 4))
 
 
@@ -220,7 +222,7 @@
   case Nil => Nil
   case x::xs => {
     val res = f(x)
-    if (acc.contains(res)) distinctBy(xs, f, acc)  
+    if (acc.contains(res) distinctBy(xs, f, acc)  
     else x::distinctBy(xs, f, res::acc)
   }
 } 
@@ -242,7 +244,7 @@
 val y = id("hey")        // String
 val z = id(Set(1,2,3,4)) // Set[Int]
 
-
+id[+A, -B]
 
 // The type variable concept in Scala can get really complicated.
 //
@@ -266,13 +268,13 @@
 arr(0) = "Hello World"
 
 
-
 // (Immutable)
 // Object Oriented Programming in Scala
 //
 // =====================================
 
-abstract class Animal
+
+abstract class Animal 
 case class Bird(name: String) extends Animal {
    override def toString = name
 }
@@ -393,8 +395,6 @@
 (1 / 2) + third
 
 
-
-
 // DFAs in Scala  
 //===============
 import scala.util.Try
@@ -548,11 +548,14 @@
 
 two - one == one
 eight - six == two
-
+eight - six
 
 
+// problems about equality and type-errors
 
-List(1, 2, 3).contains("your cup")
+List(1, 2, 3).contains("your cup")   // should not compile, but retruns false
+
+List(1, 2, 3) == Vector(1, 2, 3)     // again should not compile, but returns true
 
 
 // I like best about Scala that it lets me often write
@@ -562,9 +565,9 @@
 
 // Puzzlers
 
-val MONTH = 12
-val DAY = 24
-val (HOUR, MINUTE, SECOND) = (12, 0, 0)
+val month = 12
+val day = 24
+val (hour, min, sec) = (12, 0, 0)
 
 // use lowercase names for variable 
 
@@ -573,14 +576,14 @@
 val oneTwo = Seq(1, 2, 3).permutations
 
 if (oneTwo.length > 0) {
-  println("Permutations of 1 and 2:")
+  println("Permutations of 1,2 and 3:")
   oneTwo.foreach(println)
 }
 
 val threeFour = Seq(3, 4, 5).permutations
 
 if (!threeFour.isEmpty) {
-  println("Permutations of 3 and 4:")
+  println("Permutations of 3, 4 and 5:")
   threeFour.foreach(println)
 }
 
@@ -610,4 +613,4 @@
 
 //================
 // does not work anymore in 2.13.0
-val numbers = List("1", "2").toSet() + "3"
\ No newline at end of file
+val numbers = List("1", "2").toSet + "3"
--- a/progs/mandelbrot.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/progs/mandelbrot.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -104,8 +104,8 @@
   val d_x = (end.re - start.re) / W
   val d_y = (end.im - start.im) / H
    
-  for (y <- (0 until H)) {
-    for (x <- (0 until W)) {
+  for (y <- (0 until H).par) {
+    for (x <- (0 until W).par) {
     
      val c = start + 
       (x * d_x + y * d_y * i)
--- a/progs/sudoku.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/progs/sudoku.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -64,6 +64,10 @@
   }
 }
 
+def pretty(game: String): String = 
+  "\n" + (game.sliding(maxValue, maxValue).mkString(",\n"))
+
+
 // a list of hard games according to Andrew Coles and Peter Norvig
 
 val hard_games = 
@@ -180,6 +184,9 @@
        "....14....3....2...7..........9...3.6.1.............8.2.....1.4....5.6.....7.8...",
        "4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......")
 
+println("108:\n" ++ pretty(hard_games(108).replaceAll("\\.", " ")) ++ "\n")
+println("109:\n" ++ pretty(hard_games(109).replaceAll("\\.", " ")) ++ "\n")
+
 
 // for measuring time
 def time_needed[T](i: Int, code: => T) = {
Binary file solutions5/bf.jar has changed
--- a/solutions5/bf.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/solutions5/bf.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -1,13 +1,15 @@
 // Part 1 about an Interpreter for the Brainf*** language
 //========================================================
 
+
 object CW10a {  
 
-type Mem = Map[Int, Int]
+import io.Source
+import scala.util._
 
 
-import io.Source
-import scala.util._
+type Mem = Map[Int, Int]
+
 
 // (1) Write a function that takes a file name as argument and
 // and requests the corresponding file from disk. It returns the
@@ -92,6 +94,7 @@
       case '-' => (pc + 1, mp, write(mem, mp, sread(mem, mp) - 1))
       case '.' => { print(sread(mem, mp).toChar); (pc + 1, mp, mem) }
       case ',' => (pc + 1, mp, write(mem, mp, Console.in.read().toByte))
+      //case ',' => (pc + 1, mp, write(mem, mp, scala.io.StdIn.readByte()))
       case '['  => 
 	if (sread(mem, mp) == 0) (jumpRight(prog, pc + 1, 0), mp, mem) else (pc + 1, mp, mem) 
       case ']'  => 
@@ -173,6 +176,7 @@
     >>>+[[-]++++++>>>]<<<[[<++++++++<++>>-]+<.<[>----<-]<]
     <<[>>>>>[>>>[-]+++++++++<[>-<-]+++++++++>[-[<->-]+[<<<]]<[>+<-]>]<<-]<<-]""")
 
+
 //collatz numbers (needs a number to be typed in)
 run(""">,[[----------[
       >>>[>>>>]+[[-]+<[->>>>++>>>>+[>>>>]++[->+<<<<<]]<<<]
@@ -244,3 +248,4 @@
 */
 
 }
+
--- a/testing1/collatz_test.sh	Tue Dec 03 11:07:09 2019 +0000
+++ b/testing1/collatz_test.sh	Mon Jan 27 10:18:13 2020 +0000
@@ -27,7 +27,7 @@
 # purity test
 
 function scala_vars {
-   (egrep '\bvar\b|\breturn\b|\.par|ListBuffer|mutable|new Array' "$1" 2> /dev/null 1> /dev/null)
+   (egrep '\bvar\b|\breturn\b|\.par|ListBuffer|collection.mutable|util.control|new Array' "$1" 2> /dev/null 1> /dev/null)
 }
 
 
--- a/testing1/drumb.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/testing1/drumb.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -1,7 +1,12 @@
-// Main Part about a really dumb investment strategy
-//======================================================
+// Core Part 6 about a really dumb investment strategy
+//=====================================================
+
 
-object CW6b {
+// generate jar with
+//   > scala -d drumb.jar  drumb.scala
+
+
+object CW6b { 
 
 
 //two test portfolios
--- a/testing2/danube.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/testing2/danube.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -2,118 +2,114 @@
 // at Danube.co.uk
 //===========================================
 
-object CW7b {
-
 import io.Source
 import scala.util._
 
+object CW7b { // for purposes of generating a jar
+
 // (1) Implement the function get_csv_url which takes an url-string
 //     as argument and requests the corresponding file. The two urls
 //     of interest are ratings_url and movies_url, which correspond 
 //     to CSV-files.
-//
-//     The function should ReTurn the CSV-file appropriately broken
+//     The function should ReTurn the CSV file appropriately broken
 //     up into lines, and the first line should be dropped (that is without
-//     the header of the CSV-file). The result is a list of strings (lines
+//     the header of the CSV file). The result is a list of strings (lines
 //     in the file).
 
 def get_csv_url(url: String) : List[String] = {
-    Try(Source.fromURL(url)("UTF-8").mkString.split("\n").toList.tail).getOrElse(List())
+  val csv = Source.fromURL(url)("ISO-8859-1")
+  csv.mkString.split("\n").toList.drop(1)
 }
 
-
 val ratings_url = """https://nms.kcl.ac.uk/christian.urban/ratings.csv"""
 val movies_url = """https://nms.kcl.ac.uk/christian.urban/movies.csv"""
 
-// testcases
-//-----------
-// val ratings = get_csv_url(ratings_url)
-// val movies = get_csv_url(movies_url)
+// test cases
+
+//val ratings = get_csv_url(ratings_url)
+//val movies = get_csv_url(movies_url)
 
 //ratings.length  // 87313
 //movies.length   // 9742
 
-
-
-// (2) Implement two functions that process the CSV-files from (1). The ratings
+// (2) Implement two functions that process the CSV files. The ratings
 //     function filters out all ratings below 4 and ReTurns a list of 
 //     (userID, movieID) pairs. The movies function just ReTurns a list 
-//     of (movieID, title) pairs.
+//     of (movieId, title) pairs.
 
 
 def process_ratings(lines: List[String]) : List[(String, String)] = {
-    val filteredLines = lines.filter(line => line.split(",")(2).toInt >= 4)
-    filteredLines.map(line => (line.split(",")(0), line.split(",")(1)))
+  for (cols <- lines.map(_.split(",").toList); 
+       if (cols(2).toFloat >= 4)) yield (cols(0), cols(1))  
 }
 
 def process_movies(lines: List[String]) : List[(String, String)] = {
-    lines.map(line => (line.split(",")(0), line.split(",")(1)))
+  for (cols <- lines.map(_.split(",").toList)) yield (cols(0), cols(1))  
 }
 
+// test cases
 
-// testcases
-//-----------
-// val good_ratings = process_ratings(ratings)
-// val movie_names = process_movies(movies)
+//val good_ratings = process_ratings(ratings)
+//val movie_names = process_movies(movies)
 
 //good_ratings.length   //48580
 //movie_names.length    // 9742
 
+//==============================================
+// Do not change anything below, unless you want 
+// to submit the file for the advanced part 3!
+//==============================================
+
+
+// (3) Implement a grouping function that calulates a map
+//     containing the userIds and all the corresponding recommendations 
+//     (list of movieIds). This  should be implemented in a tail
+//     recursive fashion, using a map m as accumulator. This map
+//     is set to Map() at the beginning of the claculation.
+
+def groupById(ratings: List[(String, String)], 
+              m: Map[String, List[String]]) : Map[String, List[String]] = ratings match {
+  case Nil => m
+  case (id, mov) :: rest => {
+    val old_ratings = m.getOrElse (id, Nil)
+    val new_ratings = m + (id -> (mov :: old_ratings))
+    groupById(rest, new_ratings)
+  }
+}
+
+//
+//val ls = List(("1", "a"), ("2", "a"), ("1", "c"), ("2", "a"), ("1", "c"))
+//
+//val m = groupById(ls, Map())
+//
+//m.getOrElse("1", Nil).count(_ == "c") // => 2
+//m.getOrElse("1", Nil).count(_ == "a") // => 1
+
+// test cases
+//val ratings_map = groupById(good_ratings, Map())
+//groupById(good_ratings, Map()).get("214")
+//groupById(good_ratings, Map()).toList.minBy(_._2.length)
+//val movies_map = movie_names.toMap
+
+//ratings_map.get("414").get.map(movies_map.get(_)) // most prolific recommender with 1227 positive ratings
+//ratings_map.get("474").get.map(movies_map.get(_)) // second-most prolific recommender with 787 positive ratings
+//ratings_map.get("214").get.map(movies_map.get(_)) // least prolific recommender with only 1 positive rating
 
 
 
-// (3) Implement a grouping function that calculates a Map
-//     containing the userIDs and all the corresponding recommendations 
-//     (list of movieIDs). This  should be implemented in a tail
-//     recursive fashion, using a Map m as accumulator. This Map m
-//     is set to Map() at the beginning of the calculation.
+//(4) Implement a function that takes a ratings map and a movie_name as argument.
+// The function calculates all suggestions containing
+// the movie mov in its recommendations. It ReTurns a list of all these
+// recommendations (each of them is a list and needs to have mov deleted, 
+// otherwise it might happen we recommend the same movie).
 
-def groupById(ratings: List[(String, String)], 
-              m: Map[String, List[String]]) : Map[String, List[String]] = {
-    if (ratings.length == 0) m
-    else {
-        val firstUser = ratings(0)._1
-        val userRatings = ratings.filter(r => r._1 == firstUser)
-        val movieIds = userRatings.map(r => r._2)
-        val newMap = m + (firstUser -> movieIds)
-        groupById(ratings.filter(r => r._1 != firstUser), newMap)
-    }
-}
-
-
-// testcases
-//-----------
-//val ratings_map = groupById(good_ratings, Map())
-//val movies_map = movie_names.toMap
-
-//ratings_map.get("414").get.map(movies_map.get(_)) 
-//    => most prolific recommender with 1227 positive ratings
-
-//ratings_map.get("474").get.map(movies_map.get(_)) 
-//    => second-most prolific recommender with 787 positive ratings
-
-//ratings_map.get("214").get.map(movies_map.get(_)) 
-//    => least prolific recommender with only 1 positive rating
+def favourites(m: Map[String, List[String]], mov: String) : List[List[String]] = 
+  (for (id <- m.keys.toList;
+        if m(id).contains(mov)) yield m(id).filter(_ != mov))
 
 
 
-// (4) Implement a function that takes a ratings map and a movie_name as argument.
-//     The function calculates all suggestions containing
-//     the movie in its recommendations. It ReTurns a list of all these
-//     recommendations (each of them is a list and needs to have the movie deleted, 
-//     otherwise it might happen we recommend the same movie).
-
-
-def favourites(m: Map[String, List[String]], mov: String) : List[List[String]] = {
-    val movieLists = m.map(r => r._2).toList.filter(_.contains(mov))
-    for (movieList <- movieLists) yield {
-        movieList.filter(_!=mov)
-    }
-}
-
-
-// testcases
-//-----------
+// test cases
 // movie ID "912" -> Casablanca (1942)
 //          "858" -> Godfather
 //          "260" -> Star Wars: Episode IV - A New Hope (1977)
@@ -125,53 +121,45 @@
 // 52 a good rating to movies 260, 318, 593.
 
 
+// (5) Implement a suggestions function which takes a rating
+// map and a movie_name as arguments. It calculates all the recommended
+// movies sorted according to the most frequently suggested movie(s) first.
 
-// (5) Implement a suggestions function which takes a rating
-//     map and a movie_name as arguments. It calculates all the recommended
-//     movies sorted according to the most frequently suggested movie(s) first.
-
+// needed in Scala 2.13.
+ 
+def mapValues[S, T, R](m: Map[S, T], f: T => R) =
+  m.map { case (x, y) => (x, f(y)) }
 
 def suggestions(recs: Map[String, List[String]], 
-                mov_name: String) : List[String] = {
-    val favs = favourites(recs, mov_name).flatten
-    favs.map(x => (x, favs.count(_==x)))
-        .sortBy(_._1)
-        .reverse
-        .sortBy(_._2)
-        .reverse
-        .distinct
-        .map(_._1)
+                    mov_name: String) : List[String] = {
+  val favs = favourites(recs, mov_name).flatten
+  val favs_counted = mapValues(favs.groupBy(identity), (v:List[String]) => v.size).toList
+  val favs_sorted = favs_counted.sortBy(_._2).reverse
+  favs_sorted.map(_._1)
 }
 
+// check
+// groupMap is equivalent to groupBy(key).mapValues(_.map(f))
 
-// testcases
-//-----------
+// test cases
 
 //suggestions(ratings_map, "912")
 //suggestions(ratings_map, "912").length  
 // => 4110 suggestions with List(858, 260, 318, 593, ...)
 //    being the most frequently suggested movies
 
-
-
-// (6) Implement a recommendations function which generates at most
-//     *two* of the most frequently suggested movies. It ReTurns the 
-//     actual movie names, not the movieIDs.
-
+// (6) Implement recommendations functions which generates at most
+// *two* of the most frequently suggested movies. It Returns the 
+// actual movie names, not the movieIDs.
 
 def recommendations(recs: Map[String, List[String]],
-                    movs: Map[String, String],
-                    mov_name: String) : List[String] = {
-    val sug = suggestions(recs, mov_name)
-    val toptwo = sug.take(2)
-    if (toptwo.length == 0) Nil
-    else toptwo.map(movs(_))
-}
-
+                   movs: Map[String, String],
+                   mov_name: String) : List[String] =
+  suggestions(recs, mov_name).take(2).map(movs.get(_).get)                 
 
 
 // testcases
-//-----------
+
 // recommendations(ratings_map, movies_map, "912")
 //   => List(Godfather, Star Wars: Episode IV - A NewHope (1977))
 
@@ -189,11 +177,11 @@
 //   => List(Shawshank Redemption, Forrest Gump (1994))
 
 // recommendations(ratings_map, movies_map, "4")
-//   => Nil  (there are three ratings for this movie in ratings.csv but they are not positive)     
+//   => Nil  (there are three ratings fro this movie in ratings.csv but they are not positive)     
 
 
-// If you want to calculate the recommendations for all movies,
-// then use this code (it will take a few seconds calculation time).
+// If you want to calculate the recomendations for all movies.
+// Will take a few seconds calculation time.
 
 //val all = for (name <- movie_names.map(_._1)) yield {
 //  recommendations(ratings_map, movies_map, name)
@@ -205,32 +193,4 @@
 //List(1,2).take(2)
 //List(1,2,3).take(2)
 
-
-
 }
-
-// val ratings_url = """https://nms.kcl.ac.uk/christian.urban/ratings.csv"""
-// val movies_url = """https://nms.kcl.ac.uk/christian.urban/movies.csv"""
-
-// val ratings = CW7b.get_csv_url(ratings_url)
-// val movies = CW7b.get_csv_url(movies_url)
-
-// println(movies.length)
-// val good_ratings = CW7b.process_ratings(ratings)
-// val movie_names = CW7b.process_movies(movies)
-
-// val ratings_map = CW7b.groupById(good_ratings, Map())
-// val movies_map = movie_names.toMap
-
-
-
-//println(CW7b.recommendations(ratings_map, movies_map, "912"))
-/*
-val ratings_url = """https://nms.kcl.ac.uk/christian.urban/ratings.csv"""
-
-val ratings = CW7b.get_csv_url(ratings_url)
-
-val good_ratings = CW7b.process_ratings(ratings)
-val ratings_map = CW7b.groupById(good_ratings, Map())
-
-println(CW7b.suggestions(ratings_map, "912").length)*/
--- a/testing3/knight_test.sh	Tue Dec 03 11:07:09 2019 +0000
+++ b/testing3/knight_test.sh	Mon Jan 27 10:18:13 2020 +0000
@@ -230,7 +230,7 @@
 if [ $tsts1 -eq 0 ]
 then
   echo -e "For testing needs to take 10 seconds or less to execute: " >> $out  
-  echo -e " first_closed_tour_heuristic(6, List((3,3))) found and correct?" >> $out
+  echo -e " first_closed_tour_heuristics(6, List((3,3))) found and correct?" >> $out
   
   if (scala_assert_quick "knight2.scala" "knight_test7.scala")
   then
@@ -245,8 +245,8 @@
 if [ $tsts1 -eq 0 ]
 then
   echo -e "For testing needs to take 10 seconds or less to execute: " >> $out   
-  echo -e " first_tour_heuristic(8, List((0,0))) found and correct?" >> $out
-  echo -e " first_tour_heuristic(30, List((0,0))) found and correct?" >> $out
+  echo -e " first_tour_heuristics(8, List((0,0))) found and correct?" >> $out
+  echo -e " first_tour_heuristics(30, List((0,0))) found and correct?" >> $out
   
   if (scala_assert_quick "knight2.scala" "knight_test8.scala")
   then
@@ -298,7 +298,7 @@
   echo -e "For testing needs to take 10 seconds or less to execute: " >> $out  
   echo -e " tour_on_mega_board(70, List((0,0))) found and correct?" >> $out
   
-  if (scala_assert_quick "knight3.scala" "knight_test9.scala")
+  if (scala_assert_slow "knight3.scala" "knight_test9.scala")
   then
       echo -e "  --> success" >> $out
   else
--- a/testing3/knight_test7.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/testing3/knight_test7.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -27,6 +27,6 @@
   correct_urban(6)(p) &&  moves_urban(p.head).contains(p.last)
 
 
-val tsc = first_closed_tour_heuristic(6, List((3, 3))).get
+val tsc = first_closed_tour_heuristics(6, List((3, 3))).get
 assert(correct_closed_urban(6)(tsc) == true)
 
--- a/testing3/knight_test8.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/testing3/knight_test8.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -25,9 +25,9 @@
 }
 
 
-val ts8 = first_tour_heuristic(8, List((0,0))).get
+val ts8 = first_tour_heuristics(8, List((0,0))).get
 assert(correct_urban(8)(ts8) == true)
 
-val ts30 = first_tour_heuristic(30, List((0,0))).get
+val ts30 = first_tour_heuristics(30, List((0,0))).get
 assert(correct_urban(30)(ts30) == true)
 
--- a/testing4/re.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/testing4/re.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -8,16 +8,16 @@
 case object ZERO extends Rexp
 case object ONE extends Rexp
 case class CHAR(c: Char) extends Rexp
-case class ALT(r1: Rexp, r2: Rexp) extends Rexp 
-case class SEQ(r1: Rexp, r2: Rexp) extends Rexp 
-case class STAR(r: Rexp) extends Rexp 
+case class ALT(r1: Rexp, r2: Rexp) extends Rexp   // alternative 
+case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence
+case class STAR(r: Rexp) extends Rexp             // star
 
-// some convenience for typing in regular expressions
+
+// 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)
@@ -39,117 +39,137 @@
   def ~ (r: String) = SEQ(s, r)
 }
 
-// (1) Complete the function nullable according to
+// (5) Complete the function nullable according to
 // the definition given in the coursework; this 
 // function checks whether a regular expression
 // can match the empty string and Returns a boolean
 // accordingly.
 
-def nullable (r: Rexp) : Boolean = r match {
-  case ZERO => false
-  case ONE => true
-  case CHAR(_) => false
-  case ALT(r1, r2) => nullable(r1) || nullable(r2)
-  case SEQ(r1, r2) => nullable(r1) && nullable(r2)
-  case STAR(_) => true
+def nullable (r: Rexp) : Boolean = {
+	r match {
+		case ZERO => false
+		case ONE => true
+		case CHAR(c) => false
+		case ALT(r1, r2) => (nullable(r1) || nullable(r2))
+		case SEQ(r1, r2) => (nullable(r1) && nullable(r2))
+		case STAR(r) => true
+	}
 }
 
-// (2) Complete the function der according to
+// (6) Complete the function der according to
 // the definition given in the coursework; this
 // function calculates the derivative of a 
 // regular expression w.r.t. a character.
 
-def der (c: Char, r: Rexp) : Rexp = r match {
-  case ZERO => ZERO
-  case ONE => ZERO
-  case CHAR(d) => if (c == d) ONE else ZERO
-  case ALT(r1, r2) => ALT(der(c, r1), der(c, r2))
-  case SEQ(r1, r2) => 
-    if (nullable(r1)) ALT(SEQ(der(c, r1), r2), der(c, r2))
-    else SEQ(der(c, r1), r2)
-  case STAR(r1) => SEQ(der(c, r1), STAR(r1))
+def der (c: Char, r: Rexp) : Rexp = {
+	r match {
+		case ZERO => ZERO
+		case ONE => ZERO
+		case CHAR(d) => if(d == c) ONE else ZERO
+		case ALT(r1, r2) => ALT(der(c, r1), der(c, r2))
+		case SEQ(r1, r2) => if(nullable(r1)) {
+								(ALT(SEQ(der(c, r1), r2), der(c, r2)))
+							} else {
+								SEQ(der(c, r1), r2)
+							}
+		case STAR(r) => SEQ(der(c, r), STAR(r))
+	}
 }
 
-// (3) Complete the simp function according to
+
+// (7) Complete the simp function according to
 // the specification given in the coursework; this
 // function simplifies a regular expression from
 // the inside out, like you would simplify arithmetic 
 // expressions; however it does not simplify inside 
 // STAR-regular expressions.
 
-def simp(r: Rexp) : Rexp = r match {
-  case ALT(r1, r2) => (simp(r1), simp(r2)) match {
-    case (ZERO, r2s) => r2s
-    case (r1s, ZERO) => r1s
-    case (r1s, r2s) => if (r1s == r2s) r1s else ALT (r1s, r2s)
-  }
-  case SEQ(r1, r2) =>  (simp(r1), simp(r2)) match {
-    case (ZERO, _) => ZERO
-    case (_, ZERO) => ZERO
-    case (ONE, r2s) => r2s
-    case (r1s, ONE) => r1s
-    case (r1s, r2s) => SEQ(r1s, r2s)
-  }
-  case r => r
+def simp(r: Rexp) : Rexp = {
+	r match {
+		case STAR(r) => STAR(r) // does not process r star
+		case SEQ(r1, r2) => {
+			val x = (simp(r1), simp(r2))
+			if(x._1 == ZERO) ZERO else
+			if(x._2 == ZERO) ZERO else
+			if(x._1 == ONE) simp(x._2) else 
+			if(x._2 == ONE) simp(x._1) else
+			if(x._1 == x._2) simp(x._2) else
+			SEQ(simp(x._1), simp(x._2))
+		}
+		case ALT(r1, r2) => {
+			val x = (simp(r1), simp(r2))
+			if(x._1 == ZERO) simp(x._2) else
+			if(x._2 == ZERO) simp(x._1) else
+			if(x._1 == x._2) simp(x._2) else
+			ALT(simp(x._1), simp(x._2))
+		}
+		case r => r // if single regex, return it
+	}
 }
 
 
-// (4) Complete the two functions below; the first 
+// (8) Complete the two functions below; the first 
 // calculates the derivative w.r.t. a string; the second
 // is the regular expression matcher taking a regular
 // expression and a string and checks whether the
-// string matches the regular expression.
+// string matches the regular expression
 
-def ders (s: List[Char], r: Rexp) : Rexp = s match {
-  case Nil => r
-  case c::s => ders(s, simp(der(c, r)))
+def ders (s: List[Char], r: Rexp) : Rexp = {
+	s match {
+		case Nil => r
+		case c :: cs => ders(cs, simp(der(c,r)))
+	}
 }
 
-// main matcher function
-def matcher(r: Rexp, s: String) = nullable(ders(s.toList, r))
+def matcher(r: Rexp, s: String): Boolean = {
+	val listOfCharacters = s.toList
+	val result = ders(listOfCharacters, r)
+	nullable(result)
+}
 
-// (5) Complete the size function for regular
+
+// (9) Complete the size function for regular
 // expressions according to the specification 
 // given in the coursework.
 
-
-def size(r: Rexp): Int = r match {
-  case ZERO => 1
-  case ONE => 1
-  case CHAR(_) => 1
-  case ALT(r1, r2) => 1 + size(r1) + size (r2)
-  case SEQ(r1, r2) => 1 + size(r1) + size (r2)
-  case STAR(r1) => 1 + size(r1)
+def size(r: Rexp): Int = {
+	r match {
+		case ZERO => 1
+		case ONE => 1
+		case CHAR(c) => 1
+		case ALT(r1, r2) => 1 + size(r1) + size(r2)
+		case SEQ(r1, r2) => 1 + size(r1) + size(r2)
+		case STAR(r) => 1 + size(r)
+	}
 }
 
-
-
 // some testing data
 
-//matcher(("a" ~ "b") ~ "c", "abc")  // => true
-//matcher(("a" ~ "b") ~ "c", "ab")   // => false
+/*
+matcher(("a" ~ "b") ~ "c", "abc")  // => true
+matcher(("a" ~ "b") ~ "c", "ab")   // => false
 
 // the supposedly 'evil' regular expression (a*)* b
-val EVIL = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
+// val EVIL = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
 
-//matcher(EVIL, "a" * 1000 ++ "b")   // => true
-//matcher(EVIL, "a" * 1000)          // => false
+matcher(EVIL, "a" * 1000 ++ "b")   // => true
+matcher(EVIL, "a" * 1000)          // => false
 
 // size without simplifications
-//size(der('a', der('a', EVIL)))             // => 28
-//size(der('a', der('a', der('a', EVIL))))   // => 58
+size(der('a', der('a', EVIL)))             // => 28
+size(der('a', der('a', der('a', EVIL))))   // => 58
 
 // size with simplification
-//size(simp(der('a', der('a', EVIL))))           // => 8
-//size(simp(der('a', der('a', der('a', EVIL))))) // => 8
+size(simp(der('a', der('a', EVIL))))           // => 8
+size(simp(der('a', der('a', der('a', EVIL))))) // => 8
 
 // Python needs around 30 seconds for matching 28 a's with EVIL. 
 // Java 9 and later increase this to an "astonishing" 40000 a's in
-// around 30 seconds.
+// 30 seconds.
 //
-// Lets see how long it takes to match strings with 
-// 5 Million a's...it should be in the range of a 
-// couple of seconds.
+// Lets see how long it really takes to match strings with 
+// 5 Million a's...it should be in the range of a couple
+// of seconds.
 
 def time_needed[T](i: Int, code: => T) = {
   val start = System.nanoTime()
@@ -158,19 +178,19 @@
   (end - start)/(i * 1.0e9)
 }
 
-//for (i <- 0 to 5000000 by 500000) {
-//  println(i + " " + "%.5f".format(time_needed(2, matcher(EVIL, "a" * i))) + " secs.") 
-//}
+for (i <- 0 to 5000000 by 500000) {
+  println(i + " " + "%.5f".format(time_needed(2, matcher(EVIL, "a" * i))))
+}
 
 // another "power" test case 
-//simp(Iterator.iterate(ONE:Rexp)(r => SEQ(r, ONE | ONE)).drop(100).next) == ONE
+simp(Iterator.iterate(ONE:Rexp)(r => SEQ(r, ONE | ONE)).drop(50).next) == ONE
 
 // the Iterator produces the rexp
 //
 //      SEQ(SEQ(SEQ(..., ONE | ONE) , ONE | ONE), ONE | ONE)
 //
-//    where SEQ is nested 100 times.
- 
+//    where SEQ is nested 50 times.
 
+*/
 
 }
--- a/testing4/re_test.sh	Tue Dec 03 11:07:09 2019 +0000
+++ b/testing4/re_test.sh	Mon Jan 27 10:18:13 2020 +0000
@@ -107,9 +107,12 @@
   echo -e " simp(ZERO | ONE) == ONE" >> $out
   echo -e " simp(STAR(ZERO | ONE)) == STAR(ZERO | ONE)" >> $out
   echo -e " simp(ONE ~ (ONE ~ (ONE ~ CHAR('a')))) == CHAR('a')" >> $out
+  echo -e " simp(((ONE ~ ONE) ~ ONE) ~ CHAR('a')) == CHAR('a'))" >> $out
+  echo -e " simp(((ONE | ONE) ~ ONE) ~ CHAR('a')) == CHAR('a'))" >> $out
   echo -e " simp(ONE ~ (ONE ~ (ONE ~ ZERO))) == ZERO" >> $out
   echo -e " simp(ALT(ONE ~ (ONE ~ (ONE ~ ZERO)), CHAR('a'))) == CHAR('a')" >> $out
   echo -e " simp(CHAR('a') | CHAR('a')) == CHAR('a')" >> $out
+  echo -e " simp(CHAR('a') ~ CHAR('a')) == CHAR('a') ~ CHAR('a')" >> $out
   echo -e " simp(ONE | CHAR('a')) == (ONE | CHAR('a'))" >> $out
   echo -e " simp(ALT((CHAR('a') | ZERO) ~ ONE," >> $out
   echo -e "          ((ONE | CHAR('b')) | CHAR('c')) ~ (CHAR('d') ~ ZERO))) == CHAR('a')" >> $out
--- a/testing5/bf_test4.scala	Tue Dec 03 11:07:09 2019 +0000
+++ b/testing5/bf_test4.scala	Mon Jan 27 10:18:13 2020 +0000
@@ -3,7 +3,7 @@
 assert(run("[-]", Map(0 -> 100)) == Map(0 -> 0))
 assert(run("[->+<]", Map(0 -> 10)) == Map(0 -> 0, 1 -> 10))
 assert(run("[>>+>>+<<<<-]", Map(0 -> 42)) == Map(0 -> 0, 2 -> 42, 4 -> 42))
-val hw_urban = """+++++[->++++++++++<]>--<+++[->>++++++++++
-                  <<]>>++<<----------[+>.>.<+<]"""
-assert(run(hw_urban) == Map(0 -> 0, 1 -> 58, 2 -> 32))
+//val hw_urban = """+++++[->++++++++++<]>--<+++[->>++++++++++
+//                  <<]>>++<<----------[+>.>.<+<]"""
+//assert(run(hw_urban) == Map(0 -> 0, 1 -> 58, 2 -> 32))