updated
authorChristian Urban <christian.urban@kcl.ac.uk>
Tue, 08 Nov 2022 00:27:47 +0000
changeset 433 6af86ba1208f
parent 432 de701b64a4e0
child 434 8c5804b2f9d2
updated
core_testing1/collatz.scala
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_cw05.pdf
main_testing3/re.scala
main_testing3/re_test.sh
main_testing3/re_test1.scala
main_testing3/re_test2.scala
main_testing3/re_test3.scala
main_testing3/re_test4.scala
main_testing3/re_test5.scala
main_testing3/re_test6.scala
main_testing3/re_test7.scala
main_testing3/re_test8.scala
main_testing3/re_test9.scala
main_testing4/knight1.scala
main_testing4/knight3.scala
main_testing4/knight_test.sh
main_testing4/knight_test10.scala
--- a/core_testing1/collatz.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/core_testing1/collatz.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -1,51 +1,53 @@
 // Core Part 1 about the 3n+1 conjecture
-//==================================
+//============================================
+
+object C1 {
+
+// ADD YOUR CODE BELOW
+//======================
 
-// generate jar with
-//   > scala -d collatz.jar  collatz.scala
+// test1 7 Nov
+// test2
+// test3
+// test4
 
-object C1 { // for purposes of generating a jar
 
-def collatz(n: Long): Long =
+//(1) 
+def collatz(n: Long) : Long = 
   if (n == 1) 0 else
     if (n % 2 == 0) 1 + collatz(n / 2) else 
       1 + collatz(3 * n + 1)
 
 
+//(2) 
+//def collatz_max(bnd: Long) : (Long, Long) = {
+//  val all = for (i <- (1L to bnd)) yield (collatz(i), i)
+//  all.maxBy(_._1)
+//}
+
 def collatz_max(bnd: Long): (Long, Long) = {
   val all = for (i <- (1L to bnd)) yield (collatz(i), i)
   all.maxBy(_._1)
 }
 
-//collatz_max(1000000)
-
-
-/* some test cases
-val bnds = List(10, 100, 1000, 10000, 100000, 1000000)
-
-for (bnd <- bnds) {
-  val (steps, max) = collatz_max(bnd)
-  println(s"In the range of 1 - ${bnd} the number ${max} needs the maximum steps of ${steps}")
-}
-
-*/
 
 
-def is_pow(n: Long) : Boolean = (n & (n - 1)) == 0
+//(3)
+
+def is_pow_of_two(n: Long) : Boolean = (n & (n - 1)) == 0
 
-def is_hard(n: Long) : Boolean = is_pow(3 * n + 1)
+def is_hard(n: Long) : Boolean = is_pow_of_two(3 * n + 1)
 
-def last_odd(n: Long) : Long = 
-  if (is_hard(n)) n else
+def last_odd(n: Long) : Long = if (is_hard(n)) n else
     if (n % 2 == 0) last_odd(n / 2) else 
       last_odd(3 * n + 1)
 
-
-
-//for (i <- 130 to 10000) println(s"$i: ${last_odd(i)}")
-//for (i <- 1 to 100) println(s"$i: ${collatz(i)}")
-
 }
 
 
 
+// This template code is subject to copyright 
+// by King's College London, 2022. Do not 
+// make the template code public in any shape 
+// or form, and do not exchange it with other 
+// students under any circumstance.
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
Binary file cws/main_cw05.pdf has changed
--- a/main_testing3/re.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing3/re.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -1,5 +1,5 @@
 // Main Part 3 about Regular Expression Matching
-//=============================================
+//==============================================
 
 object M3 {
 
@@ -8,13 +8,15 @@
 case object ZERO extends Rexp
 case object ONE extends Rexp
 case class CHAR(c: Char) extends Rexp
-case class ALTs(rs: List[Rexp]) extends Rexp      // alternatives 
-case class SEQ(r1: Rexp, r2: Rexp) extends Rexp   // sequence
-case class STAR(r: Rexp) extends Rexp             // star
+case class ALTs(rs: List[Rexp]) extends Rexp  // alternatives 
+case class SEQs(rs: List[Rexp]) extends Rexp  // sequences
+case class STAR(r: Rexp) extends Rexp         // star
 
 
-//the usual binary choice can be defined in terms of ALTs
+//the usual binary choice and binary sequence can be defined 
+//in terms of ALTs and SEQs
 def ALT(r1: Rexp, r2: Rexp) = ALTs(List(r1, r2))
+def SEQ(r1: Rexp, r2: Rexp) = SEQs(List(r1, r2))
 
 // some convenience for typing in regular expressions
 import scala.language.implicitConversions    
@@ -41,83 +43,78 @@
   def ~ (r: String) = SEQ(s, r)
 }
 
-// (1) 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.
-
+// (1) 
 def nullable (r: Rexp) : Boolean = r match {
   case ZERO => false
   case ONE => true
   case CHAR(_) => false
   case ALTs(rs) => rs.exists(nullable)
-  case SEQ(r1, r2) => nullable(r1) && nullable(r2)
+  case SEQs(rs) => rs.forall(nullable)
   case STAR(_) => true
 }
 
-// (2) 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 {
+// (2) 
+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 ALTs(rs) => ALTs(rs.map(der(c, _)))
-  case SEQ(r1, r2) => 
-    if (nullable(r1)) ALT(SEQ(der(c, r1), r2), der(c, r2))
-    else SEQ(der(c, r1), r2)
+  case SEQs(Nil) => ZERO
+  case SEQs(r1::rs) => 
+    if (nullable(r1)) ALT(SEQs(der(c, r1)::rs), der(c, SEQs(rs)))
+    else SEQs(der(c, r1):: rs)
   case STAR(r1) => SEQ(der(c, r1), STAR(r1))
 }
 
 
