updated
authorChristian Urban <christian.urban@kcl.ac.uk>
Mon, 08 Nov 2021 01:03:09 +0000
changeset 401 9471c3b7ea02
parent 400 e48ea8300b2d
child 402 de59aa20a1dc
updated
core_solution1/collatz.scala
core_solution2/docdiff.scala
core_solution3/postfix.jar
core_solution3/postfix.scala
core_solution3/postfix2.jar
core_solution3/postfix2.scala
core_templates2/docdiff.jar
core_templates3/postfix.jar
core_templates3/postfix2.jar
core_testing1/collatz.scala
core_testing2/docdiff.scala
core_testing2/docdiff_test.sh
core_testing2/docdiff_test1.scala
core_testing2/docdiff_test2.scala
core_testing2/docdiff_test3.scala
core_testing2/docdiff_test4.scala
core_testing3/postfix.scala
core_testing3/postfix2.scala
core_testing3/postfix_test.sh
core_testing3/postfix_test7.scala
core_testing3/postfix_test8.scala
core_testing3/postfix_test9.scala
pre_solution3/postfix.jar
pre_solution3/postfix.scala
pre_solution3/postfix2.jar
pre_solution3/postfix2.scala
pre_testing2/docdiff.scala
pre_testing2/docdiff_test.sh
pre_testing2/docdiff_test1.scala
pre_testing2/docdiff_test2.scala
pre_testing2/docdiff_test3.scala
pre_testing2/docdiff_test4.scala
pre_testing3/postfix.scala
pre_testing3/postfix2.scala
pre_testing3/postfix_test.sh
pre_testing3/postfix_test7.scala
pre_testing3/postfix_test8.scala
pre_testing3/postfix_test9.scala
--- a/core_solution1/collatz.scala	Mon Nov 08 00:17:50 2021 +0000
+++ b/core_solution1/collatz.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -18,8 +18,7 @@
 }
 
 //collatz_max(1000000)
-//collatz_max(10000000)
-//collatz_max(100000000)
+
 
 /* some test cases
 val bnds = List(10, 100, 1000, 10000, 100000, 1000000)
--- a/core_solution2/docdiff.scala	Mon Nov 08 00:17:50 2021 +0000
+++ b/core_solution2/docdiff.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -2,7 +2,7 @@
 //========================================
 
 
-object CW7a { 
+object C2 { 
 
 //(1) Complete the clean function below. It should find
 //    all words in a string using the regular expression
Binary file core_solution3/postfix.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_solution3/postfix.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,103 @@
+// Shunting Yard Algorithm
+// by Edsger Dijkstra
+// ========================
+
+object C3a {
+
+type Toks = List[String]
+
+// the operations in the simple version
+val ops = List("+", "-", "*", "/")
+
+// the precedences of the operators
+val precs = Map("+" -> 1,
+		"-" -> 1,
+		"*" -> 2,
+		"/" -> 2)
+
+// helper function for splitting strings into tokens
+def split(s: String) : Toks = s.split(" ").toList
+
+// (6) Implement below the shunting yard algorithm. The most
+// convenient way to this in Scala is to implement a recursive 
+// function and to heavily use pattern matching. The function syard 
+// takes some input tokens as first argument. The second and third 
+// arguments represent the stack and the output of the shunting yard 
+// algorithm.
+//
+// In the marking, you can assume the function is called only with 
+// an empty stack and an empty output list. You can also assume the
+// input os  only properly formatted (infix) arithmetic expressions
+// (all parentheses will be well-nested, the input only contains 
+// operators and numbers).
+
+// You can implement any additional helper function you need. I found 
+// it helpful to implement two auxiliary functions for the pattern matching:  
+// 
+ 
+def is_op(op: String) : Boolean = ops.contains(op)
+
+def prec(op1: String, op2: String) : Boolean = precs(op1) <= precs(op2)
+
+
+def syard(toks: Toks, st: Toks = Nil, out: Toks = Nil) : Toks = (toks, st, out) match {
+  case (Nil, _, _) => out.reverse ::: st
+  case (num::in, st, out) if (num.forall(_.isDigit)) => 
+    syard(in, st, num :: out)
+  case (op1::in, op2::st, out)  if (is_op(op1) && is_op(op2) && prec(op1, op2)) =>
+    syard(op1::in, st, op2 :: out) 
+  case (op1::in, st, out) if (is_op(op1)) => syard(in, op1::st, out)
+  case ("("::in, st, out) => syard(in, "("::st, out)
+  case (")"::in, op2::st, out) =>
+    if (op2 == "(") syard(in, st, out) else syard(")"::in, st, op2 :: out)
+  case (in, st, out) => {
+    println(s"in: ${in}   st: ${st}   out: ${out.reverse}")
+    Nil
+  }  
+} 
+
+
+// test cases
+//syard(split("3 + 4 * ( 2 - 1 )"))  // 3 4 2 1 - * +
+//syard(split("10 + 12 * 33"))       // 10 12 33 * +
+//syard(split("( 5 + 7 ) * 2"))      // 5 7 + 2 *
+//syard(split("5 + 7 / 2"))          // 5 7 2 / +
+//syard(split("5 * 7 / 2"))          // 5 7 * 2 /
+//syard(split("9 + 24 / ( 7 - 3 )")) // 9 24 7 3 - / +
+
+//syard(split("3 + 4 + 5"))           // 3 4 + 5 +
+//syard(split("( ( 3 + 4 ) + 5 )"))    // 3 4 + 5 +
+//syard(split("( 3 + ( 4 + 5 ) )"))    // 3 4 5 + +
+//syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) // 3 4 5 + +
+
+// (7) Implement a compute function that evaluates an input list
+// in postfix notation. This function takes a list of tokens
+// and a stack as argumenta. The function should produce the 
+// result as an integer using the stack. You can assume 
+// this function will be only called with proper postfix 
+// expressions.    
+
+def op_comp(s: String, n1: Int, n2: Int) = s match {
+  case "+" => n2 + n1
+  case "-" => n2 - n1
+  case "*" => n2 * n1
+  case "/" => n2 / n1
+} 
+
+def compute(toks: Toks, st: List[Int] = Nil) : Int = (toks, st) match {
+  case (Nil, st) => st.head
+  case (op::in, n1::n2::st) if (is_op(op)) => compute(in, op_comp(op, n1, n2)::st)
+  case (num::in, st) => compute(in, num.toInt::st)  
+}
+
+// test cases
+// compute(syard(split("3 + 4 * ( 2 - 1 )")))  // 7
+// compute(syard(split("10 + 12 * 33")))       // 406
+// compute(syard(split("( 5 + 7 ) * 2")))      // 24
+// compute(syard(split("5 + 7 / 2")))          // 8
+// compute(syard(split("5 * 7 / 2")))          // 17
+// compute(syard(split("9 + 24 / ( 7 - 3 )"))) // 15
+
+}
+
+
Binary file core_solution3/postfix2.jar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_solution3/postfix2.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,100 @@
+// Shunting Yard Algorithm 
+// including Associativity for Operators 
+// =====================================
+
+object C3b {
+
+// type of tokens
+type Toks = List[String]
+
+// helper function for splitting strings into tokens
+def split(s: String) : Toks = s.split(" ").toList
+
+// left- and right-associativity
+abstract class Assoc
+case object LA extends Assoc
+case object RA extends Assoc
+
+// power is right-associative,
+// everything else is left-associative
+def assoc(s: String) : Assoc = s match {
+  case "^" => RA
+  case _ => LA
+}
+
+// the precedences of the operators
+val precs = Map("+" -> 1,
+  		 "-" -> 1,
+		 "*" -> 2,
+		 "/" -> 2,
+                 "^" -> 4)
+
+// the operations in the basic version of the algorithm
+val ops = List("+", "-", "*", "/", "^")
+
+// (8) Implement the extended version of the shunting yard algorithm.
+// This version should properly account for the fact that the power 
+// operation is right-associative. Apart from the extension to include
+// the power operation, you can make the same assumptions as in 
+// basic version.
+
+def is_op(op: String) : Boolean = ops.contains(op)
+
+def prec(op1: String, op2: String) : Boolean = assoc(op1) match {
+  case LA => precs(op1) <= precs(op2)
+  case RA => precs(op1) < precs(op2)
+}
+
+def syard(toks: Toks, st: Toks = Nil, out: Toks = Nil) : Toks = (toks, st, out) match {
+  case (Nil, _, _) => out.reverse ::: st
+  case (num::in, st, out) if (num.forall(_.isDigit)) => 
+    syard(in, st, num :: out)
+  case (op1::in, op2::st, out) if (is_op(op1) && is_op(op2) && prec(op1, op2)) =>
+    syard(op1::in, st, op2 :: out) 
+  case (op1::in, st, out) if (is_op(op1)) => syard(in, op1::st, out)
+  case ("("::in, st, out) => syard(in, "("::st, out)
+  case (")"::in, op2::st, out) =>
+    if (op2 == "(") syard(in, st, out) else syard(")"::in, st, op2 :: out)
+  case (in, st, out) => {
+    println(s"in: ${in}   st: ${st}   out: ${out.reverse}")
+    Nil
+  }  
+} 
+
+def op_comp(s: String, n1: Int, n2: Int) = s match {
+  case "+" => n2 + n1
+  case "-" => n2 - n1
+  case "*" => n2 * n1
+  case "/" => n2 / n1
+  case "^" => BigInt(n2).pow(n1).toInt
+} 
+
+def compute(toks: Toks, st: List[Int] = Nil) : Int = (toks, st) match {
+  case (Nil, st) => st.head
+  case (op::in, n1::n2::st) if (is_op(op)) => compute(in, op_comp(op, n1, n2)::st)
+  case (num::in, st) => compute(in, num.toInt::st)  
+}
+
+
+
+
+//compute(syard(split("3 + 4 * ( 2 - 1 )")))   // 7
+//compute(syard(split("10 + 12 * 33")))       // 406
+//compute(syard(split("( 5 + 7 ) * 2")))      // 24
+//compute(syard(split("5 + 7 / 2")))          // 8
+//compute(syard(split("5 * 7 / 2")))          // 17
+//compute(syard(split("9 + 24 / ( 7 - 3 )"))) // 15
+
+//compute(syard(split("4 ^ 3 ^ 2")))      // 262144
+//compute(syard(split("4 ^ ( 3 ^ 2 )")))  // 262144
+//compute(syard(split("( 4 ^ 3 ) ^ 2")))  // 4096
+//compute(syard(split("( 3 + 1 ) ^ 2 ^ 3")))   // 65536
+
+//syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3"))  // 3 4 8 * 5 1 - 2 3 ^ ^ / +
+//compute(syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3"))) // 3
+
+//compute(syard(split("( 3 + 1 ) ^ 2 ^ 3")))   // 65536
+
+
+
+}
Binary file core_templates2/docdiff.jar has changed
Binary file core_templates3/postfix.jar has changed
Binary file core_templates3/postfix2.jar has changed
--- a/core_testing1/collatz.scala	Mon Nov 08 00:17:50 2021 +0000
+++ b/core_testing1/collatz.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -1,4 +1,4 @@
-// Basic Part about the 3n+1 conjecture
+// Core Part 1 about the 3n+1 conjecture
 //==================================
 
 // generate jar with
@@ -18,8 +18,7 @@
 }
 
 //collatz_max(1000000)
-//collatz_max(10000000)
-//collatz_max(100000000)
+
 
 /* some test cases
 val bnds = List(10, 100, 1000, 10000, 100000, 1000000)
@@ -31,6 +30,7 @@
 
 */
 