-// (3) Implement the flatten function flts. It
-// deletes 0s from a list of regular expressions
-// and also 'spills out', or flattens, nested 
-// ALTernativeS.
+// (3) 
+def denest(rs: List[Rexp]) : List[Rexp] = rs match {
+  case Nil => Nil
+  case ZERO::tl => denest(tl)
+  case ALTs(rs1)::rs2 => rs1 ::: denest(rs2)  
+  case r::rs => r :: denest(rs) 
+}
 
-def flts(rs: List[Rexp]) : List[Rexp] = rs match {
-  case Nil => Nil
-  case ZERO::tl => flts(tl)
-  case ALTs(rs1)::rs2 => rs1 ::: flts(rs2)  
-  case r::rs => r :: flts(rs) 
+// (4)
+def flts(rs: List[Rexp], acc: List[Rexp] = Nil) : List[Rexp] = rs match {
+  case Nil => acc
+  case ZERO::rs => ZERO::Nil
+  case ONE::rs => flts(rs, acc)
+  case SEQs(rs1)::rs => flts(rs, acc ::: rs1)
+  case r::rs => flts(rs, acc :+ r) 
 }
 
-
+// (5)
+def ALTs_smart(rs: List[Rexp]) : Rexp = rs match {
+  case Nil => ZERO
+  case r::Nil => r  
+  case rs => ALTs(rs)
+}
 
-// (4) 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 SEQs_smart(rs: List[Rexp]) : Rexp = rs match {
+  case Nil => ONE
+  case ZERO::nil => ZERO
+  case r::Nil => r
+  case rs => SEQs(rs) 
+}
 
+// (6) 
 
 def simp(r: Rexp) : Rexp = r match {
-  case ALTs(rs) => (flts(rs.map(simp)).distinct) match {
-    case Nil => ZERO
-    case r::Nil => r  
-    case rs => ALTs(rs)
-  }
-  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 ALTs(rs) => 
+    ALTs_smart(denest(rs.map(simp)).distinct)
+  case SEQs(rs) => 
+    SEQs_smart(flts(rs.map(simp)))
   case r => r
 }
 
-simp(ALT(ONE | CHAR('a'), CHAR('a') | ONE))
+//println("Simp tests")
+//println(simp(ALT(ONE | CHAR('a'), CHAR('a') | ONE)))
+//println(simp(((CHAR('a') | ZERO) ~ ONE) | 
+//              (((ONE | CHAR('b')) | CHAR('c')) ~ (CHAR('d') ~ ZERO))))
 
-// (5) 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.
+
+// (7) 
 
 def ders (s: List[Char], r: Rexp) : Rexp = s match {
   case Nil => r
@@ -127,43 +124,40 @@
 // main matcher function
 def matcher(r: Rexp, s: String) = nullable(ders(s.toList, r))
 
-// (6) Complete the size function for regular
-// expressions according to the specification 
-// given in the coursework.
-
+// (8) 
 
 def size(r: Rexp): Int = r match {
   case ZERO => 1
   case ONE => 1
   case CHAR(_) => 1
   case ALTs(rs) => 1 + rs.map(size).sum
-  case SEQ(r1, r2) => 1 + size(r1) + size (r2)
+  case SEQs(rs) => 1 + rs.map(size).sum
   case STAR(r1) => 1 + size(r1)
 }
 
 
 
 // some testing data
-
-//matcher(("a" ~ "b") ~ "c", "abc")  // => true
-//matcher(("a" ~ "b") ~ "c", "ab")   // => false
+/*
+println(matcher(("a" ~ "b") ~ "c", "abc"))  // => true
+println(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'))
 
-//println(matcher(EVIL, "a" * 1000 ++ "b"))   // => true
-//println(matcher(EVIL, "a" * 1000))          // => false
+println(matcher(EVIL, "a" * 1000 ++ "b"))   // => true
+println(matcher(EVIL, "a" * 1000))          // => false
 
 // size without simplifications
-//println(size(der('a', der('a', EVIL))))             // => 28
-//println(size(der('a', der('a', der('a', EVIL)))))   // => 58
+println(size(der('a', der('a', EVIL))))             // => 36
+println(size(der('a', der('a', der('a', EVIL)))))   // => 83
 
 // size with simplification
-//println(simp(der('a', der('a', EVIL))))          
-//println(simp(der('a', der('a', der('a', EVIL)))))
+println(simp(der('a', der('a', EVIL))))          
+println(simp(der('a', der('a', der('a', EVIL)))))
 
-//println(size(simp(der('a', der('a', EVIL)))))           // => 8
-//println(size(simp(der('a', der('a', der('a', EVIL)))))) // => 8
+println(size(simp(der('a', der('a', EVIL)))))           // => 7
+println(size(simp(der('a', der('a', der('a', EVIL)))))) // => 7
 
 // 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
@@ -171,7 +165,7 @@
 //
 // 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.
+// few seconds.
 
 def time_needed[T](i: Int, code: => T) = {
   val start = System.nanoTime()
@@ -180,19 +174,20 @@
   "%.5f".format((end - start)/(i * 1.0e9))
 }
 
-//for (i <- 0 to 5000000 by 500000) {
-//  println(s"$i ${time_needed(2, matcher(EVIL, "a" * i))} secs.") 
-//}
+for (i <- 0 to 5000000 by 500000) {
+  println(s"$i ${time_needed(2, matcher(EVIL, "a" * i))} secs.") 
+}
 
 // another "power" test case 
-//simp(Iterator.iterate(ONE:Rexp)(r => SEQ(r, ONE | ONE)).drop(100).next) == ONE
+println(simp(Iterator.iterate(ONE:Rexp)(r => SEQ(r, ONE | ONE)).drop(100).next()) == ONE)
 
 // the Iterator produces the rexp
 //
 //      SEQ(SEQ(SEQ(..., ONE | ONE) , ONE | ONE), ONE | ONE)
 //
-//    where SEQ is nested 50 times.
- 
+//    where SEQ is nested 100 times.
+*/ 
 
 
 }
+
--- a/main_testing3/re_test.sh	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing3/re_test.sh	Tue Nov 08 00:27:47 2022 +0000
@@ -53,7 +53,7 @@
 
     if (scala_vars re.scala)
     then
-	echo -e "   --> FAIL (make triple-sure your program conforms to the required format)" >> $out 
+	echo -e "  --> FAIL (make triple-sure your program conforms to the required format)" >> $out 
 	tsts=$(( 1 ))
     else
 	echo -e "  --> passed" >> $out
@@ -89,6 +89,8 @@
   echo -e " nullable(ONE ~  ONE) == true" >> $out
   echo -e " nullable(ONE ~ CHAR('a')) == false" >> $out
   echo -e " nullable(STAR(ZERO)) == true" >> $out
+  echo -e " nullable(ALTs(List(ONE, CHAR('a'), ZERO))) == true" >> $out
+  echo -e " nullable(SEQs(List(ONE, ALTs(List(ONE, CHAR('a'), ZERO)), STAR(ZERO)))) == true" >> $out
   
   if (scala_assert "re.scala" "re_test1.scala")
   then
@@ -99,12 +101,12 @@
 fi
 
 
-
 if [ $tsts -eq 0 ]
 then
   echo -e " der('a', ZERO | ONE) == (ZERO | ZERO)" >> $out
   echo -e " der('a', (CHAR('a') | ONE) ~ CHAR('a')) ==" >> $out
   echo -e "                 ALT((ONE | ZERO) ~ CHAR('a'), ONE)" >> $out
+  echo -e " der('a', (CHAR('a') | CHAR('a')) ~ CHAR('a')) == (ONE | ONE) ~ CHAR('a')" >> $out
   echo -e " der('a', STAR(CHAR('a'))) == (ONE ~ STAR(CHAR('a')))" >> $out
   echo -e " der('b', STAR(CHAR('a'))) == (ZERO ~ STAR(CHAR('a')))" >> $out
   
@@ -117,7 +119,6 @@
 fi
 
 
-
 if [ $tsts -eq 0 ]
 then
   echo -e " simp(ZERO | ONE) == ONE" >> $out
@@ -136,6 +137,8 @@
   echo -e " simp(ALT(ONE | ONE, ONE | ONE)) == ONE" >> $out
   echo -e " simp(ALT(ZERO | CHAR('a'), CHAR('a') | ZERO)) == CHAR('a')" >> $out
   echo -e " simp(ALT(ONE | CHAR('a'), CHAR('a') | ONE)) == ALT(ONE, CHAR('a'))" >> $out
+  echo -e " simp(ALTs(Nil)) == ZERO" >> $out
+  echo -e " simp(SEQs(CHAR('a'))) == CHAR('a')" >> $out
   if (scala_assert "re.scala" "re_test3.scala")
   then
     echo -e "  --> success" >> $out
@@ -147,6 +150,55 @@
 
 if [ $tsts -eq 0 ]
 then