+
 def is_pow(n: Long) : Boolean = (n & (n - 1)) == 0
 
 def is_hard(n: Long) : Boolean = is_pow(3 * n + 1)
@@ -41,6 +41,7 @@
       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)}")
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing2/docdiff.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,117 @@
+// Preliminary Part about Code Similarity
+//========================================
+
+
+object C2 { 
+
+//(1) Complete the clean function below. It should find
+//    all words in a string using the regular expression
+//    \w+  and the library function 
+//
+//         some_regex.findAllIn(some_string)
+//
+//    The words should be Returned as a list of strings.
+
+def clean(s: String) : List[String] = 
+  ("""\w+""".r).findAllIn(s).toList
+
+
+//(2) The function occurrences calculates the number of times  
+//    strings occur in a list of strings. These occurrences should 
+//    be calculated as a Map from strings to integers.
+
+def occurrences(xs: List[String]): Map[String, Int] =
+  (for (x <- xs.distinct) yield (x, xs.count(_ == x))).toMap
+
+//(3) This functions calculates the dot-product of two documents
+//    (list of strings). For this it calculates the occurrence
+//    maps from (2) and then multiplies the corresponding occurrences. 
+//    If a string does not occur in a document, the product is zero.
+//    The function finally sums up all products. 
+
+def prod(lst1: List[String], lst2: List[String]) : Int = {
+    val words = (lst1 ::: lst2).distinct
+    val occs1 = occurrences(lst1)
+    val occs2 = occurrences(lst2)
+    words.map{ w => occs1.getOrElse(w, 0) * occs2.getOrElse(w, 0) }.sum
+}          
+
+//(4) Complete the functions overlap and similarity. The overlap of
+//    two documents is calculated by the formula given in the assignment
+//    description. The similarity of two strings is given by the overlap
+//    of the cleaned (see (1)) strings.  
+
+def overlap(lst1: List[String], lst2: List[String]) : Double = {
+    val m1 = prod(lst1, lst1)
+    val m2 = prod(lst2, lst2) 
+    prod(lst1, lst2).toDouble / (List(m1, m2).max)
+}
+
+def similarity(s1: String, s2: String) : Double =
+  overlap(clean(s1), clean(s2))
+
+
+/*
+
+
+val list1 = List("a", "b", "b", "c", "d") 
+val list2 = List("d", "b", "d", "b", "d")
+
+occurrences(List("a", "b", "b", "c", "d"))   // Map(a -> 1, b -> 2, c -> 1, d -> 1)
+occurrences(List("d", "b", "d", "b", "d"))   // Map(d -> 3, b -> 2)
+
+prod(list1,list2) // 7 
+
+overlap(list1, list2)   // 0.5384615384615384
+overlap(list2, list1)   // 0.5384615384615384
+overlap(list1, list1)   // 1.0
+overlap(list2, list2)   // 1.0
+
+// Plagiarism examples from 
+// https://desales.libguides.com/avoidingplagiarism/examples
+
+val orig1 = """There is a strong market demand for eco-tourism in
+Australia. Its rich and diverse natural heritage ensures Australia's
+capacity to attract international ecotourists and gives Australia a
+comparative advantage in the highly competitive tourism industry."""
+
+val plag1 = """There is a high market demand for eco-tourism in
+Australia. Australia has a comparative advantage in the highly
+competitive tourism industry due to its rich and varied natural
+heritage which ensures Australia's capacity to attract international
+ecotourists."""
+
+similarity(orig1, plag1)
+
+
+// Plagiarism examples from 
+// https://www.utc.edu/library/help/tutorials/plagiarism/examples-of-plagiarism.php
+
+val orig2 = """No oil spill is entirely benign. Depending on timing and
+location, even a relatively minor spill can cause significant harm to
+individual organisms and entire populations. Oil spills can cause
+impacts over a range of time scales, from days to years, or even
+decades for certain spills. Impacts are typically divided into acute
+(short-term) and chronic (long-term) effects. Both types are part of a
+complicated and often controversial equation that is addressed after
+an oil spill: ecosystem recovery."""
+
+val plag2 = """There is no such thing as a "good" oil spill. If the
+time and place are just right, even a small oil spill can cause damage
+to sensitive ecosystems. Further, spills can cause harm days, months,
+years, or even decades after they occur. Because of this, spills are
+usually broken into short-term (acute) and long-term (chronic)
+effects. Both of these types of harm must be addressed in ecosystem
+recovery: a controversial tactic that is often implemented immediately
+following an oil spill."""
+
+overlap(clean(orig2), clean(plag2))
+similarity(orig2, plag2)
+
+// The punchline: everything above 0.6 looks suspicious and 
+// should be looked at by staff.
+
+*/
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing2/docdiff_test.sh	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,135 @@
+#!/bin/bash
+
+# to make the script fail safely
+set -euo pipefail
+
+
+out=${1:-output}
+
+echo "" > $out
+
+echo "Below is the feedback for your submission docdiff.scala" >> $out
+echo "" >> $out
+
+
+# compilation tests
+
+function scala_compile {
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -Xprint:parser "$1" 2> c$out 1> c$out)
+}
+
+# functional tests
+
+function scala_assert {
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
+}
+
+# purity test
+
+function scala_vars {
+   (egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' c$out 2> /dev/null 1> /dev/null)
+}
+
+
+
+### compilation test
+
+echo -e "docdiff.scala runs?" >> $out
+
+if (scala_compile docdiff.scala)
+then
+    echo -e "  --> passed" >> $out
+    tsts=$(( 0 ))
+else
+    echo -e "  --> SCALA DID NOT RUN docdiff.scala\n" >> $out
+    tsts=$(( 1 )) 
+fi
+
+
+# var, .par return, ListBuffer test
+#
+echo -e "docdiff.scala does not contain vars, returns etc?" >> $out
+
+if  [ $tsts -eq 0 ]
+then 
+   if (scala_vars docdiff.scala)
+   then
+      echo -e "  --> FAIL (make triple-sure your program conforms to the required format)\n" >> $out
+      tsts=$(( 1 ))
+   else
+      echo -e "  --> passed" >> $out
+      tsts=$(( 0 )) 
+   fi
+fi
+
+### docdiff clean tests
+
+if [ $tsts -eq 0 ]
+then
+  echo -e "docdiff.scala tests:" >> $out
+  echo -e "  clean(\"ab a abc\") == List(\"ab\", \"a\", \"abc\")" >> $out
+  echo -e "  clean(\"ab*a abc1\") == List(\"ab\", \"a\", \"abc1\")" >> $out
+
+  if (scala_assert "docdiff.scala" "docdiff_test1.scala")
+  then
+    echo -e "  --> success\n" >> $out
+  else
+    echo -e "  --> ONE OF THE TESTS FAILED\n" >> $out
+  fi
+fi
+
+### docdiff occurrences tests
+
+if [ $tsts -eq 0 ]
+then
+  echo -e "  occurrences(List(\"a\", \"b\", \"b\", \"c\", \"d\")) == " >> $out
+  echo -e "      Map(\"a\" -> 1, \"b\" -> 2, \"c\" -> 1, \"d\" -> 1)" >> $out
+  echo -e "  " >> $out
+  echo -e "  occurrences(List(\"d\", \"b\", \"d\", \"b\", \"d\")) == " >> $out
+  echo -e "      Map(\"d\" -> 3, \"b\" -> 2)" >> $out
+
+  if (scala_assert "docdiff.scala" "docdiff_test2.scala") 
+  then
+    echo -e "  --> success\n" >> $out
+  else
+    echo -e "  --> ONE OF THE TESTS FAILED\n" >> $out
+  fi
+fi
+
+### docdiff prod tests
+
+if [ $tsts -eq 0 ]
+then
+  echo -e "  val l1 = List(\"a\", \"b\", \"b\", \"c\", \"d\")" >> $out
+  echo -e "  val l2 = List(\"d\", \"b\", \"d\", \"b\", \"d\")" >> $out
+  echo -e "  " >> $out
+  echo -e "  prod(l1, l2) == 7 " >> $out
+  echo -e "  prod(l1, l1) == 7 " >> $out
+  echo -e "  prod(l2, l2) == 13 " >> $out
+
+  if (scala_assert "docdiff.scala" "docdiff_test3.scala") 
+  then
+    echo -e "  --> success\n" >> $out
+  else
+    echo -e "  --> ONE OF THE TESTS FAILED\n" >> $out
+  fi
+fi
+
+### docdiff overlap tests
+
+if [ $tsts -eq 0 ]
+then
+  echo -e "  val l1 = List(\"a\", \"b\", \"b\", \"c\", \"d\")" >> $out
+  echo -e "  val l2 = List(\"d\", \"b\", \"d\", \"b\", \"d\")" >> $out
+  echo -e "  " >> $out
+  echo -e "  overlap(l1, l2) == 0.5384615384615384 " >> $out
+  echo -e "  overlap(l1, l1) == 1.0 " >> $out
+  echo -e "  overlap(l2, l2) == 1.0 " >> $out
+
+  if (scala_assert "docdiff.scala" "docdiff_test4.scala") 
+  then
+    echo -e "  --> success\n" >> $out
+  else
+    echo -e "  --> ONE OF THE TESTS FAILED\n" >> $out
+  fi
+fi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing2/docdiff_test1.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,6 @@
+
+import C2._
+
+assert(clean("ab a abc") == List("ab", "a", "abc"))
+
+assert(clean("ab*a abc1") == List("ab", "a", "abc1"))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing2/docdiff_test2.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,6 @@
+
+import C2._
+
+assert(occurrences(List("a", "b", "b", "c", "d")) == Map("a" -> 1, "b" -> 2, "c" -> 1, "d" -> 1))
+
+assert(occurrences(List("d", "b", "d", "b", "d")) == Map("d" -> 3, "b" -> 2))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing2/docdiff_test3.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,11 @@
+
+import C2._
+
+val urban_list1 = List("a", "b", "b", "c", "d")
+val urban_list2 = List("d", "b", "d", "b", "d")
+
+assert(prod(urban_list1, urban_list2) == 7)
+
+assert(prod(urban_list1, urban_list1) == 7)
+
+assert(prod(urban_list2, urban_list2) == 13)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing2/docdiff_test4.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,11 @@
+
+import C2._
+
+val urban_list1 = List("a", "b", "b", "c", "d")
+val urban_list2 = List("d", "b", "d", "b", "d")
+
+assert(overlap(urban_list1, urban_list2) == 0.5384615384615384)
+
+assert(overlap(urban_list1, urban_list1) == 1.0)
+
+assert(overlap(urban_list2, urban_list2) == 1.0)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing3/postfix.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,103 @@
+// Shunting Yard Algorithm
+// by Edsger Dijkstra
+// ========================
+
+object C3a {
+
+type Toks = List[String]
+
+// the operations in the simple version
+val ops = List("+", "-", "*", "/")
+
+// the precedences of the operators
+val precs = Map("+" -> 1,
+		"-" -> 1,
+		"*" -> 2,
+		"/" -> 2)
+
+// helper function for splitting strings into tokens
+def split(s: String) : Toks = s.split(" ").toList
+
+// (6) Implement below the shunting yard algorithm. The most
+// convenient way to this in Scala is to implement a recursive 
+// function and to heavily use pattern matching. The function syard 
+// takes some input tokens as first argument. The second and third 
+// arguments represent the stack and the output of the shunting yard 
+// algorithm.
+//
+// In the marking, you can assume the function is called only with 
+// an empty stack and an empty output list. You can also assume the
+// input os  only properly formatted (infix) arithmetic expressions
+// (all parentheses will be well-nested, the input only contains 
+// operators and numbers).
+
+// You can implement any additional helper function you need. I found 
+// it helpful to implement two auxiliary functions for the pattern matching:  
+// 
+ 
+def is_op(op: String) : Boolean = ops.contains(op)
+
+def prec(op1: String, op2: String) : Boolean = precs(op1) <= precs(op2)
+
+
+def syard(toks: Toks, st: Toks = Nil, out: Toks = Nil) : Toks = (toks, st, out) match {
+  case (Nil, _, _) => out.reverse ::: st
+  case (num::in, st, out) if (num.forall(_.isDigit)) => 
+    syard(in, st, num :: out)
+  case (op1::in, op2::st, out)  if (is_op(op1) && is_op(op2) && prec(op1, op2)) =>
+    syard(op1::in, st, op2 :: out) 
+  case (op1::in, st, out) if (is_op(op1)) => syard(in, op1::st, out)
+  case ("("::in, st, out) => syard(in, "("::st, out)
+  case (")"::in, op2::st, out) =>
+    if (op2 == "(") syard(in, st, out) else syard(")"::in, st, op2 :: out)
+  case (in, st, out) => {
+    println(s"in: ${in}   st: ${st}   out: ${out.reverse}")
+    Nil
+  }  
+} 
+
+
+// test cases
+//syard(split("3 + 4 * ( 2 - 1 )"))  // 3 4 2 1 - * +
+//syard(split("10 + 12 * 33"))       // 10 12 33 * +
+//syard(split("( 5 + 7 ) * 2"))      // 5 7 + 2 *
+//syard(split("5 + 7 / 2"))          // 5 7 2 / +
+//syard(split("5 * 7 / 2"))          // 5 7 * 2 /
+//syard(split("9 + 24 / ( 7 - 3 )")) // 9 24 7 3 - / +
+
+//syard(split("3 + 4 + 5"))           // 3 4 + 5 +
+//syard(split("( ( 3 + 4 ) + 5 )"))    // 3 4 + 5 +
+//syard(split("( 3 + ( 4 + 5 ) )"))    // 3 4 5 + +
+//syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) // 3 4 5 + +
+
+// (7) Implement a compute function that evaluates an input list
+// in postfix notation. This function takes a list of tokens
+// and a stack as argumenta. The function should produce the 
+// result as an integer using the stack. You can assume 
+// this function will be only called with proper postfix 
+// expressions.    
+
+def op_comp(s: String, n1: Int, n2: Int) = s match {
+  case "+" => n2 + n1
+  case "-" => n2 - n1
+  case "*" => n2 * n1
+  case "/" => n2 / n1
+} 
+
+def compute(toks: Toks, st: List[Int] = Nil) : Int = (toks, st) match {
+  case (Nil, st) => st.head
+  case (op::in, n1::n2::st) if (is_op(op)) => compute(in, op_comp(op, n1, n2)::st)
+  case (num::in, st) => compute(in, num.toInt::st)  
+}
+
+// test cases
+// compute(syard(split("3 + 4 * ( 2 - 1 )")))  // 7
+// compute(syard(split("10 + 12 * 33")))       // 406
+// compute(syard(split("( 5 + 7 ) * 2")))      // 24
+// compute(syard(split("5 + 7 / 2")))          // 8
+// compute(syard(split("5 * 7 / 2")))          // 17
+// compute(syard(split("9 + 24 / ( 7 - 3 )"))) // 15
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing3/postfix2.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,100 @@
+// Shunting Yard Algorithm 
+// including Associativity for Operators 
+// =====================================
+
+object C3b {
+
+// type of tokens
+type Toks = List[String]
+
+// helper function for splitting strings into tokens
+def split(s: String) : Toks = s.split(" ").toList
+
+// left- and right-associativity
+abstract class Assoc
+case object LA extends Assoc
+case object RA extends Assoc
+
+// power is right-associative,
+// everything else is left-associative
+def assoc(s: String) : Assoc = s match {
+  case "^" => RA
+  case _ => LA
+}
+
+// the precedences of the operators
+val precs = Map("+" -> 1,
+  		 "-" -> 1,
+		 "*" -> 2,
+		 "/" -> 2,
+                 "^" -> 4)
+
+// the operations in the basic version of the algorithm
+val ops = List("+", "-", "*", "/", "^")
+
+// (8) Implement the extended version of the shunting yard algorithm.
+// This version should properly account for the fact that the power 
+// operation is right-associative. Apart from the extension to include
+// the power operation, you can make the same assumptions as in 
+// basic version.
+
+def is_op(op: String) : Boolean = ops.contains(op)
+
+def prec(op1: String, op2: String) : Boolean = assoc(op1) match {
+  case LA => precs(op1) <= precs(op2)
+  case RA => precs(op1) < precs(op2)
+}
+
+def syard(toks: Toks, st: Toks = Nil, out: Toks = Nil) : Toks = (toks, st, out) match {
+  case (Nil, _, _) => out.reverse ::: st
+  case (num::in, st, out) if (num.forall(_.isDigit)) => 
+    syard(in, st, num :: out)
+  case (op1::in, op2::st, out) if (is_op(op1) && is_op(op2) && prec(op1, op2)) =>
+    syard(op1::in, st, op2 :: out) 
+  case (op1::in, st, out) if (is_op(op1)) => syard(in, op1::st, out)
+  case ("("::in, st, out) => syard(in, "("::st, out)
+  case (")"::in, op2::st, out) =>
+    if (op2 == "(") syard(in, st, out) else syard(")"::in, st, op2 :: out)
+  case (in, st, out) => {
+    println(s"in: ${in}   st: ${st}   out: ${out.reverse}")
+    Nil
+  }  
+} 
+
+def op_comp(s: String, n1: Int, n2: Int) = s match {
+  case "+" => n2 + n1
+  case "-" => n2 - n1
+  case "*" => n2 * n1
+  case "/" => n2 / n1
+  case "^" => BigInt(n2).pow(n1).toInt
+} 
+
+def compute(toks: Toks, st: List[Int] = Nil) : Int = (toks, st) match {
+  case (Nil, st) => st.head
+  case (op::in, n1::n2::st) if (is_op(op)) => compute(in, op_comp(op, n1, n2)::st)
+  case (num::in, st) => compute(in, num.toInt::st)  
+}
+
+
+
+
+//compute(syard(split("3 + 4 * ( 2 - 1 )")))   // 7
+//compute(syard(split("10 + 12 * 33")))       // 406
+//compute(syard(split("( 5 + 7 ) * 2")))      // 24
+//compute(syard(split("5 + 7 / 2")))          // 8
+//compute(syard(split("5 * 7 / 2")))          // 17
+//compute(syard(split("9 + 24 / ( 7 - 3 )"))) // 15
+
+//compute(syard(split("4 ^ 3 ^ 2")))      // 262144
+//compute(syard(split("4 ^ ( 3 ^ 2 )")))  // 262144
+//compute(syard(split("( 4 ^ 3 ) ^ 2")))  // 4096
+//compute(syard(split("( 3 + 1 ) ^ 2 ^ 3")))   // 65536
+
+//syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3"))  // 3 4 8 * 5 1 - 2 3 ^ ^ / +
+//compute(syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3"))) // 3
+
+//compute(syard(split("( 3 + 1 ) ^ 2 ^ 3")))   // 65536
+
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing3/postfix_test.sh	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,162 @@
+#!/bin/bash
+set -euo pipefail
+
+
+out=${1:-output}
+
+echo -e "" > $out
+
+echo -e "Below is the feedback for your submission postfix.scala and postfix2.scala" >> $out
+echo -e "" >> $out
+
+# compilation tests
+
+function scala_compile {
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -Xprint:parser "$1" 2> c$out 1> c$out)
+}
+
+# functional tests
+
+function scala_assert {
+  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
+}
+
+# purity test
+
+function scala_vars {
+   (egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' c$out 2> /dev/null 1> /dev/null)
+}
+
+
+
+# compilation test
+
+echo -e "postfix.scala runs?" >> $out
+
+if (scala_compile postfix.scala)
+then
+    echo -e "  --> passed" >> $out
+    tsts=$(( 0 ))
+  else
+    echo -e "  --> SCALA DID NOT RUN postfix.scala\n" >> $out
+    tsts=$(( 1 )) 
+fi
+
+
+# var, return, ListBuffer test
+#
+echo -e "postfix.scala does not contain vars, returns etc?" >> $out
+
+if  [ $tsts -eq 0 ]
+then 
+    if (scala_vars postfix.scala)
+    then
+	echo -e "   --> FAIL (make triple-sure your program conforms to the required format)" >> $out 
+	tsts=$(( 1 ))
+    else
+	echo -e "  --> passed" >> $out
+	tsts=$(( 0 )) 
+    fi
+fi
+
+
+### postfix tests
+
+if [ $tsts -eq 0 ]
+then
+  echo -e " syard(split(\"3 + 4 * ( 2 - 1 )\")) == List(\"3\", \"4\", \"2\", \"1\", \"-\", \"\*\", \"+\")" >> $out
+  echo -e " syard(split(\"( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )\")) == List(\"3\", \"4\", \"5\", \"+\", \"+\")" >> $out
+  echo -e " syard(split(\"5 + 7 / 2\")) == List(\"5\", \"7\", \"2\", \"/\", \"+\")" >> $out
+  echo -e " syard(split(\"5 * 7 / 2\")) == List(\"5\", \"7\", \"\*\", \"2\", \"/\")" >> $out
+  
+  if (scala_assert "postfix.scala" "postfix_test7.scala")
+  then
+    echo -e "  --> success" >> $out
+  else
+    echo -e "  --> \n ONE TEST FAILED\n" >> $out
+  fi
+fi
+
+
+
+if [ $tsts -eq 0 ]
+then
+  echo -e " compute(syard(split(\"3 + 4 * ( 2 - 1 )\"))) == 7" >> $out
+  echo -e " compute(syard(split(\"10 + 12 * 33\"))) == 406" >> $out
+  echo -e " compute(syard(split(\"( 5 + 7 ) * 2\"))) == 24" >> $out
+  echo -e " compute(syard(split(\"5 + 7 / 2\"))) == 8" >> $out
+  echo -e " compute(syard(split(\"5 * 7 / 2\"))) == 17" >> $out
+  echo -e " compute(syard(split(\"9 + 24 / ( 7 - 3 )\"))) == 15" >> $out
+  
+  if (scala_assert "postfix.scala" "postfix_test8.scala")
+  then
+    echo -e "  --> success" >> $out
+  else
+    echo -e "  --> \n ONE TEST FAILED\n" >> $out
+  fi
+fi
+
+echo -e "" >> $out
+
+### postfix2 tests
+
+
+# compilation test
+
+echo -e "postfix2.scala runs?" >> $out
+
+if (scala_compile postfix2.scala)
+then
+    echo -e "  --> passed" >> $out
+    tsts1=$(( 0 ))
+else
+    echo -e "  --> SCALA DID NOT RUN postfix2.scala\n" >> $out
+    tsts1=$(( 1 )) 
+fi
+
+
+# var, return, ListBuffer test
+#
+echo -e "\n\npostfix2.scala does not contain vars, returns etc?" >> $out
+
+if [ $tsts1 -eq 0 ]
+then
+    if (scala_vars postfix2.scala)
+    then
+	echo -e "   --> FAIL (make triple-sure your program conforms to the required format)" >> $out 
+	tsts1=$(( 1 ))
+    else
+	echo -e "  --> passed" >> $out
+	tsts1=$(( 0 )) 
+    fi
+fi
+
+
+if [ $tsts1 -eq 0 ]
+then
+  echo -e " syard(split(\"3 + 4 * ( 2 - 1 )\")) == List(\"3\", \"4\", \"2\", \"1\", \"-\", \"\*\", \"+\")" >> $out
+  echo -e " syard(split(\"( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )\")) == List(\"3\", \"4\", \"5\", \"+\", \"+\")" >> $out
+  echo -e " syard(split(\"5 + 7 / 2\")) == List(\"5\", \"7\", \"2\", \"/\", \"+\")" >> $out
+  echo -e " syard(split(\"5 * 7 / 2\")) == List(\"5\", \"7\", \"\*\", \"2\", \"/\")" >> $out
+  echo -e " syard(split(\"3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3\")) == " >> $out
+  echo -e "         List(\"3\", \"4\", \"8\", \"\*\", \"5\", \"1\", \"-\", \"2\", \"3\", \"^\", \"^\", \"/\", \"+\")" >> $out
+  echo -e " " >> $out 
+  echo -e " compute(syard(split(\"3 + 4 * ( 2 - 1 )\"))) == 7" >> $out
+  echo -e " compute(syard(split(\"10 + 12 * 33\"))) == 406" >> $out
+  echo -e " compute(syard(split(\"( 5 + 7 ) * 2\"))) == 24" >> $out
+  echo -e " compute(syard(split(\"5 + 7 / 2\"))) == 8" >> $out
+  echo -e " compute(syard(split(\"5 * 7 / 2\"))) == 17" >> $out
+  echo -e " compute(syard(split(\"9 + 24 / ( 7 - 3 )\"))) == 15" >> $out
+  echo -e " compute(syard(split(\"4 ^ 3 ^ 2\"))) == 262144" >> $out
+  echo -e " compute(syard(split(\"4 ^ ( 3 ^ 2 )\"))) == 262144" >> $out
+  echo -e " compute(syard(split(\"( 4 ^ 3 ) ^ 2\"))) == 4096" >> $out
+  echo -e " compute(syard(split(\"( 3 + 1 ) ^ 2 ^ 3\"))) == 65536" >> $out
+  
+  if (scala_assert "postfix2.scala" "postfix_test9.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/core_testing3/postfix_test7.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,7 @@
+import C3a._
+
+
+assert(syard(split("3 + 4 * ( 2 - 1 )")) == List("3", "4", "2", "1", "-", "*", "+"))
+assert(syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) == List("3", "4", "5", "+", "+"))
+assert(syard(split("5 + 7 / 2")) == List("5", "7", "2", "/", "+"))
+assert(syard(split("5 * 7 / 2")) == List("5", "7", "*", "2", "/"))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing3/postfix_test8.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,8 @@
+import C3a._
+
+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)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core_testing3/postfix_test9.scala	Mon Nov 08 01:03:09 2021 +0000
@@ -0,0 +1,21 @@
+import C3b._
+
+
+assert(syard(split("3 + 4 * ( 2 - 1 )")) == List("3", "4", "2", "1", "-", "*", "+"))
+assert(syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) == List("3", "4", "5", "+", "+"))
+assert(syard(split("5 + 7 / 2")) == List("5", "7", "2", "/", "+"))
+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)
Binary file pre_solution3/postfix.jar has changed
--- a/pre_solution3/postfix.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-// Shunting Yard Algorithm
-// by Edsger Dijkstra
-// ========================
-
-object CW8a {
-
-type Toks = List[String]
-
-// the operations in the simple version
-val ops = List("+", "-", "*", "/")
-
-// the precedences of the operators
-val precs = Map("+" -> 1,
-		"-" -> 1,
-		"*" -> 2,
-		"/" -> 2)
-
-// helper function for splitting strings into tokens
-def split(s: String) : Toks = s.split(" ").toList
-
-// (6) Implement below the shunting yard algorithm. The most
-// convenient way to this in Scala is to implement a recursive 
-// function and to heavily use pattern matching. The function syard 
-// takes some input tokens as first argument. The second and third 
-// arguments represent the stack and the output of the shunting yard 
-// algorithm.
-//
-// In the marking, you can assume the function is called only with 
-// an empty stack and an empty output list. You can also assume the
-// input os  only properly formatted (infix) arithmetic expressions
-// (all parentheses will be well-nested, the input only contains 
-// operators and numbers).
-
-// You can implement any additional helper function you need. I found 
-// it helpful to implement two auxiliary functions for the pattern matching:  
-// 
- 
-def is_op(op: String) : Boolean = ops.contains(op)
-
-def prec(op1: String, op2: String) : Boolean = precs(op1) <= precs(op2)
-
-
-def syard(toks: Toks, st: Toks = Nil, out: Toks = Nil) : Toks = (toks, st, out) match {
-  case (Nil, _, _) => out.reverse ::: st
-  case (num::in, st, out) if (num.forall(_.isDigit)) => 
-    syard(in, st, num :: out)
-  case (op1::in, op2::st, out)  if (is_op(op1) && is_op(op2) && prec(op1, op2)) =>
-    syard(op1::in, st, op2 :: out) 
-  case (op1::in, st, out) if (is_op(op1)) => syard(in, op1::st, out)
-  case ("("::in, st, out) => syard(in, "("::st, out)
-  case (")"::in, op2::st, out) =>
-    if (op2 == "(") syard(in, st, out) else syard(")"::in, st, op2 :: out)
-  case (in, st, out) => {
-    println(s"in: ${in}   st: ${st}   out: ${out.reverse}")
-    Nil
-  }  
-} 
-
-
-// test cases
-//syard(split("3 + 4 * ( 2 - 1 )"))  // 3 4 2 1 - * +
-//syard(split("10 + 12 * 33"))       // 10 12 33 * +
-//syard(split("( 5 + 7 ) * 2"))      // 5 7 + 2 *
-//syard(split("5 + 7 / 2"))          // 5 7 2 / +
-//syard(split("5 * 7 / 2"))          // 5 7 * 2 /
-//syard(split("9 + 24 / ( 7 - 3 )")) // 9 24 7 3 - / +
-
-//syard(split("3 + 4 + 5"))           // 3 4 + 5 +
-//syard(split("( ( 3 + 4 ) + 5 )"))    // 3 4 + 5 +
-//syard(split("( 3 + ( 4 + 5 ) )"))    // 3 4 5 + +
-//syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) // 3 4 5 + +
-
-// (7) Implement a compute function that evaluates an input list
-// in postfix notation. This function takes a list of tokens
-// and a stack as argumenta. The function should produce the 
-// result as an integer using the stack. You can assume 
-// this function will be only called with proper postfix 
-// expressions.    
-
-def op_comp(s: String, n1: Int, n2: Int) = s match {
-  case "+" => n2 + n1
-  case "-" => n2 - n1
-  case "*" => n2 * n1
-  case "/" => n2 / n1
-} 
-
-def compute(toks: Toks, st: List[Int] = Nil) : Int = (toks, st) match {
-  case (Nil, st) => st.head
-  case (op::in, n1::n2::st) if (is_op(op)) => compute(in, op_comp(op, n1, n2)::st)
-  case (num::in, st) => compute(in, num.toInt::st)  
-}
-
-// test cases
-// compute(syard(split("3 + 4 * ( 2 - 1 )")))  // 7
-// compute(syard(split("10 + 12 * 33")))       // 406
-// compute(syard(split("( 5 + 7 ) * 2")))      // 24
-// compute(syard(split("5 + 7 / 2")))          // 8
-// compute(syard(split("5 * 7 / 2")))          // 17
-// compute(syard(split("9 + 24 / ( 7 - 3 )"))) // 15
-
-}
-
-
Binary file pre_solution3/postfix2.jar has changed
--- a/pre_solution3/postfix2.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-// Shunting Yard Algorithm 
-// including Associativity for Operators 
-// =====================================
-
-object CW8b {
-
-// type of tokens
-type Toks = List[String]
-
-// helper function for splitting strings into tokens
-def split(s: String) : Toks = s.split(" ").toList
-
-// left- and right-associativity
-abstract class Assoc
-case object LA extends Assoc
-case object RA extends Assoc
-
-// power is right-associative,
-// everything else is left-associative
-def assoc(s: String) : Assoc = s match {
-  case "^" => RA
-  case _ => LA
-}
-
-// the precedences of the operators
-val precs = Map("+" -> 1,
-  		 "-" -> 1,
-		 "*" -> 2,
-		 "/" -> 2,
-                 "^" -> 4)
-
-// the operations in the basic version of the algorithm
-val ops = List("+", "-", "*", "/", "^")
-
-// (8) Implement the extended version of the shunting yard algorithm.
-// This version should properly account for the fact that the power 
-// operation is right-associative. Apart from the extension to include
-// the power operation, you can make the same assumptions as in 
-// basic version.
-
-def is_op(op: String) : Boolean = ops.contains(op)
-
-def prec(op1: String, op2: String) : Boolean = assoc(op1) match {
-  case LA => precs(op1) <= precs(op2)
-  case RA => precs(op1) < precs(op2)
-}
-
-def syard(toks: Toks, st: Toks = Nil, out: Toks = Nil) : Toks = (toks, st, out) match {
-  case (Nil, _, _) => out.reverse ::: st
-  case (num::in, st, out) if (num.forall(_.isDigit)) => 
-    syard(in, st, num :: out)
-  case (op1::in, op2::st, out) if (is_op(op1) && is_op(op2) && prec(op1, op2)) =>
-    syard(op1::in, st, op2 :: out) 
-  case (op1::in, st, out) if (is_op(op1)) => syard(in, op1::st, out)
-  case ("("::in, st, out) => syard(in, "("::st, out)
-  case (")"::in, op2::st, out) =>
-    if (op2 == "(") syard(in, st, out) else syard(")"::in, st, op2 :: out)
-  case (in, st, out) => {
-    println(s"in: ${in}   st: ${st}   out: ${out.reverse}")
-    Nil
-  }  
-} 
-
-def op_comp(s: String, n1: Int, n2: Int) = s match {
-  case "+" => n2 + n1
-  case "-" => n2 - n1
-  case "*" => n2 * n1
-  case "/" => n2 / n1
-  case "^" => BigInt(n2).pow(n1).toInt
-} 
-
-def compute(toks: Toks, st: List[Int] = Nil) : Int = (toks, st) match {
-  case (Nil, st) => st.head
-  case (op::in, n1::n2::st) if (is_op(op)) => compute(in, op_comp(op, n1, n2)::st)
-  case (num::in, st) => compute(in, num.toInt::st)  
-}
-
-
-
-
-//compute(syard(split("3 + 4 * ( 2 - 1 )")))   // 7
-//compute(syard(split("10 + 12 * 33")))       // 406
-//compute(syard(split("( 5 + 7 ) * 2")))      // 24
-//compute(syard(split("5 + 7 / 2")))          // 8
-//compute(syard(split("5 * 7 / 2")))          // 17
-//compute(syard(split("9 + 24 / ( 7 - 3 )"))) // 15
-
-//compute(syard(split("4 ^ 3 ^ 2")))      // 262144
-//compute(syard(split("4 ^ ( 3 ^ 2 )")))  // 262144
-//compute(syard(split("( 4 ^ 3 ) ^ 2")))  // 4096
-//compute(syard(split("( 3 + 1 ) ^ 2 ^ 3")))   // 65536
-
-//syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3"))  // 3 4 8 * 5 1 - 2 3 ^ ^ / +
-//compute(syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3"))) // 3
-
-//compute(syard(split("( 3 + 1 ) ^ 2 ^ 3")))   // 65536
-
-
-
-}
--- a/pre_testing2/docdiff.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-// Preliminary Part about Code Similarity
-//========================================
-
-object CW7a {
-
-
-//(1) Complete the clean function below. It should find
-//    all words in a string using the regular expression
-//    \w+  and the library function
-//
-//         some_regex.findAllIn(some_string)
-//
-//    The words should be Returned as a list of strings.
-
-
-//def clean(s: String) : List[String] = ...
-def clean(s: String) : List[String] =
-    "\\w+".r.findAllIn(s).toList
-
-//(2) The function occurrences calculates the number of times
-//    strings occur in a list of strings. These occurrences should
-//    be calculated as a Map from strings to integers.
-
-
-//def occurrences(xs: List[String]): Map[String, Int] = ..
-def occurrences(xs: List[String]) : Map[String, Int] =
-    xs.groupBy(identity).view.mapValues(_.size).toMap
-
-//(3) This functions calculates the dot-product of two documents
-//    (list of strings). For this it calculates the occurrence
-//    maps from (2) and then multiplies the corresponding occurrences.
-//    If a string does not occur in a document, the product is zero.
-//    The function finally sums up all products.
-
-
-//def prod(lst1: List[String], lst2: List[String]) : Int = ..
-def prod(lst1: List[String], lst2: List[String]) : Int =
-    occurrences(lst1).map(x => occurrences(lst2).getOrElse(x._1, 0) * x._2).reduce(_ + _)
-
-//(4) Complete the functions overlap and similarity. The overlap of
-//    two documents is calculated by the formula given in the assignment
-//    description. The similarity of two strings is given by the overlap
-//    of the cleaned strings (see (1)).
-
-
-//def overlap(lst1: List[String], lst2: List[String]) : Double = ...
-def overlap(lst1: List[String], lst2: List[String]) : Double =
-    prod(lst1, lst2).toDouble/Math.max(prod(lst1, lst1).toDouble, prod(lst2, lst2).toDouble)
-//def similarity(s1: String, s2: String) : Double = ...
-def similarity(s1: String, s2: String) : Double =
-    overlap(clean(s1), clean(s2))
-
-
-/* Test cases
-import CW7a._
-val list1 = List("a", "b", "b", "c", "d")
-val list2 = List("d", "b", "d", "b", "d")
-occurrences(List("a", "b", "b", "c", "d"))
-occurrences(List("d", "b", "d", "b", "d"))
-prod(list1,list2) // 7
-overlap(list1, list2)   // 0.5384615384615384
-overlap(list2, list1)   // 0.5384615384615384
-overlap(list1, list1)   // 1.0
-overlap(list2, list2)   // 1.0
-// Plagiarism examples from
-// https://desales.libguides.com/avoidingplagiarism/examples
-val orig1 = """There is a strong market demand for eco-tourism in
-Australia. Its rich and diverse natural heritage ensures Australia's
-capacity to attract international ecotourists and gives Australia a
-comparative advantage in the highly competitive tourism industry."""
-val plag1 = """There is a high market demand for eco-tourism in
-Australia. Australia has a comparative advantage in the highly
-competitive tourism industry due to its rich and varied natural
-heritage which ensures Australia's capacity to attract international
-ecotourists."""
-similarity(orig1, plag1) // 0.8679245283018868
-// Plagiarism examples from
-// https://www.utc.edu/library/help/tutorials/plagiarism/examples-of-plagiarism.php
-val orig2 = """No oil spill is entirely benign. Depending on timing and
-location, even a relatively minor spill can cause significant harm to
-individual organisms and entire populations. Oil spills can cause
-impacts over a range of time scales, from days to years, or even
-decades for certain spills. Impacts are typically divided into acute
-(short-term) and chronic (long-term) effects. Both types are part of a
-complicated and often controversial equation that is addressed after
-an oil spill: ecosystem recovery."""
-val plag2 = """There is no such thing as a "good" oil spill. If the
-time and place are just right, even a small oil spill can cause damage
-to sensitive ecosystems. Further, spills can cause harm days, months,
-years, or even decades after they occur. Because of this, spills are
-usually broken into short-term (acute) and long-term (chronic)
-effects. Both of these types of harm must be addressed in ecosystem
-recovery: a controversial tactic that is often implemented immediately
-following an oil spill."""
-overlap(clean(orig2), clean(plag2))  // 0.728
-similarity(orig2, plag2)             // 0.728
-// The punchline: everything above 0.6 looks suspicious and
-// should be investigated by staff.
-*/
-
-}
--- a/pre_testing2/docdiff_test.sh	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-#!/bin/bash
-
-# to make the script fail safely
-set -euo pipefail
-
-
-out=${1:-output}
-
-echo "" > $out
-
-echo "Below is the feedback for your submission docdiff.scala" >> $out
-echo "" >> $out
-
-
-# compilation tests
-
-function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -Xprint:parser "$1" 2> c$out 1> c$out)
-}
-
-# functional tests
-
-function scala_assert {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
-}
-
-# purity test
-
-function scala_vars {
-   (egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' c$out 2> /dev/null 1> /dev/null)
-}
-
-
-
-### compilation test
-
-echo -e "docdiff.scala runs?" >> $out
-
-if (scala_compile docdiff.scala)
-then
-    echo -e "  --> passed" >> $out
-    tsts=$(( 0 ))
-else
-    echo -e "  --> SCALA DID NOT RUN docdiff.scala\n" >> $out
-    tsts=$(( 1 )) 
-fi
-
-
-# var, .par return, ListBuffer test
-#
-echo -e "docdiff.scala does not contain vars, returns etc?" >> $out
-
-if  [ $tsts -eq 0 ]
-then 
-   if (scala_vars docdiff.scala)
-   then
-      echo -e "  --> FAIL (make triple-sure your program conforms to the required format)\n" >> $out
-      tsts=$(( 1 ))
-   else
-      echo -e "  --> passed" >> $out
-      tsts=$(( 0 )) 
-   fi
-fi
-
-### docdiff clean tests
-
-if [ $tsts -eq 0 ]
-then
-  echo -e "docdiff.scala tests:" >> $out
-  echo -e "  clean(\"ab a abc\") == List(\"ab\", \"a\", \"abc\")" >> $out
-  echo -e "  clean(\"ab*a abc1\") == List(\"ab\", \"a\", \"abc1\")" >> $out
-
-  if (scala_assert "docdiff.scala" "docdiff_test1.scala")
-  then
-    echo -e "  --> success\n" >> $out
-  else
-    echo -e "  --> ONE OF THE TESTS FAILED\n" >> $out
-  fi
-fi
-
-### docdiff occurrences tests
-
-if [ $tsts -eq 0 ]
-then
-  echo -e "  occurrences(List(\"a\", \"b\", \"b\", \"c\", \"d\")) == " >> $out
-  echo -e "      Map(\"a\" -> 1, \"b\" -> 2, \"c\" -> 1, \"d\" -> 1)" >> $out
-  echo -e "  " >> $out
-  echo -e "  occurrences(List(\"d\", \"b\", \"d\", \"b\", \"d\")) == " >> $out
-  echo -e "      Map(\"d\" -> 3, \"b\" -> 2)" >> $out
-
-  if (scala_assert "docdiff.scala" "docdiff_test2.scala") 
-  then
-    echo -e "  --> success\n" >> $out
-  else
-    echo -e "  --> ONE OF THE TESTS FAILED\n" >> $out
-  fi
-fi
-
-### docdiff prod tests
-
-if [ $tsts -eq 0 ]
-then
-  echo -e "  val l1 = List(\"a\", \"b\", \"b\", \"c\", \"d\")" >> $out
-  echo -e "  val l2 = List(\"d\", \"b\", \"d\", \"b\", \"d\")" >> $out
-  echo -e "  " >> $out
-  echo -e "  prod(l1, l2) == 7 " >> $out
-  echo -e "  prod(l1, l1) == 7 " >> $out
-  echo -e "  prod(l2, l2) == 13 " >> $out
-
-  if (scala_assert "docdiff.scala" "docdiff_test3.scala") 
-  then
-    echo -e "  --> success\n" >> $out
-  else
-    echo -e "  --> ONE OF THE TESTS FAILED\n" >> $out
-  fi
-fi
-
-### docdiff overlap tests
-
-if [ $tsts -eq 0 ]
-then
-  echo -e "  val l1 = List(\"a\", \"b\", \"b\", \"c\", \"d\")" >> $out
-  echo -e "  val l2 = List(\"d\", \"b\", \"d\", \"b\", \"d\")" >> $out
-  echo -e "  " >> $out
-  echo -e "  overlap(l1, l2) == 0.5384615384615384 " >> $out
-  echo -e "  overlap(l1, l1) == 1.0 " >> $out
-  echo -e "  overlap(l2, l2) == 1.0 " >> $out
-
-  if (scala_assert "docdiff.scala" "docdiff_test4.scala") 
-  then
-    echo -e "  --> success\n" >> $out
-  else
-    echo -e "  --> ONE OF THE TESTS FAILED\n" >> $out
-  fi
-fi
--- a/pre_testing2/docdiff_test1.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-
-import CW7a._
-
-assert(clean("ab a abc") == List("ab", "a", "abc"))
-
-assert(clean("ab*a abc1") == List("ab", "a", "abc1"))
--- a/pre_testing2/docdiff_test2.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-
-import CW7a._
-
-assert(occurrences(List("a", "b", "b", "c", "d")) == Map("a" -> 1, "b" -> 2, "c" -> 1, "d" -> 1))
-
-assert(occurrences(List("d", "b", "d", "b", "d")) == Map("d" -> 3, "b" -> 2))
--- a/pre_testing2/docdiff_test3.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-
-import CW7a._
-
-val urban_list1 = List("a", "b", "b", "c", "d")
-val urban_list2 = List("d", "b", "d", "b", "d")
-
-assert(prod(urban_list1, urban_list2) == 7)
-
-assert(prod(urban_list1, urban_list1) == 7)
-
-assert(prod(urban_list2, urban_list2) == 13)
--- a/pre_testing2/docdiff_test4.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-
-import CW7a._
-
-val urban_list1 = List("a", "b", "b", "c", "d")
-val urban_list2 = List("d", "b", "d", "b", "d")
-
-assert(overlap(urban_list1, urban_list2) == 0.5384615384615384)
-
-assert(overlap(urban_list1, urban_list1) == 1.0)
-
-assert(overlap(urban_list2, urban_list2) == 1.0)
--- a/pre_testing3/postfix.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-// Shunting Yard Algorithm
-// by Edsger Dijkstra
-// ========================
-
-object CW8a {
-
-type Toks = List[String]
-
-// the operations in the simple version
-val ops = List("+", "-", "*", "/")
-
-// the precedences of the operators
-val precs = Map("+" -> 1,
-		"-" -> 1,
-		"*" -> 2,
-		"/" -> 2)
-
-// helper function for splitting strings into tokens
-def split(s: String) : Toks = s.split(" ").toList
-
-// (6) Implement below the shunting yard algorithm. The most
-// convenient way to this in Scala is to implement a recursive 
-// function and to heavily use pattern matching. The function syard 
-// takes some input tokens as first argument. The second and third 
-// arguments represent the stack and the output of the shunting yard 
-// algorithm.
-//
-// In the marking, you can assume the function is called only with 
-// an empty stack and an empty output list. You can also assume the
-// input os  only properly formatted (infix) arithmetic expressions
-// (all parentheses will be well-nested, the input only contains 
-// operators and numbers).
-
-// You can implement any additional helper function you need. I found 
-// it helpful to implement two auxiliary functions for the pattern matching:  
-// 
- 
-def is_op(op: String) : Boolean = ops.contains(op)
-
-def prec(op1: String, op2: String) : Boolean = precs(op1) <= precs(op2)
-
-
-def syard(toks: Toks, st: Toks = Nil, out: Toks = Nil) : Toks = (toks, st, out) match {
-  case (Nil, _, _) => out.reverse ::: st
-  case (num::in, st, out) if (num.forall(_.isDigit)) => 
-    syard(in, st, num :: out)
-  case (op1::in, op2::st, out)  if (is_op(op1) && is_op(op2) && prec(op1, op2)) =>
-    syard(op1::in, st, op2 :: out) 
-  case (op1::in, st, out) if (is_op(op1)) => syard(in, op1::st, out)
-  case ("("::in, st, out) => syard(in, "("::st, out)
-  case (")"::in, op2::st, out) =>
-    if (op2 == "(") syard(in, st, out) else syard(")"::in, st, op2 :: out)
-  case (in, st, out) => {
-    println(s"in: ${in}   st: ${st}   out: ${out.reverse}")
-    Nil
-  }  
-} 
-
-
-// test cases
-//syard(split("3 + 4 * ( 2 - 1 )"))  // 3 4 2 1 - * +
-//syard(split("10 + 12 * 33"))       // 10 12 33 * +
-//syard(split("( 5 + 7 ) * 2"))      // 5 7 + 2 *
-//syard(split("5 + 7 / 2"))          // 5 7 2 / +
-//syard(split("5 * 7 / 2"))          // 5 7 * 2 /
-//syard(split("9 + 24 / ( 7 - 3 )")) // 9 24 7 3 - / +
-
-//syard(split("3 + 4 + 5"))           // 3 4 + 5 +
-//syard(split("( ( 3 + 4 ) + 5 )"))    // 3 4 + 5 +
-//syard(split("( 3 + ( 4 + 5 ) )"))    // 3 4 5 + +
-//syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) // 3 4 5 + +
-
-// (7) Implement a compute function that evaluates an input list
-// in postfix notation. This function takes a list of tokens
-// and a stack as argumenta. The function should produce the 
-// result as an integer using the stack. You can assume 
-// this function will be only called with proper postfix 
-// expressions.    
-
-def op_comp(s: String, n1: Int, n2: Int) = s match {
-  case "+" => n2 + n1
-  case "-" => n2 - n1
-  case "*" => n2 * n1
-  case "/" => n2 / n1
-} 
-
-def compute(toks: Toks, st: List[Int] = Nil) : Int = (toks, st) match {
-  case (Nil, st) => st.head
-  case (op::in, n1::n2::st) if (is_op(op)) => compute(in, op_comp(op, n1, n2)::st)
-  case (num::in, st) => compute(in, num.toInt::st)  
-}
-
-// test cases
-// compute(syard(split("3 + 4 * ( 2 - 1 )")))  // 7
-// compute(syard(split("10 + 12 * 33")))       // 406
-// compute(syard(split("( 5 + 7 ) * 2")))      // 24
-// compute(syard(split("5 + 7 / 2")))          // 8
-// compute(syard(split("5 * 7 / 2")))          // 17
-// compute(syard(split("9 + 24 / ( 7 - 3 )"))) // 15
-
-}
-
-
--- a/pre_testing3/postfix2.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-// Shunting Yard Algorithm 
-// including Associativity for Operators 
-// =====================================
-
-object CW8b { 
-
-// type of tokens
-type Toks = List[String]
-
-// helper function for splitting strings into tokens
-def split(s: String) : Toks = s.split(" ").toList
-
-// left- and right-associativity
-abstract class Assoc
-case object LA extends Assoc
-case object RA extends Assoc
-
-// power is right-associative,
-// everything else is left-associative
-def assoc(s: String) : Assoc = s match {
-  case "^" => RA
-  case _ => LA
-}
-
-// the precedences of the operators
-val precs = Map("+" -> 1,
-  		 "-" -> 1,
-		 "*" -> 2,
-		 "/" -> 2,
-                 "^" -> 4)
-
-// the operations in the basic version of the algorithm
-val ops = List("+", "-", "*", "/", "^")
-
-// (8) Implement the extended version of the shunting yard algorithm.
-// This version should properly account for the fact that the power 
-// operation is right-associative. Apart from the extension to include
-// the power operation, you can make the same assumptions as in 
-// basic version.
-
-def is_op(op: String) : Boolean = ops.contains(op)
-
-def prec(op1: String, op2: String) : Boolean = assoc(op1) match {
-  case LA => precs(op1) <= precs(op2)
-  case RA => precs(op1) < precs(op2)
-}
-
-def syard(toks: Toks, st: Toks = Nil, out: Toks = Nil) : Toks = (toks, st, out) match {
-  case (Nil, _, _) => out.reverse ::: st
-  case (num::in, st, out) if (num.forall(_.isDigit)) => 
-    syard(in, st, num :: out)
-  case (op1::in, op2::st, out) if (is_op(op1) && is_op(op2) && prec(op1, op2)) =>
-    syard(op1::in, st, op2 :: out) 
-  case (op1::in, st, out) if (is_op(op1)) => syard(in, op1::st, out)
-  case ("("::in, st, out) => syard(in, "("::st, out)
-  case (")"::in, op2::st, out) =>
-    if (op2 == "(") syard(in, st, out) else syard(")"::in, st, op2 :: out)
-  case (in, st, out) => {
-    println(s"in: ${in}   st: ${st}   out: ${out.reverse}")
-    Nil
-  }  
-} 
-
-def op_comp(s: String, n1: Long, n2: Long) = s match {
-  case "+" => n2 + n1
-  case "-" => n2 - n1
-  case "*" => n2 * n1
-  case "/" => n2 / n1
-  case "^" => Math.pow(n2, n1).toLong
-} 
-
-def compute(toks: Toks, st: List[Long] = Nil) : Long = (toks, st) match {
-  case (Nil, st) => st.head
-  case (op::in, n1::n2::st) if (is_op(op)) => compute(in, op_comp(op, n1, n2)::st)
-  case (num::in, st) => compute(in, num.toInt::st)  
-}
-
-
-
-
-//compute(syard(split("3 + 4 * ( 2 - 1 )")))   // 7
-//compute(syard(split("10 + 12 * 33")))       // 406
-//compute(syard(split("( 5 + 7 ) * 2")))      // 24
-//compute(syard(split("5 + 7 / 2")))          // 8
-//compute(syard(split("5 * 7 / 2")))          // 17
-//compute(syard(split("9 + 24 / ( 7 - 3 )"))) // 15
-
-//compute(syard(split("4 ^ 3 ^ 2")))      // 262144
-//compute(syard(split("4 ^ ( 3 ^ 2 )")))  // 262144
-//compute(syard(split("( 4 ^ 3 ) ^ 2")))  // 4096
-//compute(syard(split("( 3 + 1 ) ^ 2 ^ 3")))   // 65536
-
-//syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3"))  // 3 4 8 * 5 1 - 2 3 ^ ^ / +
-//compute(syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3"))) // 3
-
-//compute(syard(split("( 3 + 1 ) ^ 2 ^ 3")))   // 65536
-
-
-
-}
--- a/pre_testing3/postfix_test.sh	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-#!/bin/bash
-set -euo pipefail
-
-
-out=${1:-output}
-
-echo -e "" > $out
-
-echo -e "Below is the feedback for your submission postfix.scala and postfix2.scala" >> $out
-echo -e "" >> $out
-
-# compilation tests
-
-function scala_compile {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -Xprint:parser "$1" 2> c$out 1> c$out)
-}
-
-# functional tests
-
-function scala_assert {
-  (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
-}
-
-# purity test
-
-function scala_vars {
-   (egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' c$out 2> /dev/null 1> /dev/null)
-}
-
-
-
-# compilation test
-
-echo -e "postfix.scala runs?" >> $out
-
-if (scala_compile postfix.scala)
-then
-    echo -e "  --> passed" >> $out
-    tsts=$(( 0 ))
-  else
-    echo -e "  --> SCALA DID NOT RUN postfix.scala\n" >> $out
-    tsts=$(( 1 )) 
-fi
-
-
-# var, return, ListBuffer test
-#
-echo -e "postfix.scala does not contain vars, returns etc?" >> $out
-
-if  [ $tsts -eq 0 ]
-then 
-    if (scala_vars postfix.scala)
-    then
-	echo -e "   --> FAIL (make triple-sure your program conforms to the required format)" >> $out 
-	tsts=$(( 1 ))
-    else
-	echo -e "  --> passed" >> $out
-	tsts=$(( 0 )) 
-    fi
-fi
-
-
-### postfix tests
-
-if [ $tsts -eq 0 ]
-then
-  echo -e " syard(split(\"3 + 4 * ( 2 - 1 )\")) == List(\"3\", \"4\", \"2\", \"1\", \"-\", \"\*\", \"+\")" >> $out
-  echo -e " syard(split(\"( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )\")) == List(\"3\", \"4\", \"5\", \"+\", \"+\")" >> $out
-  echo -e " syard(split(\"5 + 7 / 2\")) == List(\"5\", \"7\", \"2\", \"/\", \"+\")" >> $out
-  echo -e " syard(split(\"5 * 7 / 2\")) == List(\"5\", \"7\", \"\*\", \"2\", \"/\")" >> $out
-  
-  if (scala_assert "postfix.scala" "postfix_test7.scala")
-  then
-    echo -e "  --> success" >> $out
-  else
-    echo -e "  --> \n ONE TEST FAILED\n" >> $out
-  fi
-fi
-
-
-
-if [ $tsts -eq 0 ]
-then
-  echo -e " compute(syard(split(\"3 + 4 * ( 2 - 1 )\"))) == 7" >> $out
-  echo -e " compute(syard(split(\"10 + 12 * 33\"))) == 406" >> $out
-  echo -e " compute(syard(split(\"( 5 + 7 ) * 2\"))) == 24" >> $out
-  echo -e " compute(syard(split(\"5 + 7 / 2\"))) == 8" >> $out
-  echo -e " compute(syard(split(\"5 * 7 / 2\"))) == 17" >> $out
-  echo -e " compute(syard(split(\"9 + 24 / ( 7 - 3 )\"))) == 15" >> $out
-  
-  if (scala_assert "postfix.scala" "postfix_test8.scala")
-  then
-    echo -e "  --> success" >> $out
-  else
-    echo -e "  --> \n ONE TEST FAILED\n" >> $out
-  fi
-fi
-
-echo -e "" >> $out
-
-### postfix2 tests
-
-
-# compilation test
-
-echo -e "postfix2.scala runs?" >> $out
-
-if (scala_compile postfix2.scala)
-then
-    echo -e "  --> passed" >> $out
-    tsts1=$(( 0 ))
-else
-    echo -e "  --> SCALA DID NOT RUN postfix2.scala\n" >> $out
-    tsts1=$(( 1 )) 
-fi
-
-
-# var, return, ListBuffer test
-#
-echo -e "\n\npostfix2.scala does not contain vars, returns etc?" >> $out
-
-if [ $tsts1 -eq 0 ]
-then
-    if (scala_vars postfix2.scala)
-    then
-	echo -e "   --> FAIL (make triple-sure your program conforms to the required format)" >> $out 
-	tsts1=$(( 1 ))
-    else
-	echo -e "  --> passed" >> $out
-	tsts1=$(( 0 )) 
-    fi
-fi
-
-
-if [ $tsts1 -eq 0 ]
-then
-  echo -e " syard(split(\"3 + 4 * ( 2 - 1 )\")) == List(\"3\", \"4\", \"2\", \"1\", \"-\", \"\*\", \"+\")" >> $out
-  echo -e " syard(split(\"( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )\")) == List(\"3\", \"4\", \"5\", \"+\", \"+\")" >> $out
-  echo -e " syard(split(\"5 + 7 / 2\")) == List(\"5\", \"7\", \"2\", \"/\", \"+\")" >> $out
-  echo -e " syard(split(\"5 * 7 / 2\")) == List(\"5\", \"7\", \"\*\", \"2\", \"/\")" >> $out
-  echo -e " syard(split(\"3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3\")) == " >> $out
-  echo -e "         List(\"3\", \"4\", \"8\", \"\*\", \"5\", \"1\", \"-\", \"2\", \"3\", \"^\", \"^\", \"/\", \"+\")" >> $out
-  echo -e " " >> $out 
-  echo -e " compute(syard(split(\"3 + 4 * ( 2 - 1 )\"))) == 7" >> $out
-  echo -e " compute(syard(split(\"10 + 12 * 33\"))) == 406" >> $out
-  echo -e " compute(syard(split(\"( 5 + 7 ) * 2\"))) == 24" >> $out
-  echo -e " compute(syard(split(\"5 + 7 / 2\"))) == 8" >> $out
-  echo -e " compute(syard(split(\"5 * 7 / 2\"))) == 17" >> $out
-  echo -e " compute(syard(split(\"9 + 24 / ( 7 - 3 )\"))) == 15" >> $out
-  echo -e " compute(syard(split(\"4 ^ 3 ^ 2\"))) == 262144" >> $out
-  echo -e " compute(syard(split(\"4 ^ ( 3 ^ 2 )\"))) == 262144" >> $out
-  echo -e " compute(syard(split(\"( 4 ^ 3 ) ^ 2\"))) == 4096" >> $out
-  echo -e " compute(syard(split(\"( 3 + 1 ) ^ 2 ^ 3\"))) == 65536" >> $out
-  
-  if (scala_assert "postfix2.scala" "postfix_test9.scala")
-  then
-    echo -e "  --> success" >> $out
-  else
-    echo -e "  --> \n ONE TEST FAILED\n" >> $out
-  fi
-fi
-
--- a/pre_testing3/postfix_test7.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-import CW8a._
-
-
-assert(syard(split("3 + 4 * ( 2 - 1 )")) == List("3", "4", "2", "1", "-", "*", "+"))
-assert(syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) == List("3", "4", "5", "+", "+"))
-assert(syard(split("5 + 7 / 2")) == List("5", "7", "2", "/", "+"))
-assert(syard(split("5 * 7 / 2")) == List("5", "7", "*", "2", "/"))
--- a/pre_testing3/postfix_test8.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-import CW8a._
-
-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)
--- a/pre_testing3/postfix_test9.scala	Mon Nov 08 00:17:50 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-import CW8b._
-
-
-assert(syard(split("3 + 4 * ( 2 - 1 )")) == List("3", "4", "2", "1", "-", "*", "+"))
-assert(syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) == List("3", "4", "5", "+", "+"))
-assert(syard(split("5 + 7 / 2")) == List("5", "7", "2", "/", "+"))
-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)