+    echo -e " denest(List(ONE, ZERO, ALTs(List(ONE, CHAR('a'))))) == List(ONE, ONE, CHAR('a'))" >> $out
+    echo -e " denest(List(ONE ~ ONE, ZERO, ZERO | ONE)) == List(ONE ~ ONE, ZERO, ONE)" >> $out
+  
+  if (scala_assert "re.scala" "re_test4.scala")
+  then
+    echo -e "  --> success" >> $out
+  else
+    echo -e "  --> \n ONE TEST FAILED\n" >> $out   
+  fi
+fi
+
+
+if [ $tsts -eq 0 ]
+then
+    echo -e " flts(List(CHAR('a'), ZERO, ONE), Nil) == List(ZERO)" >> $out
+    echo -e " flts(List(CHAR('a'), ONE, ONE, CHAR('b')), Nil) == List(CHAR('a'), CHAR('b'))" >> $out
+    echo -e " flts(List(ONE ~ CHAR('a'), CHAR('b') ~ ONE), Nil) == List(ONE, CHAR('a'), CHAR('b'), ONE)" >> $out
+  
+  if (scala_assert "re.scala" "re_test5.scala")
+  then
+    echo -e "  --> success" >> $out
+  else
+    echo -e "  --> \n ONE TEST FAILED\n" >> $out   
+  fi
+fi
+
+
+if [ $tsts -eq 0 ]
+then
+    echo -e " SEQs_smart(Nil) == ONE" >> $out
+    echo -e " SEQs_smart(List(ZERO)) == ZERO" >> $out
+    echo -e " SEQs_smart(List(CHAR('a'))) == CHAR('a')" >> $out
+    echo -e " SEQs_smart(List(ONE ~ ONE)) == ONE ~ ONE" >> $out
+    echo -e " SEQs_smart(List(ONE, ONE)) == SEQs(List(ONE, ONE))" >> $out
+    echo -e " ALTs_smart(Nil) == ZERO" >> $out
+    echo -e " ALTs_smart(List(ONE ~ ONE)) == ONE ~ ONE)" >> $out
+    echo -e " ALTs_smart(List(ZERO, ZERO)) == ALTs(List(ZERO, ZERO))" >> $out
+  
+  if (scala_assert "re.scala" "re_test6.scala")
+  then
+    echo -e "  --> success" >> $out
+  else
+    echo -e "  --> \n ONE TEST FAILED\n" >> $out   
+  fi
+fi
+
+
+if [ $tsts -eq 0 ]
+then
   echo -e " val EVIL = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))" >> $out
   echo -e " ders(\"aaaaa\".toList, EVIL) == SEQ(SEQ(STAR(CHAR('a')),STAR(STAR(CHAR('a')))),CHAR('b'))" >> $out
   echo -e " ders(List('b'), EVIL) == ONE" >> $out
@@ -161,7 +213,7 @@
   echo -e " matcher(ONE | CHAR('a'), \"\") == true" >> $out
   echo -e " matcher(ONE | CHAR('a'), \"a\") == true" >> $out
   
-  if (scala_assert "re.scala" "re_test4.scala")
+  if (scala_assert "re.scala" "re_test7.scala")
   then
     echo -e "  --> success" >> $out
   else
@@ -173,11 +225,12 @@
 if [ $tsts -eq 0 ]
 then
   echo -e " val EVIL = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))" >> $out  
-  echo -e " size(der('a', der('a', EVIL))) == 28" >> $out
-  echo -e " size(der('a', der('a', der('a', EVIL)))) == 58" >> $out
-  echo -e " size(ders(\"aaaaaa\".toList, EVIL)) == 8" >> $out
+  echo -e " size(der('a', der('a', EVIL))) == 36" >> $out
+  echo -e " size(der('a', der('a', der('a', EVIL)))) == 83" >> $out
+  echo -e " size(ders(\"aaaaaa\".toList, EVIL)) == 7" >> $out
+  echo -e " size(ders((\"a\" * 50).toList, EVIL)) == 7" >> $out
   
-  if (scala_assert "re.scala" "re_test5.scala")
+  if (scala_assert "re.scala" "re_test8.scala")
   then
     echo -e "  --> success" >> $out
   else
--- a/main_testing3/re_test1.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing3/re_test1.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -8,4 +8,6 @@
 assert(nullable(ONE ~  ONE) == true)
 assert(nullable(ONE ~ CHAR('a')) == false)
 assert(nullable(STAR(ZERO)) == true)
+assert(nullable(ALTs(List(ONE, CHAR('a'), ZERO))) == true)
+assert(nullable(SEQs(List(ONE, ALTs(List(ONE, CHAR('a'), ZERO)), STAR(ZERO)))) == true)
 
--- a/main_testing3/re_test2.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing3/re_test2.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -1,12 +1,12 @@
 import M3._
 
-assert(der('a', ZERO | ONE) == (ZERO | ZERO))
-assert(der('a', (CHAR('a') | ONE) ~ CHAR('a')) == ALT((ONE | ZERO) ~ CHAR('a'), ONE))
+assert(der('a', ZERO | ONE) == ALT(ZERO, ZERO))
+assert(der('a', (CHAR('a') | ONE) ~ CHAR('a')) == ALTs(List(SEQ(ALT(ONE, ZERO), CHAR('a')), SEQs(List(ONE)))))
 assert(der('a', (CHAR('a') | CHAR('a')) ~ CHAR('a')) == (ONE | ONE) ~ CHAR('a'))
 assert(der('a', STAR(CHAR('a'))) == (ONE ~ STAR(CHAR('a'))))
 assert(der('b', STAR(CHAR('a'))) == (ZERO ~ STAR(CHAR('a'))))
 
-
+/*
 val r0_urban = "a" ~ "b" ~ "c"
 assert(der('a', r0_urban) == (ONE ~ "b") ~ "c")
 assert(der('b', r0_urban) == (ZERO ~ "b") ~ "c")
@@ -23,3 +23,4 @@
 assert(der('a', r2_urban) == ((((ZERO ~ "b") | ZERO) ~ "c") | ZERO))
 assert(der('b', r2_urban) == ((((ZERO ~ "b") | ZERO) ~ "c") | ZERO))
 assert(der('c', r2_urban) == ((((ZERO ~ "b") | ZERO) ~ "c") | ONE))
+*/
--- a/main_testing3/re_test3.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing3/re_test3.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -17,5 +17,6 @@
 assert(simp(ALT(ONE | ONE, ONE | ONE)) == ONE)
 assert(simp(ALT(ZERO | CHAR('a'), CHAR('a') | ZERO)) == CHAR('a'))
 assert(simp(ALT(ONE | CHAR('a'), CHAR('a') | ONE)) == ALT(ONE, CHAR('a')))
+assert(simp(ALTs(Nil)) == ZERO)
+assert(simp(SEQs(List(CHAR('a')))) == CHAR('a'))
 
-
--- a/main_testing3/re_test4.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing3/re_test4.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -1,19 +1,5 @@
 import M3._
 
-val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
-
-assert(ders(("a" * 5).toList, EVIL_urban) == SEQ(SEQ(STAR(CHAR('a')),STAR(STAR(CHAR('a')))),CHAR('b')))
-assert(ders(List('b'), EVIL_urban) == ONE)
-assert(ders(List('b','b'), EVIL_urban) == ZERO)
-assert(matcher(EVIL_urban, "a" * 5 ++ "b") == true)
-assert(matcher(EVIL_urban, "a" * 50 ++ "b") == true)
-assert(matcher(EVIL_urban, "a" * 50) == false)
-assert(matcher(EVIL_urban, "b") == true)
-assert(matcher(EVIL_urban, "bb") == false)
-assert(matcher("abc", "abc") == true)
-assert(matcher("abc", "ab") == false)
-assert(matcher(("ab" | "a") ~ (ONE | "bc"), "abc") == true)
-assert(matcher(ONE, "") == true)
-assert(matcher(ZERO, "") == false)
-assert(matcher(ONE | CHAR('a'), "") == true)
-assert(matcher(ONE | CHAR('a'), "a") == true)
+assert(denest(List(ONE, ZERO, ALTs(List(ONE, CHAR('a'))))) 
+   == List(ONE, ONE, CHAR('a')))
+assert(denest(List(ONE ~ ONE, ZERO, ZERO | ONE)) == List(ONE ~ ONE, ZERO, ONE))
--- a/main_testing3/re_test5.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing3/re_test5.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -1,8 +1,6 @@
-import M3._ 
-val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
+import M3._
 
-assert(size(der('a', der('a', EVIL_urban))) == 28)
-assert(size(der('a', der('a', der('a', EVIL_urban)))) == 58)
+assert(flts(List(CHAR('a'), ZERO, ONE), Nil) == List(ZERO))
+assert(flts(List(CHAR('a'), ONE, ONE, CHAR('b')), Nil) == List(CHAR('a'), CHAR('b')))
+assert(flts(List(ONE ~ CHAR('a'), CHAR('b') ~ ONE), Nil) == List(ONE, CHAR('a'), CHAR('b'), ONE))
 
-assert(size(ders("aaaaaa".toList, EVIL_urban)) == 8)
-assert(size(ders(("a" * 50).toList, EVIL_urban)) == 8)
--- a/main_testing3/re_test6.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing3/re_test6.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -1,9 +1,10 @@
 import M3._
 
-val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
-
-
-assert(simp(Iterator.iterate(ONE:Rexp)(r => SEQ(r, ONE | ONE)).drop(50).next) == ONE)
-assert(simp(Iterator.iterate(ONE:Rexp)(r => ALT(r, r)).drop(20).next) == ONE)
-assert(matcher(EVIL_urban, "a" * 1000000) == false)
-assert(matcher(EVIL_urban, "a" * 1000000 ++ "b") == true)
+assert(SEQs_smart(Nil) == ONE)
+assert(SEQs_smart(List(ZERO)) == ZERO)
+assert(SEQs_smart(List(CHAR('a'))) == CHAR('a'))
+assert(SEQs_smart(List(ONE ~ ONE)) == ONE ~ ONE)
+assert(SEQs_smart(List(ONE, ONE)) == SEQs(List(ONE, ONE)))
+assert(ALTs_smart(Nil) == ZERO)
+assert(ALTs_smart(List(ONE ~ ONE)) == ONE ~ ONE)
+assert(ALTs_smart(List(ZERO, ZERO)) == ALTs(List(ZERO, ZERO)))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_testing3/re_test7.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -0,0 +1,19 @@
+import M3._
+
+val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
+
+assert(ders(("a" * 5).toList, EVIL_urban) == SEQs(List(STAR(CHAR('a')), STAR(STAR(CHAR('a'))), CHAR('b'))))
+assert(ders(List('b'), EVIL_urban) == ONE)
+assert(ders(List('b','b'), EVIL_urban) == ZERO)
+assert(matcher(EVIL_urban, "a" * 5 ++ "b") == true)
+assert(matcher(EVIL_urban, "a" * 50 ++ "b") == true)
+assert(matcher(EVIL_urban, "a" * 50) == false)
+assert(matcher(EVIL_urban, "b") == true)
+assert(matcher(EVIL_urban, "bb") == false)
+assert(matcher("abc", "abc") == true)
+assert(matcher("abc", "ab") == false)
+assert(matcher(("ab" | "a") ~ (ONE | "bc"), "abc") == true)
+assert(matcher(ONE, "") == true)
+assert(matcher(ZERO, "") == false)
+assert(matcher(ONE | CHAR('a'), "") == true)
+assert(matcher(ONE | CHAR('a'), "a") == true)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_testing3/re_test8.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -0,0 +1,8 @@
+import M3._ 
+val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
+
+assert(size(der('a', der('a', EVIL_urban))) == 36)
+assert(size(der('a', der('a', der('a', EVIL_urban)))) == 83)
+
+assert(size(ders("aaaaaa".toList, EVIL_urban)) == 7)
+assert(size(ders(("a" * 50).toList, EVIL_urban)) == 7)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_testing3/re_test9.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -0,0 +1,9 @@
+import M3._
+
+val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
+
+
+assert(simp(Iterator.iterate(ONE:Rexp)(r => SEQ(r, ONE | ONE)).drop(50).next) == ONE)
+assert(simp(Iterator.iterate(ONE:Rexp)(r => ALT(r, r)).drop(20).next) == ONE)
+assert(matcher(EVIL_urban, "a" * 1000000) == false)
+assert(matcher(EVIL_urban, "a" * 1000000 ++ "b") == true)
--- a/main_testing4/knight1.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing4/knight1.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -1,119 +1,13 @@
-// Main Part 4 about finding Knight's tours
-//==========================================
-import scala.annotation.tailrec
-
-
-object M4a {
+// Part 1 about finding and counting Knight's tours
+//==================================================
 
-// If you need any auxiliary functions, feel free to 
-// implement them, but do not make any changes to the
-// templates below. Also have a look whether the functions
-// at the end of the file are of any help.
-
-
+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
 
-//(1) Complete the function that tests whether the position x
-//    is inside the board and not yet element in the path.
 
-def is_legal(dim: Int, path: Path, x: Pos) : Boolean = {
-  (x._1 < dim) && (x._2 < dim) && (!path.contains(x))
-}
-
-
-
-//(2) Complete the function that calculates for a position x
-//    all legal onward moves that are not already in the path. 
-//    The moves should be ordered in a "clockwise" manner.
- 
-def legal_moves(dim: Int, path: Path, x: Pos) : List[Pos] = {
-    val movesets = List(
-    (x._1 + 1, x._2 + 2),
-    (x._1 + 2, x._2 + 1),
-    (x._1 + 2, x._2 - 1),
-    (x._1 + 1, x._2 - 2),
-    (x._1 - 1, x._2 - 2),
-    (x._1 - 2, x._2 - 1),
-    (x._1 - 2, x._2 + 1),
-    (x._1 - 1, x._2 + 2)
-  )
-  movesets.filter(is_legal(dim, path, _))
-}
-
-
-//some 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)))
-
-
-//(3) Complete the two recursive functions below. 
-//    They exhaustively search for knight's tours starting from the 
-//    given path. The first function counts all possible tours, 
-//    and the second collects all tours in a list of paths.
-
-def count_tours(dim: Int, path: Path) : Int = {
-  if (dim <= 4) 0 else {
-    if (path.length >= (dim * dim)) 1 else {
-      val movesets = legal_moves(dim, path, path.head)
-      (for (move <- movesets) yield count_tours(dim, move :: path)).sum
-    }
-  }
-}
-
-def enum_tours(dim: Int, path: Path) : List[Path] = {
-  if (dim <= 4) Nil else {
-    if (path.length >= (dim * dim)) List(path) else {
-      val movesets = legal_moves(dim, path, path.head)
-      (for (move <- movesets) yield enum_tours(dim, move :: path)).flatten
-    }
-  }
-}
-
-
-//(4) Implement a first-function that finds the first 
-//    element, say x, in the list xs where f is not None. 
-//    In that case Return f(x), otherwise None. If possible,
-//    calculate f(x) only once.
-
-@tailrec
-def first(xs: List[Pos], f: Pos => Option[Path]) : Option[Path] = {
-  xs match {
-    case Nil => None
-    case head :: rest => {
-      val result = f(head)
-      if (result.isEmpty) first(rest, f) else result
-    }
-  }
-}
-
-
-// testcases
-//
-//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)   // Some(List((4,0)))
-//first(List((1, 0),(2, 0),(3, 0)), foo)          // None
-
-
-//(5) Implement a function that uses the first-function from (4) for
-//    trying out onward moves, and searches recursively for a
-//    knight tour on a dim * dim-board.
-
-def first_tour(dim: Int, path: Path) : Option[Path] = ???
- 
-
-
-/* Helper functions
-
-
-// for measuring time
+// for measuring time in the JAR
 def time_needed[T](code: => T) : T = {
   val start = System.nanoTime()
   val result = code
@@ -122,14 +16,6 @@
   result
 }
 
-// can be called for example with
-//
-//     time_needed(count_tours(dim, List((0, 0))))
-//
-// in order to print out the time that is needed for 
-// running count_tours
-
-
 // for printing a board
 def print_board(dim: Int, path: Path): Unit = {
   println()
@@ -141,7 +27,145 @@
   } 
 }
 
+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(0,first_tour(8, List((0, 0))).get)
+//??val ts1 = time_needed(0,first_tour(8, List((1, 1))).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_testing4/knight3.scala	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing4/knight3.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -64,4 +64,10 @@
 // testcases
 //print_board(70, tour_on_mega_board(70, List((0, 0))).get)
 
+
+
 }
+
+
+//val dim = 30 //75
+//M4c.print_board(dim, M4c.tour_on_mega_board(dim, List((0, 0))).get)
--- a/main_testing4/knight_test.sh	Thu Nov 03 11:30:09 2022 +0000
+++ b/main_testing4/knight_test.sh	Tue Nov 08 00:27:47 2022 +0000
@@ -72,65 +72,65 @@
 
 ### knight1 test
 
-#if [ $tsts1 -eq 0 ]
-#then
-#    #echo -e "For testing needs to take 10 seconds or less to execute: " >> $out
-#    echo -e " is_legal(8, Nil, (3, 4)) == true " >> $out
-#    echo -e " is_legal(8, List((4, 1), (1, 0)), (4, 1)) == false " >> $out
-#    echo -e " is_legal(2, Nil, (0, 0)) == true" >> $out                          
-#
-#    if (scala_assert "knight1.scala" "knight_test1.scala")
-#    then
-#        echo -e "  --> success" >> $out
-#    else
-#        echo -e "  --> \n ONE TEST FAILED\n" >> $out
-#    fi
-#fi
+if [ $tsts1 -eq 0 ]
+then
+    #echo -e "For testing needs to take 10 seconds or less to execute: " >> $out
+    echo -e " is_legal(8, Nil, (3, 4)) == true " >> $out
+    echo -e " is_legal(8, List((4, 1), (1, 0)), (4, 1)) == false " >> $out
+    echo -e " is_legal(2, Nil, (0, 0)) == true" >> $out                          
+
+    if (scala_assert "knight1.scala" "knight_test1.scala")
+    then
+        echo -e "  --> success" >> $out
+    else
+        echo -e "  --> \n ONE TEST FAILED\n" >> $out
+    fi
+fi
 
 ### knight2 test
 
-#if [ $tsts1 -eq 0 ]
-#then
-#  #echo -e "For testing needs to take 10 seconds or less to execute: " >> $out
-#  echo -e " legal_moves(8, Nil, (2,2)) == List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4))" >> $out
-#  echo -e " legal_moves(8, Nil, (7,7)) == List((6,5), (5,6))" >> $out
-#  echo -e " legal_moves(8, List((4,1), (1,0)), (2,2)) == List((3,4), (4,3), (3,0), (0,1), (0,3), (1,4))" >> $out
-#  echo -e " legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6))" >> $out
-#  echo -e " legal_moves(1, Nil, (0,0)) == Nil" >> $out
-#  echo -e " legal_moves(2, Nil, (0,0)) == Nil" >> $out
-#  echo -e " legal_moves(3, Nil, (0,0)) == List((1,2), (2,1))" >> $out
-#  
-#  if (scala_assert "knight1.scala" "knight_test2.scala")
-#  then
-#    echo -e "  --> success" >> $out
-#  else
-#    echo -e "  --> \n ONE TEST FAILED\n" >> $out
-#  fi
-#fi
+if [ $tsts1 -eq 0 ]
+then
+  #echo -e "For testing needs to take 10 seconds or less to execute: " >> $out
+  echo -e " legal_moves(8, Nil, (2,2)) == List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4))" >> $out
+  echo -e " legal_moves(8, Nil, (7,7)) == List((6,5), (5,6))" >> $out
+  echo -e " legal_moves(8, List((4,1), (1,0)), (2,2)) == List((3,4), (4,3), (3,0), (0,1), (0,3), (1,4))" >> $out
+  echo -e " legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6))" >> $out
+  echo -e " legal_moves(1, Nil, (0,0)) == Nil" >> $out
+  echo -e " legal_moves(2, Nil, (0,0)) == Nil" >> $out
+  echo -e " legal_moves(3, Nil, (0,0)) == List((1,2), (2,1))" >> $out
+  
+  if (scala_assert "knight1.scala" "knight_test2.scala")
+  then
+    echo -e "  --> success" >> $out
+  else
+    echo -e "  --> \n ONE TEST FAILED\n" >> $out
+  fi
+fi
 
 
 ### knight3 test
 
-#if [ $tsts1 -eq 0 ]
-#then
-#  #echo -e "For testing needs to take 10 seconds or less to execute: " >> $out
-#  echo -e " count_tours from every position on the board" >> $out
-#  echo -e " dim = 1: 1" >> $out
-#  echo -e "       2: 0,0,0,0" >>  $out
-#  echo -e "       3: 0,0,0,0,0,0,0,0,0" >>  $out
-#  echo -e "       4: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" >> $out
-#  #echo -e "       5: 304,0,56,0,304,0,56,0,56,0,56,0,64,0,56,0,56,0,56,0,304,0,56,0,304" >> $out
-#  echo -e " enum_tours(5, List((0,0)) ) == 304 and all correct?" >> $out
-#  echo -e " enum_tours(5, List((0,1)) ) == 0" >> $out
-#  echo -e " enum_tours(5, List((0,2)) ) == 56 and all correct?" >> $out
-#  
-#  if (scala_assert "knight1.scala" "knight_test3.scala") 
-#  then
-#    echo -e "  --> success" >> $out
-#  else
-#    echo -e "  --> \n ONE TEST FAILED\n" >> $out
-#  fi
-#fi
+if [ $tsts1 -eq 0 ]
+then
+  #echo -e "For testing needs to take 10 seconds or less to execute: " >> $out
+  echo -e " count_tours from every position on the board" >> $out
+  echo -e " dim = 1: 1" >> $out
+  echo -e "       2: 0,0,0,0" >>  $out
+  echo -e "       3: 0,0,0,0,0,0,0,0,0" >>  $out
+  echo -e "       4: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" >> $out
+  #echo -e "       5: 304,0,56,0,304,0,56,0,56,0,56,0,64,0,56,0,56,0,56,0,304,0,56,0,304" >> $out
+  echo -e " enum_tours(5, List((0,0)) ) == 304 and all correct?" >> $out
+  echo -e " enum_tours(5, List((0,1)) ) == 0" >> $out
+  echo -e " enum_tours(5, List((0,2)) ) == 56 and all correct?" >> $out
+  
+  if (scala_assert "knight1.scala" "knight_test3.scala")
+  then
+    echo -e "  --> success" >> $out
+  else
+    echo -e "  --> \n ONE TEST FAILED\n" >> $out
+  fi
+fi
 
 ### knight4 test
 
@@ -278,7 +278,7 @@
 
     if (scala_vars knight3.scala)
     then
-	echo "  --> Fail (make triple-sure your program conforms to the required format)xsxs" >> $out
+	echo "  --> Fail (make triple-sure your program conforms to the required format)" >> $out
 	tsts3=$(( 1 ))
     else
 	echo "  --> passed" >> $out
@@ -300,3 +300,50 @@
   fi
 fi
 
+
+echo -e "" >> $out
+echo -e "" >> $out
+
+
+
+# compilation test
+   
+echo "knight4.scala runs?" >> $out
+
+if (scala_compile knight4.scala)
+then
+    echo "  --> passed" >> $out
+    tsts4=$(( 0 ))
+else
+    echo -e "  --> SCALA DID NOT RUN KNIGHT4.SCALA\n" >> $out  
+    tsts4=$(( 1 )) 
+fi
+
+# knights4: purity test
+#
+if  [ $tsts4 -eq 0 ]
+then 
+    echo -e "knight4.scala does not contain vars, returns, Arrays, ListBuffers etc?" >> $out
+
+    if (scala_vars knight4.scala)
+    then
+	echo "  --> Fail (make triple-sure your program conforms to the required format)" >> $out
+	tsts4=$(( 1 ))
+    else
+	echo "  --> passed" >> $out
+	tsts4=$(( 0 )) 
+    fi
+fi
+
+if [ $tsts4 -eq 0 ]
+then
+  #echo -e "For testing needs to take 10 seconds or less to execute: " >> $out  
+  echo -e " " >> $out
+  
+  if (scala_assert "knight4.scala" "knight_test10.scala")
+  then
+      echo -e "  --> success" >> $out
+  else
+      echo -e "  --> \n ONE TEST FAILED\n" >> $out 
+  fi
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main_testing4/knight_test10.scala	Tue Nov 08 00:27:47 2022 +0000
@@ -0,0 +1,29 @@
+import M4d._
+
+//type Pos = (Int, Int)
+//type Path = List[Pos]
+
+def add_pair_urban(x: Pos)(y: Pos): Pos = 
+  (x._1 + y._1, x._2 + y._2)
+
+def is_legal_urban(dim: Int, path: Path)(x: Pos): Boolean = 
+  0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
+
+def moves_urban(x: Pos): List[Pos] = 
+  List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
+       (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair_urban(x))
+
+def legal_moves_urban(dim: Int, path: Path, x: Pos): List[Pos] = 
+  moves_urban(x).filter(is_legal_urban(dim, path))
+
+def correct_urban(dim: Int)(p: Path): Boolean = p match {
+  case Nil => true
+  case x::Nil => true
+  case x::y::p => 
+    if (legal_moves_urban(dim, p, y).contains(x)) correct_urban(dim)(y::p) else false
+}
+
+
+val ts70 = tour_on_mega_board(70, List((0,0))).get
+assert(correct_urban(70)(ts70) == true)
+