--- a/README Thu Jan 13 12:55:03 2022 +0000
+++ b/README Mon Apr 11 23:55:27 2022 +0100
@@ -1,3 +1,12 @@
+https://github.com/5CCS2PEP/assignment2021scala-shrisiva02/issues/30
+
+Screenshot 2022-01-13 at 21.15.00
+
+problems with .vscode in files
+
+=============
+
+
TA meeting
https://web.microsoftstream.com/video/cec0d34d-77f5-4940-9bad-628416d4c521
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking1/collatz.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,51 @@
+// Core Part 1 about the 3n+1 conjecture
+//==================================
+
+// generate jar with
+// > scala -d collatz.jar collatz.scala
+
+object C1 { // for purposes of generating a jar
+
+def collatz(n: Long): Long =
+ if (n == 1) 0 else
+ if (n % 2 == 0) 1 + collatz(n / 2) else
+ 1 + collatz(3 * n + 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
+
+def is_hard(n: Long) : Boolean = is_pow(3 * n + 1)
+
+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)}")
+
+}
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking1/collatz_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,145 @@
+#!/bin/bash
+
+# to make the script fail safely
+set -euo pipefail
+
+
+out=${1:-output}
+
+echo -e "" > $out
+
+echo `date` | tee -a $out
+echo "" >> $out
+echo "Below is the feedback and provisional marks for your submission" >> $out
+echo "for the Core Part 1 (Scala). Please note all marks are provisional until" >> $out
+echo "ratified by the assessment board -- this is not an official" >> $out
+echo "results transcript." >> $out
+echo "" >> $out
+
+echo "The feedback for your submission for collatz.scala" >> $out
+echo "" >> $out
+
+# marks for core part 1
+marks=$(( 0 ))
+
+# 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 -nc -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
+}
+
+# purity test
+function scala_vars {
+ (sed 's/immutable/ok/g' c$out > cb$out;
+ egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' cb$out 2> /dev/null 1> /dev/null)
+}
+
+
+### compilation test
+
+echo -e "collatz.scala runs?" >> $out
+
+if (scala_compile collatz.scala)
+then
+ echo -e " --> success" >> $out
+ tsts0=$(( 0 ))
+else
+ echo -e " --> SCALA DID NOT RUN collatz.scala\n" >> $out
+ tsts0=$(( 1 ))
+fi
+
+# var, .par return, ListBuffer test
+#
+
+if [ $tsts0 -eq 0 ]
+then
+ echo -e "collatz.scala does not contain VARS, RETURNS etc?" >> $out
+
+ if (scala_vars collatz.scala)
+ then
+ echo -e " --> test failed\n" >> $out
+ tsts=$(( 1 ))
+ else
+ echo -e " --> success" >> $out
+ tsts=$(( 0 ))
+ fi
+else
+ tsts=$(( 1 ))
+fi
+
+
+echo >> $out
+
+### collatz tests
+
+if [ $tsts -eq 0 ]
+then
+ echo "collatz.scala tests:" | tee -a $out
+ echo " collatz(1) == 0" | tee -a $out
+ echo " collatz(6) == 8" | tee -a $out
+ echo " collatz(9) == 19" | tee -a $out
+ echo " collatz(9000) == 47" | tee -a $out
+
+ if (scala_assert "collatz.scala" "collatz_test1.scala")
+ then
+ echo " --> success" | tee -a $out
+ marks=$(( marks + 1 ))
+ else
+ echo " --> one of the tests failed" | tee -a $out
+ fi
+fi
+
+### collatz-max tests
+
+if [ $tsts -eq 0 ]
+then
+ echo " collatz_max(10) == (19, 9)" | tee -a $out
+ echo " collatz_max(100) == (118, 97)" | tee -a $out
+ echo " collatz_max(1000) == (178, 871)" | tee -a $out
+ echo " collatz_max(10000) == (261, 6171)" | tee -a $out
+ echo " collatz_max(100000) == (350, 77031)" | tee -a $out
+ echo " collatz_max(1000000) == (524, 837799)" | tee -a $out
+ # echo " collatz_max(2) == (1, 2) || collatz_max(2) == (0, 1)" | tee -a $out
+ echo " collatz_max(2) == (1, 2)" | tee -a $out
+ echo " collatz_max(77000) == (339, 52527)" | tee -a $out
+
+ if (scala_assert "collatz.scala" "collatz_test2.scala")
+ then
+ echo " --> success" | tee -a $out
+ marks=$(( marks + 1 ))
+ else
+ echo " --> one of the tests failed" | tee -a $out
+ fi
+fi
+
+### last-odd tests
+
+if [ $tsts -eq 0 ]
+then
+ echo " last_odd(113) == 85" | tee -a $out
+ echo " last_odd(84) == 21" | tee -a $out
+ echo " last_odd(605) == 341" | tee -a $out
+
+ if (scala_assert "collatz.scala" "collatz_test3.scala")
+ then
+ echo " --> success" | tee -a $out
+ marks=$(( marks + 1 ))
+ else
+ echo " --> one of the tests failed" | tee -a $out
+ fi
+fi
+
+
+
+## final marks
+echo >> $out
+echo "Overall mark for the Core Part 1 (Scala)" | tee -a $out
+echo " $marks" | tee -a $out
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking1/collatz_test1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,8 @@
+
+
+assert(C1.collatz(1) == 0)
+assert(C1.collatz(6) == 8)
+assert(C1.collatz(9) == 19)
+assert(C1.collatz(9000) == 47)
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking1/collatz_test2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,10 @@
+import C1._
+
+assert(collatz_max(10) == (19, 9))
+assert(collatz_max(100) == (118, 97))
+assert(collatz_max(1000) == (178, 871))
+assert(collatz_max(10000) == (261, 6171))
+assert(collatz_max(100000) == (350, 77031))
+assert(collatz_max(1000000) == (524, 837799))
+assert(collatz_max(2) == (1, 2))
+assert(collatz_max(77000) == (339, 52527))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking1/collatz_test3.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,4 @@
+
+assert(C1.last_odd(113) == 85)
+assert(C1.last_odd(84) == 21)
+assert(C1.last_odd(605) == 341)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking1/mk_core1 Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,26 @@
+#!/bin/bash
+set -euo pipefail
+
+trap "exit" INT
+
+files=${1:-*/core1}
+
+for sd in $files; do
+ echo -e "\n"
+ cd $sd
+ echo $sd
+ touch .
+ cp ../../../../../core_marking1/collatz_test.sh .
+ cp ../../../../../core_marking1/collatz_test1.scala .
+ cp ../../../../../core_marking1/collatz_test2.scala .
+ cp ../../../../../core_marking1/collatz_test3.scala .
+ ./collatz_test.sh output
+ rm collatz_test.sh
+ rm collatz_test1.scala
+ rm collatz_test2.scala
+ rm collatz_test3.scala
+ cd ..
+ cd ..
+done
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking2/docdiff.scala Mon Apr 11 23:55:27 2022 +0100
@@ -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_marking2/docdiff_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,171 @@
+#!/bin/zsh
+
+# to make the script fail safely
+set -euo pipefail
+
+
+out=${1:-output}
+
+echo "" > $out
+
+echo `date` >> $out
+echo -e "Below is the feedback and provisional marks for your submission" >> $out
+echo -e "for the Core Part 2 (Scala). Please note all marks are provisional until" >> $out
+echo -e "ratified by the assessment board -- this is not an official" >> $out
+echo -e "results transcript." >> $out
+echo -e "" >> $out
+
+echo -e "Below is the feedback for your submission docdiff.scala" >> $out
+echo -e "" >> $out
+
+# marks for C2 core part
+marks=$(( 0.0 ))
+
+
+# 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 -nc -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
+}
+
+# purity test
+function scala_vars {
+ (sed 's/immutable/ok/g' c$out > cb$out;
+ egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' cb$out 2> /dev/null 1> /dev/null)
+}
+
+
+
+### compilation test
+
+echo -e "docdiff.scala runs?" | tee -a $out
+
+if (scala_compile docdiff.scala)
+then
+ echo -e " --> success" | tee -a $out
+ tsts=$(( 0 ))
+else
+ echo -e " --> SCALA DID NOT RUN docdiff.scala\n" | tee -a $out
+ tsts=$(( 1 ))
+fi
+
+
+# var, .par return, ListBuffer test
+#
+
+if [ $tsts -eq 0 ]
+then
+ echo -e "docdiff.scala does not contain VARS, RETURNS etc?" | tee -a $out
+
+ if (scala_vars docdiff.scala)
+ then
+ echo -e " --> test failed\n" | tee -a $out
+ tsts=$(( 1 ))
+ else
+ echo -e " --> success" | tee -a $out
+ tsts=$(( 0 ))
+ fi
+else
+ tsts=$(( 1 ))
+fi
+
+echo >> $out
+
+
+### docdiff clean tests
+
+if [ $tsts -eq 0 ]
+then
+ echo -e "docdiff.scala tests:" | tee -a $out
+ echo -e " clean(\"ab a abc\") == List(\"ab\", \"a\", \"abc\")" | tee -a $out
+ echo -e " clean(\"ab*a abc1\") == List(\"ab\", \"a\", \"abc1\")" | tee -a $out
+
+ if (scala_assert "docdiff.scala" "docdiff_test1.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 0.5 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+### docdiff occurrences tests
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " occurrences(List(\"a\", \"b\", \"b\", \"c\", \"d\")) == " | tee -a $out
+ echo -e " Map(\"a\" -> 1, \"b\" -> 2, \"c\" -> 1, \"d\" -> 1)" | tee -a $out
+ echo -e " " | tee -a $out
+ echo -e " occurrences(List(\"d\", \"b\", \"d\", \"b\", \"d\")) == " | tee -a $out
+ echo -e " Map(\"d\" -> 3, \"b\" -> 2)" | tee -a $out
+ echo -e " " | tee -a $out
+ echo -e " occurrences(Nil) == Map() " | tee -a $out
+ echo -e " " | tee -a $out
+ echo -e " occurrences(List(\"b\", \"b\", \"b\", \"b\", \"b\")) == Map(\"b\" -> 5)" | tee -a $out
+
+ if (scala_assert "docdiff.scala" "docdiff_test2.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+### docdiff prod tests
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " val l1 = List(\"a\", \"b\", \"b\", \"c\", \"d\")" | tee -a $out
+ echo -e " val l2 = List(\"d\", \"b\", \"d\", \"b\", \"d\")" | tee -a $out
+ echo -e " " | tee -a $out
+ echo -e " prod(l1, l2) == 7 " | tee -a $out
+ echo -e " prod(l1, l1) == 7 " | tee -a $out
+ echo -e " prod(l2, l2) == 13 " | tee -a $out
+ echo -e " " | tee -a $out
+ echo -e " val l3 = List(\"1\", \"2\", \"3\", \"4\", \"5\")" | tee -a $out
+ echo -e " prod(l1, l3) == 0 " | tee -a $out
+
+ if (scala_assert "docdiff.scala" "docdiff_test3.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+### docdiff overlap tests
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " val l1 = List(\"a\", \"b\", \"b\", \"c\", \"d\")" | tee -a $out
+ echo -e " val l2 = List(\"d\", \"b\", \"d\", \"b\", \"d\")" | tee -a $out
+ echo -e " " | tee -a $out
+ echo -e " overlap(l1, l2) == 0.5384615384615384 " | tee -a $out
+ echo -e " overlap(l1, l1) == 1.0 " | tee -a $out
+ echo -e " overlap(l2, l2) == 1.0 " | tee -a $out
+
+ if (scala_assert "docdiff.scala" "docdiff_test4.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 0.5 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+
+## final marks
+echo -e "Overall mark for the Core Part 2 (Scala)" | tee -a $out
+printf " %0.1f\n" $marks | tee -a $out
+
+
+#echo -e " $marks" | tee -a $out
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking2/docdiff_test1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,4 @@
+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_marking2/docdiff_test2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,10 @@
+
+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))
+
+assert(occurrences(List("b", "b", "b", "b", "b")) == Map("b" -> 5))
+
+assert(occurrences(Nil) == Map())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking2/docdiff_test3.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,15 @@
+
+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)
+
+
+val urban_listA = List("a", "b", "b", "c", "d")
+val urban_listB = List("1", "2", "3", "4", "5")
+
+assert(prod(urban_listA, urban_listB) == 0)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking2/docdiff_test4.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,9 @@
+
+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_marking2/mk_core2 Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,29 @@
+#!/bin/bash
+set -euo pipefail
+
+
+trap "exit" INT
+
+files=${1:-*/core2}
+
+for sd in $files; do
+ echo -e "\n"
+ cd $sd
+ echo $sd
+ touch .
+ cp ../../../../../core_marking2/docdiff_test.sh .
+ cp ../../../../../core_marking2/docdiff_test1.scala .
+ cp ../../../../../core_marking2/docdiff_test2.scala .
+ cp ../../../../../core_marking2/docdiff_test3.scala .
+ cp ../../../../../core_marking2/docdiff_test4.scala .
+ ./docdiff_test.sh output
+ rm docdiff_test.sh
+ rm docdiff_test1.scala
+ rm docdiff_test2.scala
+ rm docdiff_test3.scala
+ rm docdiff_test4.scala
+ cd ..
+ cd ..
+done
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking3/mk_core3 Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,29 @@
+#!/bin/bash
+set -euo pipefail
+
+
+trap "exit" INT
+
+files=${1:-*/core3}
+
+for sd in $files; do
+ echo -e "\n"
+ cd $sd
+ echo $sd
+ touch .
+ cp ../../../../../core_marking3/postfix_test.sh .
+ cp ../../../../../core_marking3/postfix_test1.scala .
+ cp ../../../../../core_marking3/postfix_test2.scala .
+ cp ../../../../../core_marking3/postfix_test3.scala .
+ cp ../../../../../core_marking3/postfix_test4.scala .
+ ./postfix_test.sh output
+ rm postfix_test.sh
+ rm postfix_test1.scala
+ rm postfix_test2.scala
+ rm postfix_test3.scala
+ rm postfix_test4.scala
+ cd ..
+ cd ..
+done
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking3/postfix.scala Mon Apr 11 23:55:27 2022 +0100
@@ -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_marking3/postfix2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -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_marking3/postfix_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,201 @@
+#!/bin/zsh
+set -euo pipefail
+
+
+out=${1:-output}
+
+echo -e "" > $out
+
+echo `date` >> $out
+echo -e "Below is the feedback and provisional marks for your submission" >> $out
+echo -e "of the Core Part 3 (Scala). Please note all marks are provisional until" >> $out
+echo -e "ratified by the assessment board -- this is not an official" >> $out
+echo -e "results transcript." >> $out
+echo -e "" >> $out
+
+echo -e "Below is the feedback for your submission docdiff.scala" >> $out
+echo -e "" >> $out
+
+
+# marks for CW9 preliminary
+marks=$(( 0.0 ))
+
+
+# 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 {
+ (sed 's/immutable/ok/g' c$out > cb$out;
+ egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' cb$out 2> /dev/null 1> /dev/null)
+}
+
+
+# compilation test
+
+echo -e "postfix.scala runs?" | tee -a $out
+
+if (scala_compile postfix.scala)
+then
+ echo -e " --> success" | tee -a $out
+ tsts=$(( 0 ))
+else
+ echo -e " --> SCALA DID NOT RUN postfix.scala\n" | tee -a $out
+ tsts=$(( 1 ))
+fi
+
+
+
+# var, return, ListBuffer test
+#
+if [ $tsts -eq 0 ]
+ then
+ echo -e "postfix.scala does not contain VARS, RETURNS etc?" | tee -a $out
+
+ if (scala_vars postfix.scala)
+ then
+ echo -e " --> FAIL\n" | tee -a $out
+ tsts=$(( 1 ))
+ else
+ echo -e " --> success" | tee -a $out
+ tsts=$(( 0 ))
+ fi
+else
+ tsts=$(( 1 ))
+fi
+
+
+
+### postfix tests
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " syard(split(\"3 + 4 * ( 2 - 1 )\")) == List(\"3\", \"4\", \"2\", \"1\", \"-\", \"*\", \"+\")" | tee -a $out
+ echo -e " syard(split(\"( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )\")) == List(\"3\", \"4\", \"5\", \"+\", \"+\")" | tee -a $out
+ echo -e " syard(split(\"5 + 7 / 2\")) == List(\"5\", \"7\", \"2\", \"/\", \"+\")" | tee -a $out
+ echo -e " syard(split(\"5 * 7 / 2\")) == List(\"5\", \"7\", \"*\", \"2\", \"/\")" | tee -a $out
+
+ if (scala_assert "postfix.scala" "postfix_test1.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " compute(syard(split(\"3 + 4 * ( 2 - 1 )\"))) == 7" | tee -a $out
+ echo -e " compute(syard(split(\"10 + 12 * 33\"))) == 406" | tee -a $out
+ echo -e " compute(syard(split(\"( 5 + 7 ) * 2\"))) == 24" | tee -a $out
+ echo -e " compute(syard(split(\"5 + 7 / 2\"))) == 8" | tee -a $out
+ echo -e " compute(syard(split(\"5 * 7 / 2\"))) == 17" | tee -a $out
+ echo -e " compute(syard(split(\"9 + 24 / ( 7 - 3 )\"))) == 15" | tee -a $out
+
+ if (scala_assert "postfix.scala" "postfix_test2.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+
+
+### postfix2 tests
+
+echo -e "Below is the feedback for your submission postfix2.scala" >> $out
+echo -e "" >> $out
+
+# compilation test
+
+echo -e "postfix2.scala runs?" | tee -a $out
+
+if (scala_compile postfix2.scala)
+then
+ echo -e " --> success" | tee -a $out
+ tsts=$(( 0 ))
+else
+ echo -e " --> SCALA DID NOT RUN postfix2.scala\n" | tee -a $out
+ tsts=$(( 1 ))
+fi
+
+
+# var, return, ListBuffer test
+#
+if [ $tsts -eq 0 ]
+then
+ echo -e "postfix2.scala does not contain VARS, RETURNS etc?" | tee -a $out
+
+ if (scala_vars postfix2.scala)
+ then
+ echo -e " --> FAIL\n" | tee -a $out
+ tsts=$(( 1 ))
+ else
+ echo -e " --> success" | tee -a $out
+ tsts=$(( 0 ))
+ fi
+else
+ tsts=$(( 1 ))
+fi
+
+
+
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " syard(split(\"3 + 4 * ( 2 - 1 )\")) == List(\"3\", \"4\", \"2\", \"1\", \"-\", \"*\", \"+\")" | tee -a $out
+ echo -e " syard(split(\"( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )\")) == List(\"3\", \"4\", \"5\", \"+\", \"+\")" | tee -a $out
+ echo -e " syard(split(\"5 + 7 / 2\")) == List(\"5\", \"7\", \"2\", \"/\", \"+\")" | tee -a $out
+ echo -e " syard(split(\"5 * 7 / 2\")) == List(\"5\", \"7\", \"*\", \"2\", \"/\")" | tee -a $out
+ echo -e " syard(split(\"3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3\")) == " | tee -a $out
+ echo -e " List(\"3\", \"4\", \"8\", \"*\", \"5\", \"1\", \"-\", \"2\", \"3\", \"^\", \"^\", \"/\", \"+\")" | tee -a $out
+
+ if (scala_assert "postfix2.scala" "postfix_test3.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 0.5 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " compute(syard(split(\"3 + 4 * ( 2 - 1 )\"))) == 7" | tee -a $out
+ echo -e " compute(syard(split(\"10 + 12 * 33\"))) == 406" | tee -a $out
+ echo -e " compute(syard(split(\"( 5 + 7 ) * 2\"))) == 24" | tee -a $out
+ echo -e " compute(syard(split(\"5 + 7 / 2\"))) == 8" | tee -a $out
+ echo -e " compute(syard(split(\"5 * 7 / 2\"))) == 17" | tee -a $out
+ echo -e " compute(syard(split(\"9 + 24 / ( 7 - 3 )\"))) == 15" | tee -a $out
+ echo -e " compute(syard(split(\"4 ^ 3 ^ 2\"))) == 262144" | tee -a $out
+ echo -e " compute(syard(split(\"4 ^ ( 3 ^ 2 )\"))) == 262144" | tee -a $out
+ echo -e " compute(syard(split(\"( 4 ^ 3 ) ^ 2\"))) == 4096" | tee -a $out
+ echo -e " compute(syard(split(\"( 3 + 1 ) ^ 2 ^ 3\"))) == 65536" | tee -a $out
+
+ if (scala_assert "postfix2.scala" "postfix_test4.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 0.5 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+## final marks
+echo -e "Overall mark for the Core Part 3 (Scala)" | tee -a $out
+printf " %0.1f\n" $marks | tee -a $out
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking3/postfix_test1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -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_marking3/postfix_test2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -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_marking3/postfix_test3.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,9 @@
+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", "^", "^", "/", "+"))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core_marking3/postfix_test4.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,13 @@
+import C3b._
+
+
+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 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/cw03.pdf has changed
Binary file cws/cw04.pdf has changed
Binary file cws/cw05.pdf has changed
Binary file cws/cw06.pdf has changed
--- a/cws/disclaimer.sty Thu Jan 13 12:55:03 2022 +0000
+++ b/cws/disclaimer.sty Mon Apr 11 23:55:27 2022 +0100
@@ -4,8 +4,8 @@
\begin{itemize}
\item #1
\item Make sure the files you submit can be processed by just calling\\
- \mbox{\texttt{scala <<filename.scala>>}} on the commandline.\footnote{All
- major OSes, including Windows, have a commandline. So there is no
+ \mbox{\texttt{scala <<filename.scala>>}} on the command line.\footnote{All
+ major OSes, including Windows, have a command line. So there is no
good reason to not download Scala, install it and run it on your
own computer. Just do it!} Use the
template files provided and do not make any changes to arguments of
@@ -37,8 +37,8 @@
\begin{itemize}
\item Make sure the files you submit can be processed by just calling\\
- \mbox{\texttt{scala <<filename.scala>>}} on the commandline.\footnote{All
- major OSes, including Windows, have a commandline. So there is no
+ \mbox{\texttt{scala <<filename.scala>>}} on the command line.\footnote{All
+ major OSes, including Windows, have a command line. So there is no
good reason to not download Scala, install it and run it on your
own computer. Just do it!} Use the
template files provided and do not make any changes to arguments of
@@ -71,7 +71,7 @@
\begin{itemize}
\item Make sure the files you submit can be processed by just calling\\
- \mbox{\texttt{scala <<filename.scala>>}} on the commandline. Use the
+ \mbox{\texttt{scala <<filename.scala>>}} on the command line. Use the
template file provided and do not make any changes to arguments of
functions or to any types. You are free to implement any auxiliary
function you might need.
Binary file cws/main_cw01.pdf has changed
Binary file cws/main_cw02.pdf has changed
Binary file cws/main_cw03.pdf has changed
--- a/cws/main_cw03.tex Thu Jan 13 12:55:03 2022 +0000
+++ b/cws/main_cw03.tex Mon Apr 11 23:55:27 2022 +0100
@@ -176,6 +176,7 @@
5000000: 1.29659 secs.
\end{lstlisting}%$
+
\subsection*{Preliminaries}
The task is to implement a regular expression matcher that is based on
@@ -241,8 +242,10 @@
The alternative regular expressions comes in two versions: one is
binary (+ / \texttt{ALT}) and the other is n-ary ($\sum$ /
\texttt{ALTs}). The latter takes a list of regular expressions as
-arguments. In what follows we shall use $rs$ to stand for lists of
-regular expressions. The binary alternative can be seen as an abbreviation,
+argument. In what follows we shall use $rs$ to stand for lists of
+regular expressions. When the list is empty, we shall write $\sum\,[]$;
+if it is non-empty, we sometimes write $\sum\,[r_1,..., r_n]$.
+The binary alternative can be seen as an abbreviation,
that is $r_1 + r_2 \dn \sum\,[r_1, r_2]$. As a result we can ignore the
binary version and only implement the n-ary alternative.
@@ -267,7 +270,7 @@
\item[(2)] Implement a function, called \textit{der}, by recursion over
regular expressions. It takes a character and a regular expression
- as arguments and calculates the derivative of a regular expression according
+ as arguments and calculates the \emph{derivative} of a regular expression according
to the rules:
\begin{center}
@@ -337,8 +340,8 @@
\end{tabular}
\end{center}
- The first clause just states that empty lists cannot be further
- flattened. The second removes all $\ZERO$s from the list.
+ The first clause states that empty lists cannot be further
+ flattened. The second removes the first $\ZERO$ from the list and recurses.
The third is when the first regular expression is an \texttt{ALTs}, then
the content of this alternative should be spilled out and appended
with the flattened rest of the list. The last case is for all other
@@ -366,16 +369,16 @@
expressions $r_1,.. ,r_n$; then flatten the resulting list using
\texttt{flts}; finally remove all duplicates in this list (this can be
done in Scala using the function
-\texttt{\_.distinct}). \textcolor{red}{When you perform these
+\texttt{\_.distinct}). When you perform these
operations, you end up with three cases, namely where the list is
empty, contains a single element and ``otherwise''. These cases
- should be processed as follows}
+ should be processed as follows
\begin{center}
-\textcolor{red}{\begin{tabular}{l@{\hspace{4mm}}c@{\hspace{4mm}}ll}
+\begin{tabular}{l@{\hspace{4mm}}c@{\hspace{4mm}}ll}
$\sum\;[]$ & $\mapsto$ & $\ZERO$\\
$\sum\;[r]$ & $\mapsto$ & $r$\\
$\sum\;rs$ & $\mapsto$ & $\sum\;rs$ & ``otherwise''\\
-\end{tabular}}
+\end{tabular}
\end{center}
@@ -515,7 +518,7 @@
\begin{center}
\begin{tabular}{@{}cc@{}}
\multicolumn{2}{c}{Graph: $(a^*)^*\cdot b$ and strings
- $\underbrace{a\ldots a}_{n}$}\bigskip\\
+ $\underbrace{a\ldots a}_{n}$}\medskip\\
\begin{tikzpicture}
\begin{axis}[
@@ -531,7 +534,7 @@
scaled ticks=false,
axis lines=left,
width=6cm,
- height=5.0cm,
+ height=5.5cm,
legend entries={Python, Java 8, JavaScript, Swift, Dart},
legend pos=north west,
legend cell align=left]
@@ -557,7 +560,7 @@
scaled ticks=false,
axis lines=left,
width=6cm,
- height=5.0cm,
+ height=5.5cm,
legend entries={Java 9},
legend pos=north west]
\addplot[cyan,mark=*, mark options={fill=white}] table {re-java9.data};
Binary file cws/main_cw04.pdf has changed
Binary file cws/main_cw05.pdf has changed
--- a/main_marking1/drumb.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking1/drumb.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,7 +1,12 @@
-// Main Part about a really dumb investment strategy
-//======================================================
+// Main Part 1 about a really dumb investment strategy
+//=====================================================
+
-object CW6b {
+// generate jar with
+// > scala -d drumb.jar drumb.scala
+
+
+object M1 {
//two test portfolios
@@ -19,7 +24,7 @@
// strings for each line in the CSV-file.
def get_january_data(symbol: String, year: Int) : List[String] =
- Source.fromFile(symbol ++ ".csv")("ISO-8859-1").getLines.toList.filter(_.startsWith(year.toString))
+ Source.fromFile(symbol ++ ".csv")("ISO-8859-1").getLines().toList.filter(_.startsWith(year.toString))
//test cases
@@ -164,10 +169,28 @@
//test cases for the two portfolios given above
-//println("Real data: " + investment(rstate_portfolio, 1978 to 2019, 100))
-//println("Blue data: " + investment(blchip_portfolio, 1978 to 2019, 100))
+ println("Real data: " + investment(rstate_portfolio, 1978 to 2019, 100))
+ println("Blue data: " + investment(blchip_portfolio, 1978 to 2019, 100))
+
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- a/main_marking1/drumb_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking1/drumb_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/zsh
# to make the script fail safely
set -euo pipefail
@@ -16,7 +16,7 @@
echo -e "" >> $out
# marks for CW6 main part
-marks=$(( 0 ))
+marks=$(( 0.0 ))
echo -e "" >> $out
@@ -38,10 +38,11 @@
# purity test
+function scala_vars {
+ (sed 's/immutable/ok/g' c$out > cb$out;
+ egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' cb$out 2> /dev/null 1> /dev/null)
+}
-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 "drumb.scala runs?" | tee -a $out
@@ -76,8 +77,6 @@
echo >> $out
-sleep 15
-
### get january tests
if [ $tsts -eq 0 ]
@@ -88,7 +87,7 @@
if (scala_assert "drumb.scala" "drumb_test1.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 0.5 ))
else
echo -e " --> TEST FAILED\n" | tee -a $out
fi
@@ -104,7 +103,7 @@
if (scala_assert "drumb.scala" "drumb_test2.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> TEST FAILED\n" | tee -a $out
fi
@@ -126,7 +125,7 @@
if (scala_assert "drumb.scala" "drumb_test3.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> TEST FAILED\n" | tee -a $out
fi
@@ -144,7 +143,7 @@
if (scala_assert "drumb.scala" "drumb_test4.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> TEST FAILED\n" | tee -a $out
fi
@@ -166,7 +165,7 @@
if (scala_assert "drumb.scala" "drumb_test5.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> TEST FAILED\n" | tee -a $out
fi
@@ -184,7 +183,7 @@
if (scala_assert "drumb.scala" "drumb_test6.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> TEST FAILED\n" | tee -a $out
fi
@@ -210,7 +209,7 @@
if (scala_assert "drumb.scala" "drumb_test7.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 0.5 ))
else
echo -e " --> TEST FAILED\n" | tee -a $out
fi
@@ -219,7 +218,6 @@
## final marks
echo -e "" >> $out
echo -e "Overall mark for Main Part 1 (Scala)" | tee -a $out
-echo -e "$marks" | tee -a $out
+printf " %0.1f\n" $marks | tee -a $out
-sleep 10
--- a/main_marking1/drumb_test1.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking1/drumb_test1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,12 +1,5 @@
-/*def myassert(cond : => Boolean) = {
- try {
- assert(cond)
- } catch {
- case _ : Throwable => System.exit(1)
- }
-}
-*/
+
-assert(CW6b.get_january_data("GOOG", 1980) == List())
-assert(CW6b.get_january_data("GOOG", 2010).head == "2010-01-04,312.204773")
+assert(M1.get_january_data("GOOG", 1980) == List())
+assert(M1.get_january_data("GOOG", 2010).head == "2010-01-04,312.204773")
--- a/main_marking1/drumb_test2.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking1/drumb_test2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,12 +1,4 @@
-/*def myassert(cond : => Boolean) = {
- try {
- assert(cond)
- } catch {
- case _ : Throwable => System.exit(1)
- }
-}
-*/
-assert(CW6b.get_first_price("GOOG", 1980) == None)
-assert(CW6b.get_first_price("GOOG", 2010) == Some(312.204773))
+assert(M1.get_first_price("GOOG", 1980) == None)
+assert(M1.get_first_price("GOOG", 2010) == Some(312.204773))
--- a/main_marking1/drumb_test3.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking1/drumb_test3.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,17 +1,11 @@
-/*def myassert(cond : => Boolean) = {
- try {
- assert(cond)
- } catch {
- case _ : Throwable => System.exit(1)
- }
-}
-*/
-assert(CW6b.get_prices(List("BIDU"), 2004 to 2008) ==
+import M1._
+
+assert(get_prices(List("BIDU"), 2004 to 2008) ==
List(List(None), List(None), List(Some(6.35)),
List(Some(12.241)), List(Some(38.188))))
-assert(CW6b.get_prices(List("GOOG", "AAPL"), 2010 to 2012) ==
+assert(get_prices(List("GOOG", "AAPL"), 2010 to 2012) ==
List(List(Some(312.204773), Some(26.782711)),
List(Some(301.0466), Some(41.244694)),
List(Some(331.462585), Some(51.464207))))
--- a/main_marking1/drumb_test4.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking1/drumb_test4.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,6 +1,6 @@
-assert(CW6b.get_delta(None, None) == None)
-assert(CW6b.get_delta(Some(50.0), None) == None)
-assert(CW6b.get_delta(None, Some(100.0)) == None)
-assert(CW6b.get_delta(Some(50.0), Some(100.0)) == Some(1.0))
+assert(M1.get_delta(None, None) == None)
+assert(M1.get_delta(Some(50.0), None) == None)
+assert(M1.get_delta(None, Some(100.0)) == None)
+assert(M1.get_delta(Some(50.0), Some(100.0)) == Some(1.0))
--- a/main_marking1/drumb_test5.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking1/drumb_test5.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,18 +1,10 @@
-/*def myassert(cond : => Boolean) = {
- try {
- assert(cond)
- } catch {
- case _ : Throwable => System.exit(1)
- }
-}
-*/
-// get_prices(List("GOOG", "AAPL"), 2010 to 2012)
+
val urban_prices = List(List(Some(312.204773), Some(26.782711)),
List(Some(301.0466), Some(41.244694)),
List(Some(331.462585), Some(51.464207)))
-assert(CW6b.get_deltas(urban_prices) == List(List(Some(-0.03573991804411003), Some(0.539974575389325)),
+assert(M1.get_deltas(urban_prices) == List(List(Some(-0.03573991804411003), Some(0.539974575389325)),
List(Some(0.10103414222249969), Some(0.24777764141006836))))
@@ -22,6 +14,6 @@
List(Some(38.188)))
-assert(CW6b.get_deltas(urban_prices2) == List(List(None), List(None),
+assert(M1.get_deltas(urban_prices2) == List(List(None), List(None),
List(Some(0.9277165354330709)),
List(Some(2.119679764725104))))
--- a/main_marking1/drumb_test6.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking1/drumb_test6.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,18 +1,9 @@
-//val urban_deltas = get_deltas(get_prices(List("GOOG", "AAPL"), 2010 to 2012))
-/*
-def myassert(cond : => Boolean) = {
- try {
- assert(cond)
- } catch {
- case _ : Throwable => System.exit(1)
- }
-}
-*/
+
val ds_urban = List(List(Some(-0.03573991804411003), Some(0.539974575389325)),
List(Some(0.10103414222249969), Some(0.24777764141006836)))
-assert(CW6b.yearly_yield(ds_urban, 100, 0) == 125)
-assert(CW6b.yearly_yield(ds_urban, 100, 1) == 117)
+assert(M1.yearly_yield(ds_urban, 100, 0) == 125)
+assert(M1.yearly_yield(ds_urban, 100, 1) == 117)
--- a/main_marking1/drumb_test7.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking1/drumb_test7.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,24 +1,16 @@
-/*
-def myassert(cond : => Boolean) = {
- try {
- assert(cond)
- } catch {
- case _ : Throwable => System.exit(1)
- }
-}
-*/
+
-assert(CW6b.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2000, 100) == 100)
-assert(CW6b.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2001, 100) == 27)
-assert(CW6b.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2002, 100) == 42)
-assert(CW6b.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2003, 100) == 27)
-assert(CW6b.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2004, 100) == 38)
+assert(M1.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2000, 100) == 100)
+assert(M1.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2001, 100) == 27)
+assert(M1.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2002, 100) == 42)
+assert(M1.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2003, 100) == 27)
+assert(M1.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2004, 100) == 38)
// 113
-assert((112 to 114).contains(CW6b.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2005, 100)))
+assert((112 to 114).contains(M1.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2005, 100)))
// 254
-assert((252 to 256).contains(CW6b.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2006, 100)))
+assert((252 to 256).contains(M1.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2006, 100)))
// 349
-assert((346 to 352).contains(CW6b.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2007, 100)))
+assert((346 to 352).contains(M1.investment(List("GOOG", "AAPL", "BIDU"), 2000 to 2007, 100)))
//11504
-assert((11389 to 11619).contains(CW6b.investment(List("GOOG", "AAPL", "BIDU"), 1990 to 2017, 100)))
+assert((11389 to 11619).contains(M1.investment(List("GOOG", "AAPL", "BIDU"), 1990 to 2017, 100)))
--- a/main_marking1/mk Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-#!/bin/sh
-###set -e
-
-trap "exit" INT
-
-files=${1:-*/main1}
-
-for sd in $files; do
- cd $sd
- echo $sd
- sleep 5
- touch .
- cp ../../../../../main_marking1/drumb_test.sh .
- cp ../../../../../main_marking1/drumb_test1.scala .
- cp ../../../../../main_marking1/drumb_test2.scala .
- cp ../../../../../main_marking1/drumb_test3.scala .
- cp ../../../../../main_marking1/drumb_test4.scala .
- cp ../../../../../main_marking1/drumb_test5.scala .
- cp ../../../../../main_marking1/drumb_test6.scala .
- cp ../../../../../main_marking1/drumb_test7.scala .
- cp ../../../../../main_marking1/*.csv .
- ./drumb_test.sh output
- rm drumb_test.sh
- rm drumb_test1.scala
- rm drumb_test2.scala
- rm drumb_test3.scala
- rm drumb_test4.scala
- rm drumb_test5.scala
- rm drumb_test6.scala
- rm drumb_test7.scala
- rm *.csv
- cd ..
- cd ..
-done
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking1/mk_main1 Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,36 @@
+#!/bin/bash
+###set -e
+
+trap "exit" INT
+
+files=${1:-*/main1}
+
+for sd in $files; do
+ echo -e "\n"
+ cd $sd
+ echo $sd
+ touch .
+ cp ../../../../../main_marking1/drumb_test.sh .
+ cp ../../../../../main_marking1/drumb_test1.scala .
+ cp ../../../../../main_marking1/drumb_test2.scala .
+ cp ../../../../../main_marking1/drumb_test3.scala .
+ cp ../../../../../main_marking1/drumb_test4.scala .
+ cp ../../../../../main_marking1/drumb_test5.scala .
+ cp ../../../../../main_marking1/drumb_test6.scala .
+ cp ../../../../../main_marking1/drumb_test7.scala .
+ cp ../../../../../main_marking1/*.csv .
+ ./drumb_test.sh output
+ rm drumb_test.sh
+ rm drumb_test1.scala
+ rm drumb_test2.scala
+ rm drumb_test3.scala
+ rm drumb_test4.scala
+ rm drumb_test5.scala
+ rm drumb_test6.scala
+ rm drumb_test7.scala
+ rm *.csv
+ cd ..
+ cd ..
+done
+
+
--- a/main_marking2/danube_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking2/danube_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -37,9 +37,9 @@
}
# purity test
-
function scala_vars {
- (egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' c$out 2> /dev/null 1> /dev/null)
+ (sed 's/immutable/ok/g' c$out > cb$out;
+ egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' cb$out 2> /dev/null 1> /dev/null)
}
@@ -111,6 +111,9 @@
echo -e " " | tee -a $out
echo -e " good_ratings.length == 48580 " | tee -a $out
echo -e " movie_names.length == 9742 " | tee -a $out
+ echo -e " " | tee -a $out
+ echo -e " val r_elems = List((\"1\",\"1\"), (\"1\",\"3\"), (\"1\",\"6\"), (\"1\",\"47\")) " | tee -a $out
+ echo -e " r_elems.forall(good_ratings.contains(_)) == true" | tee -a $out
if (scala_assert "danube.scala" "danube_test2.scala")
then
@@ -201,57 +204,6 @@
fi
fi
-### danube most_recommended 1
-gd=$(( 0 ))
-
-if [ $tsts -eq 0 ]
-then
- echo -e " val rmap = Map(\"1\" -> List(\"b\", \"a\"), " | tee -a $out
- echo -e " \"2\" -> List(\"y\", \"x\"), " | tee -a $out
- echo -e " \"3\" -> List(\"c\", \"a\")) " | tee -a $out
- echo -e " val nmap = Map(\"a\" -> \"A\", \"b\" -> \"B\", \"c\" -> \"C\", " | tee -a $out
- echo -e " \"x\" -> \"X\", \"y\" -> \"Y\") " | tee -a $out
- echo -e " most_recommended(rmap, nmap).toSet == " | tee -a $out
- echo -e " Set((\"A\",2), (\"B\",1), (\"C\",1), (\"X\",1), (\"Y\",1)) " | tee -a $out
-
- if (scala_assert "danube.scala" "danube_test7a.scala")
- then
- echo -e " --> success (0.5% Marks)" | tee -a $out
- marks=$(( marks + 0.5 ))
- else
- echo -e " --> TEST FAILED\n" | tee -a $out
- gd=$(( 1 ))
- fi
-fi
-
-### danube most_recommended 2
-
-sleep 10
-
-if [ $gd -eq 0 ]
-then
- if [ $tsts -eq 0 ]
- then
- echo -e " most_recommended(ratings_map, movie_map) runs within allocated time? " | tee -a $out
- START=$(date +%s)
-
- if (scala_assert_thirty "danube.scala" "danube_test7b.scala")
- then
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> success (0.5% Marks)" | tee -a $out
- marks=$(( marks + 0.5 ))
- else
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> TEST FAILED\n" | tee -a $out
- fi
- fi
-fi
-
-sleep 10
## final marks
--- a/main_marking2/danube_test1.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking2/danube_test1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,5 +1,5 @@
-import CW7b._
+import M2._
val urban_mov_url = """https://nms.kcl.ac.uk/christian.urban/movies.csv"""
//val urban_mov_url = """http://localhost:8000/movies.csv"""
--- a/main_marking2/danube_test2.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking2/danube_test2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -2,7 +2,7 @@
import io.Source
import scala.util._
-import CW7b._
+import M2._
def urban_get_csv_file(name: String) : List[String] = {
val csv = Source.fromFile(name)
@@ -12,8 +12,11 @@
val urban_ratings = urban_get_csv_file("ratings.csv")
val urban_movies = urban_get_csv_file("movies.csv")
+val urban_res1 = process_ratings(urban_ratings)
+val urban_rat_elems = List(("1","1"), ("1","3"), ("1","6"), ("1","47"))
-assert(process_ratings(urban_ratings).length == 48580)
+assert(urban_res1.length == 48580)
+assert(urban_rat_elems.forall(urban_res1.contains(_)))
assert(process_movies(urban_movies).length == 9742)
--- a/main_marking2/danube_test3.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking2/danube_test3.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW7b._
+import M2 ._
// first test
--- a/main_marking2/danube_test4.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking2/danube_test4.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,7 +1,7 @@
// first test
-import CW7b._
+import M2._
def urban_groupById(ratings: List[(String, String)]) =
ratings.groupBy(_._1).view.mapValues(_.map(_._2)).toMap
--- a/main_marking2/danube_test5.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking2/danube_test5.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,7 +1,7 @@
// first test
-import CW7b._
+import M2._
def urban_groupById(ratings: List[(String, String)]) =
ratings.groupBy(_._1).view.mapValues(_.map(_._2)).toMap
--- a/main_marking2/danube_test6.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking2/danube_test6.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,5 +1,5 @@
-import CW7b._
+import M2._
// first test
--- a/main_marking2/danube_test7a.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-
-import CW7b._
-
-val urban_recs =
- Map("1" -> List("b", "a"),
- "2" -> List("y", "x"),
- "3" -> List("a", "c"))
-
-val urban_names = Map("a" -> "A", "b" -> "B", "c" -> "C", "x" -> "X", "y" -> "Y")
-
-assert(most_recommended(urban_recs, urban_names).toSet ==
- Set(("A",2), ("B",1), ("C",1), ("X",1), ("Y",1)))
-
--- a/main_marking2/danube_test7b.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-
-import CW7b._
-
-def urban_groupById(ratings: List[(String, String)]) =
- ratings.groupBy(_._1).view.mapValues(_.map(_._2)).toMap
-
-def urban_get_csv_file(name: String) : List[String] = {
- import io.Source
- import scala.util._
- val csv = Source.fromFile(name)
- csv.mkString.split("\n").toList.drop(1)
-}
-
-def urban_process_ratings(lines: List[String]) : List[(String, String)] = {
- for (cols <- lines.map(_.split(",").toList);
- if (cols(2).toFloat >= 4)) yield (cols(0), cols(1))
-}
-
-def urban_process_movies(lines: List[String]) : List[(String, String)] = {
- for (cols <- lines.map(_.split(",").toList)) yield (cols(0), cols(1))
-}
-
-
-val urban_good_ratings = process_ratings(urban_get_csv_file("ratings.csv"))
-val urban_movie_names = process_movies(urban_get_csv_file("movies.csv")).toMap
-
-val urban_ratings_map = urban_groupById(urban_good_ratings)
-
-def urban_test() =
- { most_recommended(urban_ratings_map, urban_movie_names) ; true }
-
-assert(urban_test())
-
-
--- a/main_marking2/mk Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-#!/bin/sh
-###set -e
-
-trap "exit" INT
-
-files=${1:-*/main2}
-
-
-for sd in $files; do
- cd $sd
- echo $sd
- touch .
- cp ../../../../../main_marking2/danube_test.sh .
- cp ../../../../../main_marking2/danube_test1.scala .
- cp ../../../../../main_marking2/danube_test2.scala .
- cp ../../../../../main_marking2/danube_test3.scala .
- cp ../../../../../main_marking2/danube_test4.scala .
- cp ../../../../../main_marking2/danube_test5.scala .
- cp ../../../../../main_marking2/danube_test6.scala .
- cp ../../../../../main_marking2/danube_test7a.scala .
- cp ../../../../../main_marking2/danube_test7b.scala .
- cp ../../../../../main_marking2/movies.csv .
- cp ../../../../../main_marking2/ratings.csv .
- ./danube_test.sh output
- rm danube_test.sh
- rm danube_test1.scala
- rm danube_test2.scala
- rm danube_test3.scala
- rm danube_test4.scala
- rm danube_test5.scala
- rm danube_test6.scala
- rm danube_test7a.scala
- rm danube_test7b.scala
- rm ratings.csv
- rm movies.csv
- cd ..
- cd ..
-done
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking2/mk_main2 Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,37 @@
+#!/bin/bash
+###set -e
+
+trap "exit" INT
+
+files=${1:-*/main2}
+
+
+for sd in $files; do
+ echo -e "\n"
+ cd $sd
+ echo $sd
+ touch .
+ cp ../../../../../main_marking2/danube_test.sh .
+ cp ../../../../../main_marking2/danube_test1.scala .
+ cp ../../../../../main_marking2/danube_test2.scala .
+ cp ../../../../../main_marking2/danube_test3.scala .
+ cp ../../../../../main_marking2/danube_test4.scala .
+ cp ../../../../../main_marking2/danube_test5.scala .
+ cp ../../../../../main_marking2/danube_test6.scala .
+ cp ../../../../../main_marking2/movies.csv .
+ cp ../../../../../main_marking2/ratings.csv .
+ ./danube_test.sh output
+ rm danube_test.sh
+ rm danube_test1.scala
+ rm danube_test2.scala
+ rm danube_test3.scala
+ rm danube_test4.scala
+ rm danube_test5.scala
+ rm danube_test6.scala
+ rm ratings.csv
+ rm movies.csv
+ cd ..
+ cd ..
+done
+
+
--- a/main_marking3/mk Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-#!/bin/sh
-###set -e
-
-trap "exit" INT
-
-files=${1:-*/main3}
-
-for sd in $files; do
- cd $sd
- echo $sd
- touch .
- cp ../../../../../main_marking3/re_test.sh .
- cp ../../../../../main_marking3/re_test1.scala .
- cp ../../../../../main_marking3/re_test2.scala .
- cp ../../../../../main_marking3/re_test3.scala .
- cp ../../../../../main_marking3/re_test4.scala .
- cp ../../../../../main_marking3/re_test5.scala .
- cp ../../../../../main_marking3/re_test6.scala .
- cp ../../../../../main_marking3/re_test7.scala .
- ./re_test.sh output
- rm re_test.sh
- rm re_test1.scala
- rm re_test2.scala
- rm re_test3.scala
- rm re_test4.scala
- rm re_test5.scala
- rm re_test6.scala
- rm re_test7.scala
- cd ..
- cd ..
-done
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking3/mk_main3 Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,36 @@
+#!/bin/bash
+###set -e
+
+trap "exit" INT
+
+files=${1:-*/main3}
+
+for sd in $files; do
+ echo -e "\n"
+ cd $sd
+ echo $sd
+ touch .
+ cp ../../../../../main_marking3/re_test.sh .
+ cp ../../../../../main_marking3/re_test1.scala .
+ cp ../../../../../main_marking3/re_test2.scala .
+ cp ../../../../../main_marking3/re_test3.scala .
+ cp ../../../../../main_marking3/re_test3a.scala .
+ cp ../../../../../main_marking3/re_test4.scala .
+ cp ../../../../../main_marking3/re_test5.scala .
+ cp ../../../../../main_marking3/re_test6.scala .
+ cp ../../../../../main_marking3/re_test7.scala .
+ ./re_test.sh output
+ rm re_test.sh
+ rm re_test1.scala
+ rm re_test2.scala
+ rm re_test3.scala
+ rm re_test3a.scala
+ rm re_test4.scala
+ rm re_test5.scala
+ rm re_test6.scala
+ rm re_test7.scala
+ cd ..
+ cd ..
+done
+
+
--- a/main_marking3/re.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking3/re.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,23 +1,25 @@
-// Core Part about Regular Expression Matching
+// Main Part 3 about Regular Expression Matching
//=============================================
-object CW8c {
+object M3 {
// Regular Expressions
abstract class Rexp
case object ZERO extends Rexp
case object ONE extends Rexp
case class CHAR(c: Char) extends Rexp
-case class ALT(r1: Rexp, r2: Rexp) extends Rexp
-case class SEQ(r1: Rexp, r2: Rexp) extends Rexp
-case class STAR(r: Rexp) extends Rexp
+case class 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
+
+
+//the usual binary choice can be defined in terms of ALTs
+def ALT(r1: Rexp, r2: Rexp) = ALTs(List(r1, r2))
// some convenience for typing in regular expressions
-
import scala.language.implicitConversions
import scala.language.reflectiveCalls
-
def charlist2rexp(s: List[Char]): Rexp = s match {
case Nil => ONE
case c::Nil => CHAR(c)
@@ -49,7 +51,7 @@
case ZERO => false
case ONE => true
case CHAR(_) => false
- case ALT(r1, r2) => nullable(r1) || nullable(r2)
+ case ALTs(rs) => rs.exists(nullable)
case SEQ(r1, r2) => nullable(r1) && nullable(r2)
case STAR(_) => true
}
@@ -63,25 +65,39 @@
case ZERO => ZERO
case ONE => ZERO
case CHAR(d) => if (c == d) ONE else ZERO
- case ALT(r1, r2) => ALT(der(c, r1), der(c, r2))
+ case 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 STAR(r1) => SEQ(der(c, r1), STAR(r1))
}
-// (3) Complete the simp function according to
+
+// (3) Implement the flatten function flts. It
+// deletes 0s from a list of regular expressions
+// and also 'spills out', or flattens, nested
+// ALTernativeS.
+
+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) Complete the simp function according to
// the specification given in the coursework; this
// function simplifies a regular expression from
// the inside out, like you would simplify arithmetic
// expressions; however it does not simplify inside
// STAR-regular expressions.
+
def simp(r: Rexp) : Rexp = r match {
- case ALT(r1, r2) => (simp(r1), simp(r2)) match {
- case (ZERO, r2s) => r2s
- case (r1s, ZERO) => r1s
- case (r1s, r2s) => if (r1s == r2s) r1s else ALT (r1s, r2s)
+ case 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
@@ -93,8 +109,9 @@
case r => r
}
+simp(ALT(ONE | CHAR('a'), CHAR('a') | ONE))
-// (4) Complete the two functions below; the first
+// (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
@@ -108,7 +125,7 @@
// main matcher function
def matcher(r: Rexp, s: String) = nullable(ders(s.toList, r))
-// (5) Complete the size function for regular
+// (6) Complete the size function for regular
// expressions according to the specification
// given in the coursework.
@@ -117,7 +134,7 @@
case ZERO => 1
case ONE => 1
case CHAR(_) => 1
- case ALT(r1, r2) => 1 + size(r1) + size (r2)
+ case ALTs(rs) => 1 + rs.map(size).sum
case SEQ(r1, r2) => 1 + size(r1) + size (r2)
case STAR(r1) => 1 + size(r1)
}
@@ -130,18 +147,21 @@
//matcher(("a" ~ "b") ~ "c", "ab") // => false
// the supposedly 'evil' regular expression (a*)* b
-val EVIL = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
+// val EVIL = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
-//matcher(EVIL, "a" * 1000 ++ "b") // => true
-//matcher(EVIL, "a" * 1000) // => false
+//println(matcher(EVIL, "a" * 1000 ++ "b")) // => true
+//println(matcher(EVIL, "a" * 1000)) // => false
// size without simplifications
-//size(der('a', der('a', EVIL))) // => 28
-//size(der('a', der('a', der('a', EVIL)))) // => 58
+//println(size(der('a', der('a', EVIL)))) // => 28
+//println(size(der('a', der('a', der('a', EVIL))))) // => 58
// size with simplification
-//size(simp(der('a', der('a', EVIL)))) // => 8
-//size(simp(der('a', der('a', der('a', EVIL))))) // => 8
+//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
// 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
@@ -155,11 +175,11 @@
val start = System.nanoTime()
for (j <- 1 to i) code
val end = System.nanoTime()
- (end - start)/(i * 1.0e9)
+ "%.5f".format((end - start)/(i * 1.0e9))
}
//for (i <- 0 to 5000000 by 500000) {
-// println(i + " " + "%.5f".format(time_needed(2, matcher(EVIL, "a" * i))) + " secs.")
+// println(s"$i ${time_needed(2, matcher(EVIL, "a" * i))} secs.")
//}
// another "power" test case
@@ -169,7 +189,7 @@
//
// SEQ(SEQ(SEQ(..., ONE | ONE) , ONE | ONE), ONE | ONE)
//
-// where SEQ is nested 100 times.
+// where SEQ is nested 50 times.
--- a/main_marking3/re_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking3/re_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/zsh
# to make the script fail safely
set -euo pipefail
@@ -16,7 +16,7 @@
echo -e "" >> $out
# marks for CW8
-marks=$(( 0 ))
+marks=$(( 0.0 ))
# compilation tests
@@ -35,10 +35,11 @@
}
# purity test
+function scala_vars {
+ (sed 's/immutable/ok/g' c$out > cb$out;
+ egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' cb$out 2> /dev/null 1> /dev/null)
+}
-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)
-}
echo -e "" >> $out
echo -e "Below is the feedback for your submission re.scala" >> $out
@@ -97,7 +98,7 @@
if (scala_assert "re.scala" "re_test1.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 0.5 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -131,7 +132,7 @@
if (scala_assert "re.scala" "re_test2.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -161,12 +162,33 @@
if (scala_assert "re.scala" "re_test3.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
fi
+### re3a flts test
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " flts(Nil) == Nil" | tee -a $out
+ echo -e " flts(ZERO::ZERO::Nil) == Nil" | tee -a $out
+ echo -e " flts(ZERO::ONE::ZERO::ONE::Nil) == List(ONE, ONE)" | tee -a $out
+ echo -e " flts(ONE::ALTs(List(ONE))::ONE::Nil) == List(ONE, ONE, ONE)" | tee -a $out
+ echo -e " flts(ONE::ALTs(List(ONE))::ONE::ALTs(List(ONE))::Nil) == List(ONE, ONE, ONE, ONE)" | tee -a $out
+
+ if (scala_assert "re.scala" "re_test3a.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+
+
### re4 test
if [ $tsts -eq 0 ]
@@ -191,7 +213,7 @@
if (scala_assert "re.scala" "re_test4.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -211,7 +233,7 @@
if (scala_assert "re.scala" "re_test5.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 0.5 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -219,7 +241,6 @@
### re6 'power' test 1
-sleep 5
if [ $tsts -eq 0 ]
then
@@ -240,7 +261,7 @@
DIFF=$(( $END - $START ))
echo " This test ran for $DIFF seconds" | tee -a $out
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 0.5 ))
else
END=$(date +%s)
DIFF=$(( $END - $START ))
@@ -249,7 +270,6 @@
fi
fi
-sleep 10
### re7 'power' test 2
@@ -266,7 +286,7 @@
DIFF=$(( $END - $START ))
echo " This test ran for $DIFF seconds" | tee -a $out
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 0.5 ))
else
END=$(date +%s)
DIFF=$(( $END - $START ))
@@ -275,10 +295,11 @@
fi
fi
-sleep 10
+
## final marks
echo -e "Overall mark for Main Part 3 (Scala)" | tee -a $out
-echo -e "$marks" | tee -a $out
+printf " %0.1f\n" $marks | tee -a $out
+
--- a/main_marking3/re_test1.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking3/re_test1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW8c._
+import M3._
assert(nullable(ZERO) == false)
assert(nullable(ONE) == true)
--- a/main_marking3/re_test2.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking3/re_test2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW8c._
+import M3._
assert(der('a', ZERO | ONE) == (ZERO | ZERO))
assert(der('a', (CHAR('a') | ONE) ~ CHAR('a')) == ALT((ONE | ZERO) ~ CHAR('a'), ONE))
--- a/main_marking3/re_test3.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking3/re_test3.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW8c._
+import M3._
assert(simp(ZERO | ONE) == ONE)
@@ -16,6 +16,7 @@
assert(simp((ZERO | ((ZERO | ZERO) | (ZERO | ZERO))) ~ ((ONE | ZERO) | ONE ) ~ (CHAR('a'))) == ZERO)
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'), CHAR('a') | ONE))
+assert(simp(ALT(ONE | CHAR('a'), CHAR('a') | ONE)) == ALT(ONE, CHAR('a')))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking3/re_test3a.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,8 @@
+import M3._
+
+
+assert(flts(Nil) == Nil)
+assert(flts(ZERO::ZERO::Nil) == Nil)
+assert(flts(ZERO::ONE::ZERO::ONE::Nil) == List(ONE, ONE))
+assert(flts(ONE::ALTs(List(ONE))::ONE::Nil) == List(ONE, ONE, ONE))
+assert(flts(ONE::ALTs(List(ONE))::ONE::ALTs(List(ONE))::Nil) == List(ONE, ONE, ONE, ONE))
--- a/main_marking3/re_test4.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking3/re_test4.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW8c._
+import M3._
val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
--- a/main_marking3/re_test5.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking3/re_test5.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW8c._
+import M3._
val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
--- a/main_marking3/re_test6.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking3/re_test6.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW8c._
+import M3._
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)
--- a/main_marking3/re_test7.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking3/re_test7.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW8c._
+import M3._
val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
--- a/main_marking4/knight1.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking4/knight1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,13 +1,119 @@
-// Part 1 about finding and counting Knight's tours
-//==================================================
+// Main Part 4 about finding Knight's tours
+//==========================================
+import scala.annotation.tailrec
+
+
+object M4a {
-object CW9a { // for preparing the jar
+// 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.
+
+
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.
-// for measuring time in the JAR
+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
def time_needed[T](code: => T) : T = {
val start = System.nanoTime()
val result = code
@@ -16,6 +122,14 @@
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()
@@ -27,151 +141,7 @@
}
}
-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, _))
-
-// 1 mark
-
-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)))
-
-// 2 marks
-
-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)
- }
-}
*/
-// 1 mark
-
-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)
-
-
-// 1 mark
-
-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))
-
-
-
-
-
-}
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking4/knight1_test1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,9 @@
+import M4a._
+
+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)
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking4/knight1_test2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,13 @@
+import M4a._
+
+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, Nil, (0,1)) == List((1,3), (2,2), (2,0)))
+assert(legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6)))
+assert(legal_moves(1, Nil, (0,0)) == Nil)
+assert(legal_moves(2, Nil, (0,0)) == Nil)
+assert(legal_moves(3, Nil, (0,0)) == List((1,2), (2,1)))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking4/knight1_test3a.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,14 @@
+import M4a._
+
+def count_all_tours_urban(dim: Int) = {
+ for (i <- (0 until dim).toList;
+ j <- (0 until dim).toList) yield count_tours(dim, List((i, j)))
+}
+
+
+assert(count_all_tours_urban(1) == List(1))
+assert(count_all_tours_urban(2) == List(0, 0, 0, 0))
+assert(count_all_tours_urban(3) == List(0, 0, 0, 0, 0, 0, 0, 0, 0))
+assert(count_all_tours_urban(4) == List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking4/knight1_test3b.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,19 @@
+import M4a._
+//type Pos = (Int, Int) // a position on a chessboard
+//type Path = List[Pos] // a path...a list of positions
+
+/*
+def count_all_tours_urban(dim: Int) = {
+ for (i <- (0 until dim).toList;
+ j <- (0 until dim).toList) yield count_tours(dim, List((i, j)))
+}
+*/
+
+def count_all_tours_urban(dim: Int) = {
+ for (i <- (0 until 3).toList;
+ j <- (0 until dim).toList) yield count_tours(dim, List((i, j)))
+}
+
+
+assert(count_all_tours_urban(5) == List(304, 0, 56, 0, 304, 0, 56, 0, 56, 0, 56, 0, 64, 0, 56))
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking4/knight1_test3c.scala Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,33 @@
+import M4a._
+
+//type Pos = (Int, Int) // a position on a chessboard
+//type Path = List[Pos] // a path...a list of positions
+
+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 ts00_urban = enum_tours(5, List((0, 0)))
+assert(ts00_urban.map(correct_urban(5)).forall(_ == true) == true)
+assert(ts00_urban.length == 304)
+
+
+val ts_urban = enum_tours(5, List((0, 2)))
+assert(ts_urban.map(correct_urban(5)).forall(_ == true) == true)
+assert(ts_urban.length == 56)
--- a/main_marking4/knight1_test4.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking4/knight1_test4.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW9a._
+import M4a._
val f_urban = (x:(Int, Int)) => if (x._1 > 3) Some(List(x)) else None
--- a/main_marking4/knight1_test5.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking4/knight1_test5.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW9a._
+import M4a._
//type Pos = (Int, Int) // a position on a chessboard
//type Path = List[Pos] // a path...a list of positions
--- a/main_marking4/knight2.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking4/knight2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,7 +1,7 @@
-// Part 3 about finding a single tour using the Warnsdorf Rule
+// Part 2 about finding a single tour using the Warnsdorf Rule
//=============================================================
-object CW9b {
+object M4b { // for preparing the jar
type Pos = (Int, Int)
type Path = List[Pos]
@@ -67,7 +67,6 @@
def first_closed_tour_heuristic(dim: Int, path: Path) =
time_needed(tfirst_closed_tour_heuristics(dim: Int, path: Path))
-
// heuristic cannot be used to search for closed tours on 7 x 7 an beyond
//for (dim <- 1 to 6) {
// val t = time_needed(0, first_closed_tour_heuristics(dim, List((dim / 2, dim / 2))))
--- a/main_marking4/knight2_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,310 +0,0 @@
-#!/bin/bash
-
-# to make the script fail safely
-set -euo pipefail
-
-
-out=${1:-output}
-
-echo "" > $out
-
-echo -e `date` >> $out
-echo -e "" >> $out
-echo "Below is the feedback and provisional marks for your submission" >> $out
-echo "for the Main Part 4 (Scala). Please note all marks are provisional until" >> $out
-echo "ratified by the assessment board -- this is not an official" >> $out
-echo "results transcript." >> $out
-echo "" >> $out
-
-# marks for Main CW4
-marks=$(( 0 ))
-
-# 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)
-}
-
-function scala_assert_thirty {
- (ulimit -t 40; 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)
-}
-
-echo -e "" >> $out
-echo -e "Below is the feedback for your submission knight1.scala" >> $out
-echo -e "" >> $out
-
-
-# compilation test
-
-echo -e "knight1.scala is present?" | tee -a $out
-
-if [ -f "knight1.scala" ]; then
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
-else
- echo -e " --> knight1.scala is not present\n" | tee -a $out
- tsts=$(( 1 ))
-fi
-
-
-
-
-if [ $tsts -eq 0 ]
-then
- echo -e "knight1.scala runs?" | tee -a $out
-
- if (scala_compile knight1.scala)
- then
- echo -e " --> success " | tee -a $out
- tsts=$(( 0 ))
- else
- echo -e " --> SCALA DID NOT RUN knight1.scala\n" | tee -a $out
- tsts=$(( 1 ))
- fi
-else
- tsts=$(( 1 ))
-fi
-
-# knights1: purity test
-
-
-if [ $tsts -eq 0 ]
-then
- echo -e "knight1.scala does not contain VARS, RETURNS etc?" | tee -a $out
-
- if (scala_vars knight1.scala)
- then
- echo -e " --> TEST FAILED\n" | tee -a $out
- tsts=$(( 1 ))
- else
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
- fi
-else
- tsts=$(( 1 ))
-fi
-
-
-### knight4 test
-
-if [ $tsts -eq 0 ]
-then
- echo -e " Let f = (x:(Int, Int)) => if (x._1 > 3) Some(List(x)) else None " | tee -a $out
- echo -e " first(List((1,0),(2,0),(3,0),(4,0)), f) == Some(List((4,0)))" | tee -a $out
- echo -e " first(List((1,0),(2,0),(3,0)), f) == None" | tee -a $out
-
- if (scala_assert "knight1.scala" "knight1_test4.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-sleep 4
-
-### knight5 test
-
-if [ $tsts -eq 0 ]
-then
- echo -e " is first_tour(6, List((0,0))) ok? " | tee -a $out
- echo -e " is first_tour(4, List((0,0))) == None " | tee -a $out
- START=$(date +%s)
-
- if (scala_assert_thirty "knight1.scala" "knight1_test5.scala")
- then
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo -e " This test ran for $DIFF seconds" | tee -a $out
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
- else
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo -e " This test ran for $DIFF seconds" | tee -a $out
- echo -e " --> TEST FAILED\n" | tee -a $out
- fi
-fi
-
-
-echo -e "" >> $out
-echo -e "Below is the feedback for your submission knight2.scala" >> $out
-echo -e "" >> $out
-
-
-# knights2: compilation test
-
-echo "knight2.scala runs?" | tee -a $out
-
-if (scala_compile knight2.scala)
-then
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
-else
- echo -e " --> SCALA DID NOT RUN knight2.scala\n" | tee -a $out
- tsts=$(( 1 ))
-fi
-
-
-
-# knights2: purity test
-#
-if [ $tsts -eq 0 ]
-then
- echo "knight2.scala does not VARS, RETURNS etc?" | tee -a $out
-
- if (scala_vars knight2.scala)
- then
- echo -e " --> TEST FAILED\n" | tee -a $out
- tsts=$(( 1 ))
- else
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
- fi
-else
- tsts=$(( 1 ))
-fi
-
-
-# ordered move test
-
-if [ $tsts -eq 0 ]
-then
- echo -e " ordered_moves(8, List((3,4), (3,2)), (1,3)) == List((0,1), (0,5), (2,1), (2,5))" | tee -a $out
- echo -e " ordered_moves(8, List((4,0)), (0,0)) == List((2,1), (1,2))" | tee -a $out
- echo -e " ordered_moves(8, List((0,4)), (0,0)) == List((1,2), (2,1))" | tee -a $out
-
- if (scala_assert "knight2.scala" "knight2_test6.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-sleep 4
-
-# first-closed-tour test
-
-if [ $tsts -eq 0 ]
-then
- echo -e " first_closed_tour_heuristics(6, List((3,3))) found and correct?" | tee -a $out
- START=$(date +%s)
-
- if (scala_assert_thirty "knight2.scala" "knight2_test7.scala")
- then
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo -e " This test ran for $DIFF seconds" | tee -a $out
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
- else
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo -e " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> TEST FAILED\n" | tee -a $out
- fi
-fi
-
-sleep 4
-
-# first-tour test
-
-if [ $tsts -eq 0 ]
-then
- echo -e " first_tour_heuristics(8, List((0,0))) found and correct?" | tee -a $out
- echo -e " first_tour_heuristics(30, List((0,0))) found and correct?" | tee -a $out
- START=$(date +%s)
-
- if (scala_assert_thirty "knight2.scala" "knight2_test8.scala")
- then
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo " This test ran for $DIFF seconds" | tee -a $out
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
- else
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-echo -e "" >> $out
-echo -e "Below is the feedback for your submission knight3.scala" >> $out
-echo -e "" >> $out
-
-# compilation test
-echo "knight3.scala runs?" | tee -a $out
-
-if (scala_compile knight3.scala)
-then
- echo " --> success" | tee -a $out
- tsts=$(( 0 ))
-else
- echo -e " --> SCALA DID NOT RUN knight3.scala\n" | tee -a $out
- tsts=$(( 1 ))
-fi
-
-
-# knights3: purity test
-#
-if [ $tsts -eq 0 ]
-then
- echo -e "knight3.scala does not contain VARS, RETURNS etc?" | tee -a $out
-
- if (scala_vars knight3.scala)
- then
- echo " --> TEST FAILED\n" | tee -a $out
- tsts=$(( 1 ))
- else
- echo " --> success" | tee -a $out
- tsts=$(( 0 ))
- fi
-else
- tsts=$(( 1 ))
-fi
-
-sleep 4
-
-if [ $tsts -eq 0 ]
-then
- echo -e " tour_on_mega_board(70, List((0,0))) found and correct?" | tee -a $out
- START=$(date +%s)
-
- if (scala_assert_thirty "knight3.scala" "knight3_test9.scala")
- then
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo -e " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
- else
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo -e " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> TEST FAILED\n" | tee -a $out
- fi
-fi
-
-sleep 4
-
-## final marks
-echo -e "" >> $out
-echo -e "Overall mark for Main Part 4 (Scala)" | tee -a $out
-echo -e "$marks" | tee -a $out
--- a/main_marking4/knight2_test6.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking4/knight2_test6.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,19 +1,6 @@
-import CW9b._
+import M4b._
assert(ordered_moves(8, List((3,4), (3,2)), (1, 3)) == List((0,1), (0,5), (2,1), (2,5)))
assert(ordered_moves(8, List((4,0)), (0,0)) == List((2,1), (1,2)))
assert(ordered_moves(8, List((0,4)), (0,0)) == List((1,2), (2,1)))
-
-
-/*
-import scala.concurrent._
-import scala.concurrent.duration._
-import ExecutionContext.Implicits.global
-import scala.language.postfixOps
-
-lazy val f = Future {
-}
-
-Await.result(f, 120 second)
-*/
--- a/main_marking4/knight2_test7.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking4/knight2_test7.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW9b._
+import M4b._
//type Pos = (Int, Int)
//type Path = List[Pos]
--- a/main_marking4/knight2_test8.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking4/knight2_test8.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW9b._
+import M4b._
//type Pos = (Int, Int)
//type Path = List[Pos]
--- a/main_marking4/knight3.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking4/knight3.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,7 +1,7 @@
// Part 3 about finding a single tour using the Warnsdorf Rule
//=============================================================
-object CW9c {
+object M4c { // for preparing the jar
type Pos = (Int, Int)
type Path = List[Pos]
@@ -60,4 +60,8 @@
def tour_on_mega_board(dim: Int, path: Path) =
time_needed(ttour_on_mega_board(dim: Int, path: Path))
+
+// testcases
+//print_board(70, tour_on_mega_board(70, List((0, 0))).get)
+
}
--- a/main_marking4/knight3_test9.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking4/knight3_test9.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW9c._
+import M4c._
//type Pos = (Int, Int)
//type Path = List[Pos]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking4/knight_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,419 @@
+#!/bin/zsh
+
+# to make the script fail safely
+set -euo pipefail
+
+out=${1:-output}
+
+echo "" > $out
+
+echo `date` >> $out
+echo -e "" >> $out
+echo -e "Below is the feedback and provisional marks for your submission" >> $out
+echo -e "of the Main Part 4 (Scala). Please note all marks are provisional until" >> $out
+echo -e "ratified by the assessment board -- this is not an official" >> $out
+echo -e "results transcript." >> $out
+echo -e "" >> $out
+
+echo -e "" >> $out
+echo -e "Below is the feedback for your submission knight1.scala" >> $out
+echo -e "" >> $out
+
+
+
+# marks for CW8 part 1
+marks=$(( 0.0 ))
+
+# 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)
+}
+
+function scala_assert_slow {
+ (ulimit -t 120; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
+}
+
+function scala_assert_thirty {
+ (ulimit -t 40; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
+}
+
+function scala_assert_quick {
+ (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
+}
+
+function scala_assert_long {
+ (ulimit -t 60; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
+}
+
+function scala_assert_elong {
+ (ulimit -t 90; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
+}
+
+# purity test
+function scala_vars {
+ (sed 's/immutable/ok/g' c$out > cb$out;
+ egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' cb$out 2> /dev/null 1> /dev/null)
+}
+
+
+
+# compilation test
+
+echo -e "knight1.scala runs?" | tee -a $out
+
+if (scala_compile knight1.scala)
+then
+ echo -e " --> success " | tee -a $out
+ tsts=$(( 0 ))
+else
+ echo -e " --> SCALA DID NOT RUN KNIGHT1.SCALA\n" | tee -a $out
+ tsts=$(( 1 ))
+fi
+
+
+# knights1: purity test
+if [ $tsts -eq 0 ]
+ then
+ echo -e "knight1.scala does not contain VARS, RETURNS etc?" | tee -a $out
+
+ if (scala_vars knight1.scala)
+ then
+ echo -e " --> FAIL\n" | tee -a $out
+ tsts=$(( 1 ))
+ else
+ echo -e " --> success" | tee -a $out
+ tsts=$(( 0 ))
+ fi
+else
+ tsts=$(( 1 ))
+fi
+
+echo >> $out
+
+### knight1 test
+
+if [ $tsts -eq 0 ]
+then
+ echo " is_legal(8, Nil, (3, 4)) == true " | tee -a $out
+ echo " is_legal(8, List((4, 1), (1, 0)), (4, 1)) == false " | tee -a $out
+ echo " is_legal(2, Nil, (0, 0)) == true" | tee -a $out
+
+ if (scala_assert "knight1.scala" "knight1_test1.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ echo -e " --> \n ONE TEST FAILED\n"| tee -a $out
+ fi
+fi
+
+### knight2 test
+
+if [ $tsts -eq 0 ]
+then
+ echo " legal_moves(8, Nil, (2,2)) == List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4))" | tee -a $out
+ echo " legal_moves(8, Nil, (7,7)) == List((6,5), (5,6))" | tee -a $out
+ echo " legal_moves(8, List((4,1), (1,0)), (2,2)) == List((3,4), (4,3), (3,0), (0,1), (0,3), (1,4))" | tee -a $out
+ echo " legal_moves(8, Nil, (0,1)) == List((1,3), (2,2), (2,0))" | tee -a $out
+ echo " legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6))" | tee -a $out
+ echo " legal_moves(1, Nil, (0,0)) == Nil" | tee -a $out
+ echo " legal_moves(2, Nil, (0,0)) == Nil" | tee -a $out
+ echo " legal_moves(3, Nil, (0,0)) == List((1,2), (2,1))" | tee -a $out
+
+ if (scala_assert "knight1.scala" "knight1_test2.scala")
+ then
+ echo -e " --> success\n" | tee -a $out
+ marks=$(( marks + 1 ))
+ else
+ echo -e " --> ONE TEST FAILED\n" | tee -a $out
+ fi
+fi
+
+
+### knight3 test
+
+if [ $tsts -eq 0 ]
+then
+ echo " count_tours from every position on the board 1 - 4 (0.5% marks)" | tee -a $out
+ echo " dim = 1: 1" | tee -a $out
+ echo " 2: 0,0,0,0" | tee -a $out
+ echo " 3: 0,0,0,0,0,0,0,0,0" | tee -a $out
+ echo " 4: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" | tee -a $out
+ START=$(date +%s)
+
+ if (scala_assert_thirty "knight1.scala" "knight1_test3a.scala")
+ then
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ #echo " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> success\n" | tee -a $out
+ marks=$(( marks + 0.5 ))
+ else
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> ONE TEST FAILED\n" | tee -a $out
+ fi
+fi
+
+
+
+if [ $tsts -eq 0 ]
+then
+ echo " count_tours from every position on the board of dim 5 for the first 3 rows (0.25% marks)" | tee -a $out
+ echo " dim = 5: 304,0,56,0,304,0,56,0,56,0,56,0,64,0,56)" | tee -a $out
+ START=$(date +%s)
+
+ if (scala_assert_thirty "knight1.scala" "knight1_test3b.scala")
+ then
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ #echo " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> success\n" | tee -a $out
+ marks=$(( marks + 0.25 ))
+ else
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> ONE TEST FAILED\n" | tee -a $out
+ fi
+fi
+
+
+
+if [ $tsts -eq 0 ]
+then
+ echo " enum_tours(5, List((0,2)) ) => 56 tours? and all correct?" | tee -a $out
+ echo " enum_tours(5, List((0,0)) ) => 304 tours? and all correct?" | tee -a $out
+ echo " (0.25% marks) " | tee -a $out
+ START=$(date +%s)
+
+ if (scala_assert_thirty "knight1.scala" "knight1_test3c.scala")
+ then
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ #echo " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> success\n" | tee -a $out
+ marks=$(( marks + 0.25 ))
+ else
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> \n ONE TEST FAILED\n" | tee -a $out
+ fi
+fi
+
+
+### knight4 test
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " Let f = (x:(Int, Int)) => if (x._1 > 3) Some(List(x)) else None " | tee -a $out
+ echo -e " first(List((1,0),(2,0),(3,0),(4,0)), f) == Some(List((4,0)))" | tee -a $out
+ echo -e " first(List((1,0),(2,0),(3,0)), f) == None" | tee -a $out
+
+ if (scala_assert "knight1.scala" "knight1_test4.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+### knight5 test
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " is first_tour(6, List((0,0))) ok? " | tee -a $out
+ echo -e " is first_tour(4, List((0,0))) == None " | tee -a $out
+ START=$(date +%s)
+
+ if (scala_assert_thirty "knight1.scala" "knight1_test5.scala")
+ then
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo -e " This test ran for $DIFF seconds" | tee -a $out
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo -e " This test ran for $DIFF seconds" | tee -a $out
+ echo -e " --> TEST FAILED\n" | tee -a $out
+ fi
+fi
+
+echo -e "" >> $out
+echo -e "Below is the feedback for your submission knight2.scala" >> $out
+echo -e "" >> $out
+
+
+# knights2: compilation test
+
+echo "knight2.scala runs?" | tee -a $out
+
+if (scala_compile knight2.scala)
+then
+ echo -e " --> success" | tee -a $out
+ tsts=$(( 0 ))
+else
+ echo -e " --> SCALA DID NOT RUN knight2.scala\n" | tee -a $out
+ tsts=$(( 1 ))
+fi
+
+
+
+# knights2: purity test
+#
+if [ $tsts -eq 0 ]
+then
+ echo "knight2.scala does not VARS, RETURNS etc?" | tee -a $out
+
+ if (scala_vars knight2.scala)
+ then
+ echo -e " --> TEST FAILED\n" | tee -a $out
+ tsts=$(( 1 ))
+ else
+ echo -e " --> success" | tee -a $out
+ tsts=$(( 0 ))
+ fi
+else
+ tsts=$(( 1 ))
+fi
+
+
+# ordered move test
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " ordered_moves(8, List((3,4), (3,2)), (1,3)) == List((0,1), (0,5), (2,1), (2,5))" | tee -a $out
+ echo -e " ordered_moves(8, List((4,0)), (0,0)) == List((2,1), (1,2))" | tee -a $out
+ echo -e " ordered_moves(8, List((0,4)), (0,0)) == List((1,2), (2,1))" | tee -a $out
+
+ if (scala_assert "knight2.scala" "knight2_test6.scala")
+ then
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+
+# first-closed-tour test
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " first_closed_tour_heuristics(6, List((3,3))) found and correct?" | tee -a $out
+ START=$(date +%s)
+
+ if (scala_assert_thirty "knight2.scala" "knight2_test7.scala")
+ then
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo -e " This test ran for $DIFF seconds" | tee -a $out
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo -e " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> TEST FAILED\n" | tee -a $out
+ fi
+fi
+
+
+# first-tour test
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " first_tour_heuristics(8, List((0,0))) found and correct?" | tee -a $out
+ echo -e " first_tour_heuristics(30, List((0,0))) found and correct?" | tee -a $out
+ START=$(date +%s)
+
+ if (scala_assert_thirty "knight2.scala" "knight2_test8.scala")
+ then
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo " This test ran for $DIFF seconds" | tee -a $out
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
+ fi
+fi
+
+echo -e "" >> $out
+echo -e "Below is the feedback for your submission knight3.scala" >> $out
+echo -e "" >> $out
+
+# compilation test
+echo "knight3.scala runs?" | tee -a $out
+
+if (scala_compile knight3.scala)
+then
+ echo " --> success" | tee -a $out
+ tsts=$(( 0 ))
+else
+ echo -e " --> SCALA DID NOT RUN knight3.scala\n" | tee -a $out
+ tsts=$(( 1 ))
+fi
+
+
+# knights3: purity test
+#
+if [ $tsts -eq 0 ]
+then
+ echo -e "knight3.scala does not contain VARS, RETURNS etc?" | tee -a $out
+
+ if (scala_vars knight3.scala)
+ then
+ echo " --> TEST FAILED\n" | tee -a $out
+ tsts=$(( 1 ))
+ else
+ echo " --> success" | tee -a $out
+ tsts=$(( 0 ))
+ fi
+else
+ tsts=$(( 1 ))
+fi
+
+
+if [ $tsts -eq 0 ]
+then
+ echo -e " tour_on_mega_board(70, List((0,0))) found and correct?" | tee -a $out
+ START=$(date +%s)
+
+ if (scala_assert_thirty "knight3.scala" "knight3_test9.scala")
+ then
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo -e " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> success" | tee -a $out
+ marks=$(( marks + 1.0 ))
+ else
+ END=$(date +%s)
+ DIFF=$(( $END - $START ))
+ echo -e " This test ran for $DIFF seconds." | tee -a $out
+ echo -e " --> TEST FAILED\n" | tee -a $out
+ fi
+fi
+
+
+## final marks
+echo -e "" >> $out
+echo -e "Overall mark for Main Part 4 (Scala)" | tee -a $out
+printf " %0.2f\n" $marks | tee -a $out
+
+
--- a/main_marking4/mk Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#!/bin/sh
-###set -e
-
-trap "exit" INT
-
-files=${1:-*/main4}
-
-for sd in $files; do
- cd $sd
- echo $sd
- sleep 5
- touch .
- cp ../../../../../main_marking4/knight2_test.sh .
- cp ../../../../../main_marking4/knight1_test4.scala .
- cp ../../../../../main_marking4/knight1_test5.scala .
- cp ../../../../../main_marking4/knight2_test6.scala .
- cp ../../../../../main_marking4/knight2_test7.scala .
- cp ../../../../../main_marking4/knight2_test8.scala .
- cp ../../../../../main_marking4/knight3_test9.scala .
- ./knight2_test.sh output
- rm knight2_test.sh
- rm knight1_test4.scala
- rm knight1_test5.scala
- rm knight2_test6.scala
- rm knight2_test7.scala
- rm knight2_test8.scala
- rm knight3_test9.scala
- cd ..
- cd ..
-done
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking4/mk_main4 Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,42 @@
+#!/bin/bash
+###set -e
+
+trap "exit" INT
+
+files=${1:-*/main4}
+
+for sd in $files; do
+ echo -e "\n"
+ cd $sd
+ echo $sd
+ touch .
+ cp ../../../../../main_marking4/knight_test.sh .
+ cp ../../../../../main_marking4/knight1_test1.scala .
+ cp ../../../../../main_marking4/knight1_test2.scala .
+ cp ../../../../../main_marking4/knight1_test3a.scala .
+ cp ../../../../../main_marking4/knight1_test3b.scala .
+ cp ../../../../../main_marking4/knight1_test3c.scala .
+ cp ../../../../../main_marking4/knight1_test4.scala .
+ cp ../../../../../main_marking4/knight1_test5.scala .
+ cp ../../../../../main_marking4/knight2_test6.scala .
+ cp ../../../../../main_marking4/knight2_test7.scala .
+ cp ../../../../../main_marking4/knight2_test8.scala .
+ cp ../../../../../main_marking4/knight3_test9.scala .
+ ./knight_test.sh output
+ rm knight_test.sh
+ rm knight1_test1.scala
+ rm knight1_test2.scala
+ rm knight1_test3a.scala
+ rm knight1_test3b.scala
+ rm knight1_test3c.scala
+ rm knight1_test4.scala
+ rm knight1_test5.scala
+ rm knight2_test6.scala
+ rm knight2_test7.scala
+ rm knight2_test8.scala
+ rm knight3_test9.scala
+ cd ..
+ cd ..
+done
+
+
--- a/main_marking5/bf.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf.scala Mon Apr 11 23:55:27 2022 +0100
@@ -2,7 +2,7 @@
// the Brainf***++ language
//==============================================
-object CW10a {
+object M5a {
// representation of Bf memory
@@ -96,18 +96,11 @@
case '+' => (pc + 1, mp, write(mem, mp, sread(mem, mp) + 1))
case '-' => (pc + 1, mp, write(mem, mp, sread(mem, mp) - 1))
case '.' => { print(sread(mem, mp).toChar); (pc + 1, mp, mem) }
- //case ',' => (pc + 1, mp, write(mem, mp, Console.in.read().toByte))
- //case ',' => (pc + 1, mp, write(mem, mp, scala.io.StdIn.readByte()))
case '[' =>
if (sread(mem, mp) == 0) (jumpRight(prog, pc + 1, 0), mp, mem) else (pc + 1, mp, mem)
case ']' =>
if (sread(mem, mp) != 0) (jumpLeft(prog, pc - 1, 0), mp, mem) else (pc + 1, mp, mem)
- // new commands
- case '@' => (pc + 1, mp, write(mem, sread(mem, mp), sread(mem, mp - 1)))
- case '*' => (pc + 1, mp, write(mem, mp, sread(mem, mp) * sread(mem, mp -1)))
- case '#' => { println(s"${sread(mem, mp)}"); (pc + 1, mp, mem) }
-
case _ => (pc + 1, mp, mem)
}
compute(prog, new_pc, new_mp, new_mem)
@@ -142,15 +135,6 @@
// prints out numbers 0 to 9
//run("""+++++[->++++++++++<]>--<+++[->>++++++++++<<]>>++<<----------[+>.>.<+<]""")
-// bf++ program calculating the cube-function, 10 * 10 * 10 = 1000
-//run("""++++++++++#>+***#""") // Map(0 -> 10, 1 -> 1000)
-
-
-// bf++ program copies 3 from 0-cell to to cells 1, 4, 5, 6 and 7
-// (note that because of how the program wprks cell 1 will contain 7)
-//run("""+++>+@+@+@+@+@""") // Map(0 -> 3, 1 -> 7, 4 -> 3, 5 -> 3, 6 -> 3, 7 -> 3)
-
-
// some more "useful" programs
//-----------------------------
@@ -225,3 +209,7 @@
//run(load_bff("collatz.bf"))
}
+
+
+//M5a.run(M5a.load_bff("mandelbrot.bf"))
+//M5a.run(M5a.load_bff("collatz.bf"))
--- a/main_marking5/bf_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/zsh
# to make the script fail safely
set -euo pipefail
@@ -17,7 +17,7 @@
echo -e "" >> $out
# marks for CW10 part 1
-marks=$(( 0 ))
+marks=$(( 0.0 ))
# compilation tests
@@ -36,9 +36,9 @@
}
# purity test
-
function scala_vars {
- (egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' c$out 2> /dev/null 1> /dev/null)
+ (sed 's/immutable/ok/g' c$out > cb$out;
+ egrep '\bvar\b|\breturn\b|\.par\.|\.par |ListBuffer|AtomicInteger|mutable|util.control|new Array' cb$out 2> /dev/null 1> /dev/null)
}
@@ -90,7 +90,7 @@
if (scala_assert "bf.scala" "bf_test1.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 0.5 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -109,7 +109,7 @@
if (scala_assert "bf.scala" "bf_test2.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 0.5 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -131,7 +131,7 @@
if (scala_assert "bf.scala" "bf_test3.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 2 ))
+ marks=$(( marks + 2.0 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -144,8 +144,6 @@
echo -e " run(\"[-]\", Map(0 -> 100)) == Map(0 -> 0)" | tee -a $out
echo -e " run(\"[->+<]\", Map(0 -> 10)) == Map(0 -> 0, 1 -> 10)" | tee -a $out
echo -e " run(\"[>>+>>+<<<<-]\", Map(0 -> 42)) == Map(0 -> 0, 2 -> 42, 4 -> 42)" | tee -a $out
- echo -e " run(\"++++++++++#>+***#\") == Map(0 -> 10, 1 -> 1000)" | tee -a $out
- echo -e " run(\"+++>+@+@+@+@+@\") == Map(0 -> 3, 1 -> 7, 4 -> 3, 5 -> 3, 6 -> 3, 7 -> 3)" | tee -a $out
echo -e " run(\"\"\"+++++[->++++++++++<]>--<+++[->>++++++++++" | tee -a $out
echo -e " <<]>>++<<----------[+>.>.<+<]\"\"\") == Map(0 -> 0, 1 -> 58, 2 -> 32)" | tee -a $out
@@ -156,14 +154,13 @@
if (scala_assert "bf.scala" "bf_test4.scala")
then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ echo -e " --> success (mark 1%)" | tee -a $out
+ marks=$(( marks + 1.0 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
fi
-sleep 10
if [ $tsts -eq 0 ]
then
@@ -180,8 +177,8 @@
END=$(date +%s)
DIFF=$(( $END - $START ))
echo -e " This test ran for $DIFF seconds" | tee -a $out
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ echo -e " --> success (mark 1%)" | tee -a $out
+ marks=$(( marks + 1.0 ))
else
END=$(date +%s)
DIFF=$(( $END - $START ))
@@ -190,7 +187,6 @@
fi
fi
-sleep 10
echo -e "" >> $out
echo -e "Below is the feedback for your submission of bfc.scala" >> $out
@@ -250,7 +246,7 @@
if (scala_assert "bfc.scala" "bf_test5.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -276,7 +272,7 @@
if (scala_assert "bfc.scala" "bf_test6.scala")
then
echo -e " --> success" | tee -a $out
- marks=$(( marks + 1 ))
+ marks=$(( marks + 1.0 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -301,7 +297,7 @@
if (scala_assert "bfc.scala" "bf_test7.scala")
then
echo -e " --> success (+ 2%)" | tee -a $out
- marks=$(( marks + 2 ))
+ marks=$(( marks + 2.0 ))
else
echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
fi
@@ -310,6 +306,5 @@
## final marks
echo -e "Overall mark for Part 5 (Scala)" | tee -a $out
-echo -e "$marks" | tee -a $out
+printf " %0.1f\n" $marks | tee -a $out
-sleep 12
--- a/main_marking5/bf_test1.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf_test1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW10a._
+import M5a._
assert(load_bff("benchmark.bf").length == 188)
assert(load_bff("foobar.bf") == "")
--- a/main_marking5/bf_test2.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf_test2.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW10a._
+import M5a._
assert(sread(Map(), 2) == 0)
assert(sread(Map(2 -> 1), 2) == 1)
--- a/main_marking5/bf_test3.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf_test3.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW10a._
+import M5a._
assert(jumpRight("[xxxxxx]xxx", 1, 0) == 8)
assert(jumpRight("[xx[x]x]xxx", 1, 0) == 8)
--- a/main_marking5/bf_test4.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf_test4.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,10 +1,9 @@
-import CW10a._
+import M5a._
assert(run("[-]", Map(0 -> 100)) == Map(0 -> 0))
assert(run("[->+<]", Map(0 -> 10)) == Map(0 -> 0, 1 -> 10))
assert(run("[>>+>>+<<<<-]", Map(0 -> 42)) == Map(0 -> 0, 2 -> 42, 4 -> 42))
-assert(run("++++++++++#>+***#") == Map(0 -> 10, 1 -> 1000))
-assert(run("+++>+@+@+@+@+@") == Map(0 -> 3, 1 -> 7, 4 -> 3, 5 -> 3, 6 -> 3, 7 -> 3))
+
val hw_urban = """+++++[->++++++++++<]>--<+++[->>++++++++++
<<]>>++<<----------[+>.>.<+<]"""
--- a/main_marking5/bf_test4b.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf_test4b.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW10a._
+import M5a._
val urban_bench =
""">+[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++
--- a/main_marking5/bf_test5.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf_test5.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW10b._
+import M5b._
val hw_urban = """+++++[->++++++++++<]>--<+++[->>++++++++++<<]>>++<<----------[+>.>.<+<]"""
assert(jtable(hw_urban) == Map(69 -> 61, 5 -> 20, 60 -> 70, 27 -> 44, 43 -> 28, 19 -> 6))
--- a/main_marking5/bf_test6.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf_test6.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW10b._
+import M5b._
assert(optimise(load_bff("benchmark.bf")).length == 181)
assert(optimise(load_bff("mandelbrot.bf")).length == 11205)
--- a/main_marking5/bf_test7.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bf_test7.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-import CW10b._
+import M5b._
assert(combine(optimise(load_bff("benchmark.bf"))).length == 134)
assert(combine(optimise(load_bff("mandelbrot.bf"))).length == 6511)
--- a/main_marking5/bfc.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_marking5/bfc.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,7 +1,7 @@
// Part 2 about a "Compiler" for the Brainf*** language
//======================================================
-object CW10b {
+object M5b {
// !!! Copy any function you need from file bf.scala !!!
//
@@ -170,14 +170,14 @@
// that is write(mem, mp, 0).
//
// The easiest way to modify a string in this way is to use the regular
-// expression """[^<>+-.\[\]@*#]""", which recognises everything that is
+// expression """[^<>+-.\[\]""", which recognises everything that is
// not a bf-command and replace it by the empty string. Similarly the
// regular expression """\[-\]""" finds all occurences of [-] and
// by using the Scala method .replaceAll you can repplace it with the
// string "0" standing for the new bf-command.
def optimise(s: String) : String = {
- s.replaceAll("""[^<>+-.\[\]@*#]""","")
+ s.replaceAll("""[^<>+-.\[\]]""","")
.replaceAll("""\[-\]""", "0")
}
@@ -212,9 +212,10 @@
//println(optimise(load_bff("collatz.bf")))
//optimise(load_bff("benchmark.bf")) // should have inserted 0's
-//optimise(load_bff("mandelbrot.bf")).length // => 11203
+//optimise(load_bff("mandelbrot.bf")).length // => 11205
//time_needed(1, run3(load_bff("benchmark.bf")))
+//time_needed(1, run3(load_bff("mandelbrot.bf")))
--- a/main_marking5/mk Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-#!/bin/sh
-###set -e
-
-trap "exit" INT
-
-files=${1:-*/main5}
-
-for sd in $files; do
- cd $sd
- echo $sd
- touch .
- cp ../../../../../main_marking5/bf_test.sh .
- cp ../../../../../main_marking5/bf_test1.scala .
- cp ../../../../../main_marking5/bf_test2.scala .
- cp ../../../../../main_marking5/bf_test3.scala .
- cp ../../../../../main_marking5/bf_test4.scala .
- cp ../../../../../main_marking5/bf_test4b.scala .
- cp ../../../../../main_marking5/bf_test5.scala .
- cp ../../../../../main_marking5/bf_test6.scala .
- cp ../../../../../main_marking5/bf_test7.scala .
- cp ../../../../../main_marking5/*.bf .
- ./bf_test.sh output
- rm bf_test.sh
- rm bf_test1.scala
- rm bf_test2.scala
- rm bf_test3.scala
- rm bf_test4.scala
- rm bf_test4b.scala
- rm bf_test5.scala
- rm bf_test6.scala
- rm bf_test7.scala
- rm *.bf
- cd ..
- cd ..
-done
-
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main_marking5/mk_main5 Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,38 @@
+#!/bin/bash
+###set -e
+
+trap "exit" INT
+
+files=${1:-*/main5}
+
+for sd in $files; do
+ echo -e "\n"
+ cd $sd
+ echo $sd
+ touch .
+ cp ../../../../../main_marking5/bf_test.sh .
+ cp ../../../../../main_marking5/bf_test1.scala .
+ cp ../../../../../main_marking5/bf_test2.scala .
+ cp ../../../../../main_marking5/bf_test3.scala .
+ cp ../../../../../main_marking5/bf_test4.scala .
+ cp ../../../../../main_marking5/bf_test4b.scala .
+ cp ../../../../../main_marking5/bf_test5.scala .
+ cp ../../../../../main_marking5/bf_test6.scala .
+ cp ../../../../../main_marking5/bf_test7.scala .
+ cp ../../../../../main_marking5/*.bf .
+ ./bf_test.sh output
+ rm bf_test.sh
+ rm bf_test1.scala
+ rm bf_test2.scala
+ rm bf_test3.scala
+ rm bf_test4.scala
+ rm bf_test4b.scala
+ rm bf_test5.scala
+ rm bf_test6.scala
+ rm bf_test7.scala
+ rm *.bf
+ cd ..
+ cd ..
+done
+
+
--- a/main_solution3/re.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_solution3/re.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,4 +1,4 @@
-// Core Part about Regular Expression Matching
+// Main Part 3 about Regular Expression Matching
//=============================================
object M3 {
@@ -12,17 +12,14 @@
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp // sequence
case class STAR(r: Rexp) extends Rexp // star
-// some convenience for typing in regular expressions
-
//the usual binary choice can be defined in terms of ALTs
def ALT(r1: Rexp, r2: Rexp) = ALTs(List(r1, r2))
-
+// some convenience for typing in regular expressions
import scala.language.implicitConversions
import scala.language.reflectiveCalls
-
def charlist2rexp(s: List[Char]): Rexp = s match {
case Nil => ONE
case c::Nil => CHAR(c)
@@ -76,6 +73,10 @@
}
+// (3) Implement the flatten function flts. It
+// deletes 0s from a list of regular expressions
+// and also 'spills out', or flattens, nested
+// ALTernativeS.
def flts(rs: List[Rexp]) : List[Rexp] = rs match {
case Nil => Nil
@@ -84,7 +85,7 @@
case r::rs => r :: flts(rs)
}
-// (3) Complete the simp function according to
+// (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
@@ -110,7 +111,7 @@
simp(ALT(ONE | CHAR('a'), CHAR('a') | ONE))
-// (4) Complete the two functions below; the first
+// (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
@@ -124,7 +125,7 @@
// main matcher function
def matcher(r: Rexp, s: String) = nullable(ders(s.toList, r))
-// (5) Complete the size function for regular
+// (6) Complete the size function for regular
// expressions according to the specification
// given in the coursework.
@@ -146,7 +147,7 @@
//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
--- a/main_solution5/bf.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_solution5/bf.scala Mon Apr 11 23:55:27 2022 +0100
@@ -211,4 +211,5 @@
}
-M5a.run(M5a.load_bff("mandelbrot.bf"))
+//M5a.run(M5a.load_bff("mandelbrot.bf"))
+M5a.run(M5a.load_bff("collatz.bf"))
--- a/main_templates3/re.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_templates3/re.scala Mon Apr 11 23:55:27 2022 +0100
@@ -12,28 +12,12 @@
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp // sequence
case class STAR(r: Rexp) extends Rexp // star
-import scala.language.implicitConversions
-import scala.language.reflectiveCalls
-
-def charlist2rexp(s: List[Char]): Rexp = s match {
- case Nil => ONE
- case c::Nil => CHAR(c)
- case c::s => SEQ(CHAR(c), charlist2rexp(s))
-}
-implicit def string2rexp(s: String): Rexp = charlist2rexp(s.toList)
-
-
-// "a|b"
-ALT(CHAR('a'), CHAR('b'))
-
-val reg : Rexp = "a" | "b" // CHAR('a')
-
-// some convenience for typing regular expressions
-
//the usual binary choice can be defined in terms of ALTs
def ALT(r1: Rexp, r2: Rexp) = ALTs(List(r1, r2))
+// some convenience for typing regular expressions
+
import scala.language.implicitConversions
import scala.language.reflectiveCalls
@@ -44,9 +28,6 @@
}
implicit def string2rexp(s: String): Rexp = charlist2rexp(s.toList)
-
-
-
implicit def RexpOps (r: Rexp) = new {
def | (s: Rexp) = ALT(r, s)
def % = STAR(r)
@@ -61,6 +42,11 @@
def ~ (r: String) = SEQ(s, r)
}
+
+// ALT(CHAR('a'), CHAR('b'))
+// val reg : Rexp = "a" | "b"
+
+
// (1) Complete the function nullable according to
// the definition given in the coursework; this
// function checks whether a regular expression
--- a/main_testing2/danube_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ b/main_testing2/danube_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -5,8 +5,8 @@
-#scalafile=${2:-danube.scala}
-out=${1:-output}
+scalafile=${1:-danube.scala}
+out=${2:-output}
@@ -25,7 +25,7 @@
# functional tests
function scala_assert {
- (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "") # 2> /dev/null 1> /dev/null)
+ (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
}
# purity test
--- a/main_testing3/re.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_testing3/re.scala Mon Apr 11 23:55:27 2022 +0100
@@ -13,12 +13,10 @@
case class STAR(r: Rexp) extends Rexp // star
-// some convenience for typing regular expressions
-
//the usual binary choice can be defined in terms of ALTs
def ALT(r1: Rexp, r2: Rexp) = ALTs(List(r1, r2))
-
+// some convenience for typing in regular expressions
import scala.language.implicitConversions
import scala.language.reflectiveCalls
@@ -52,18 +50,12 @@
def nullable (r: Rexp) : Boolean = r match {
case ZERO => false
case ONE => true
- case CHAR(c) => false
- case ALTs(rs) => {
- if (rs.size == 0) false
- else if (nullable(rs.head)) true
- else nullable(ALTs(rs.tail))
- }
- case SEQ(c, s) => nullable(c) && nullable(s)
- case STAR(r) => true
- case _ => false
+ case CHAR(_) => false
+ case ALTs(rs) => rs.exists(nullable)
+ case SEQ(r1, r2) => nullable(r1) && nullable(r2)
+ case STAR(_) => true
}
-
// (2) Complete the function der according to
// the definition given in the coursework; this
// function calculates the derivative of a
@@ -72,16 +64,12 @@
def der (c: Char, r: Rexp) : Rexp = r match {
case ZERO => ZERO
case ONE => ZERO
- case CHAR(x) => {
- if (x==c) ONE
- else ZERO
- }
- case ALTs(rs) => ALTs(for (i <- rs) yield der(c, i))
- case SEQ(x, y) => {
- if (nullable(x)) ALTs(List(SEQ(der(c, x), y), der(c, y)))
- else SEQ(der(c, x), y)
- }
- case STAR(x) => SEQ(der(c, x), STAR(x))
+ 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 STAR(r1) => SEQ(der(c, r1), STAR(r1))
}
@@ -92,118 +80,119 @@
def flts(rs: List[Rexp]) : List[Rexp] = rs match {
case Nil => Nil
- case ZERO::rest => flts(rest)
- case ALTs(rs_other)::rest => rs_other ::: flts(rest)
- case r::rest => r::flts(rest)
+ case ZERO::tl => flts(tl)
+ case ALTs(rs1)::rs2 => rs1 ::: flts(rs2)
+ case r::rs => r :: flts(rs)
}
// (4) Complete the simp function according to
-// the specification given in the coursework description;
-// this function simplifies a regular expression from
+// 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. Use the _.distinct and
-// flts functions.
+// STAR-regular expressions.
+
def simp(r: Rexp) : Rexp = r match {
- case SEQ(x, ZERO) => ZERO
- case SEQ(ZERO, x) => ZERO
- case SEQ(x, ONE) => x
- case SEQ(ONE, x) => x
- case SEQ(x, y) => SEQ(simp(x), simp(y))
- case ALTs(rs) => {
- val list = flts(for (x <- rs) yield simp(x)).distinct
- if (list.size == 0) ZERO
- else if (list.size == 1) list.head
- else ALTs(list)
+ case ALTs(rs) => (flts(rs.map(simp)).distinct) match {
+ case Nil => ZERO
+ case r::Nil => r
+ case rs => ALTs(rs)
}
- case x => x
+ case SEQ(r1, r2) => (simp(r1), simp(r2)) match {
+ case (ZERO, _) => ZERO
+ case (_, ZERO) => ZERO
+ case (ONE, r2s) => r2s
+ case (r1s, ONE) => r1s
+ case (r1s, r2s) => SEQ(r1s, r2s)
+ }
+ case r => r
}
+simp(ALT(ONE | CHAR('a'), CHAR('a') | ONE))
// (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
+// string matches the regular expression.
def ders (s: List[Char], r: Rexp) : Rexp = s match {
case Nil => r
- case c::rest => {
- val deriv = simp(der(c,r))
- ders(rest, deriv)
- }
+ case c::s => ders(s, simp(der(c, r)))
}
-def matcher(r: Rexp, s: String): Boolean = nullable(ders(s.toList, r))
-
+// 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.
+
def size(r: Rexp): Int = r match {
- case Nil => 0
case ZERO => 1
case ONE => 1
- case CHAR(x) => 1
- case ALTs(rs) => 1 + (for (x <- rs) yield size(x)).sum
- case SEQ(x, y) => 1 + size(x) + size(y)
- case STAR(x) => 1 + size(x)
+ case CHAR(_) => 1
+ case ALTs(rs) => 1 + rs.map(size).sum
+ case SEQ(r1, r2) => 1 + size(r1) + size (r2)
+ case STAR(r1) => 1 + size(r1)
}
+
// some testing data
-
-// matcher(("a" ~ "b") ~ "c", "abc") // => true
-// matcher(("a" ~ "b") ~ "c", "ab") // => false
+//matcher(("a" ~ "b") ~ "c", "abc") // => true
+//matcher(("a" ~ "b") ~ "c", "ab") // => false
// the supposedly 'evil' regular expression (a*)* b
// val EVIL = SEQ(STAR(STAR(CHAR('a'))), CHAR('b'))
-// matcher(EVIL, "a" * 1000 ++ "b") // => true
-// matcher(EVIL, "a" * 1000) // => false
+//println(matcher(EVIL, "a" * 1000 ++ "b")) // => true
+//println(matcher(EVIL, "a" * 1000)) // => false
// size without simplifications
-// size(der('a', der('a', EVIL))) // => 28
-// size(der('a', der('a', der('a', EVIL)))) // => 58
+//println(size(der('a', der('a', EVIL)))) // => 28
+//println(size(der('a', der('a', der('a', EVIL))))) // => 58
// size with simplification
-// size(simp(der('a', der('a', EVIL)))) // => 8
-// size(simp(der('a', der('a', der('a', EVIL))))) // => 8
+//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
// 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
-// 30 seconds.
+// around 30 seconds.
//
-// Lets see how long it really takes to match strings with
-// 5 Million a's...it should be in the range of a couple
-// of seconds.
+// 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.
-// def time_needed[T](i: Int, code: => T) = {
-// val start = System.nanoTime()
-// for (j <- 1 to i) code
-// val end = System.nanoTime()
-// "%.5f".format((end - start)/(i * 1.0e9))
-// }
+def time_needed[T](i: Int, code: => T) = {
+ val start = System.nanoTime()
+ for (j <- 1 to i) code
+ val end = System.nanoTime()
+ "%.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(50).next()) == ONE
+//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.
+
-// This a dummy comment. Hopefully it works!
}
-
--- a/main_testing3/re_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ b/main_testing3/re_test.sh Mon Apr 11 23:55:27 2022 +0100
@@ -108,8 +108,8 @@
echo -e " simp(ZERO | ONE) == ONE" >> $out
echo -e " simp(STAR(ZERO | ONE)) == STAR(ZERO | ONE)" >> $out
echo -e " simp(ONE ~ (ONE ~ (ONE ~ CHAR('a')))) == CHAR('a')" >> $out
- echo -e " simp(((ONE ~ ONE) ~ ONE) ~ CHAR('a')) == CHAR('a'))" >> $out
- echo -e " simp(((ONE | ONE) ~ ONE) ~ CHAR('a')) == CHAR('a'))" >> $out
+ echo -e " simp(((ONE ~ ONE) ~ ONE) ~ CHAR('a')) == CHAR('a')" >> $out
+ echo -e " simp(((ONE | ONE) ~ ONE) ~ CHAR('a')) == CHAR('a')" >> $out
echo -e " simp(ONE ~ (ONE ~ (ONE ~ ZERO))) == ZERO" >> $out
echo -e " simp(ALT(ONE ~ (ONE ~ (ONE ~ ZERO)), CHAR('a'))) == CHAR('a')" >> $out
echo -e " simp(CHAR('a') | CHAR('a')) == CHAR('a')" >> $out
--- a/main_testing4/knight1.scala Thu Jan 13 12:55:03 2022 +0000
+++ b/main_testing4/knight1.scala Mon Apr 11 23:55:27 2022 +0100
@@ -1,13 +1,119 @@
-// Part 1 about finding and counting Knight's tours
-//==================================================
+// Main Part 4 about finding Knight's tours
+//==========================================
+import scala.annotation.tailrec
+
+
+object M4a {
-object M4a { // for preparing the jar
+// 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.
+
+
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.
-// for measuring time in the JAR
+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
def time_needed[T](code: => T) : T = {
val start = System.nanoTime()
val result = code
@@ -16,6 +122,14 @@
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()
@@ -27,145 +141,7 @@
}
}
-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/pre_marking1/collatz.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-// Basic Part about the 3n+1 conjecture
-//==================================
-
-// generate jar with
-// > scala -d collatz.jar collatz.scala
-
-object CW6a { // for purposes of generating a jar
-
-def collatz(n: Long): Long =
- if (n == 1) 0 else
- if (n % 2 == 0) 1 + collatz(n / 2) else
- 1 + collatz(3 * n + 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)
-//collatz_max(10000000)
-//collatz_max(100000000)
-
-/* 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
-
-def is_hard(n: Long) : Boolean = is_pow(3 * n + 1)
-
-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)}")
-
-}
-
-
-
--- a/pre_marking1/collatz_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-#!/bin/bash
-
-# to make the script fail safely
-set -euo pipefail
-
-
-out=${1:-output}
-
-echo "" > $out
-
-echo `date` >> $out
-echo >> $out
-echo "Below is the feedback and provisional marks for your submission" >> $out
-echo "for the Preliminary Part of Part 1 (Scala). Please note all marks are provisional until" >> $out
-echo "ratified by the assessment board -- this is not an official" >> $out
-echo "results transcript." >> $out
-echo "" >> $out
-
-echo "The feedback for your submission for collatz.scala" >> $out
-echo "" >> $out
-
-# marks for CW6 preliminary part
-marks=$(( 0 ))
-
-# 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 -nc -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 "collatz.scala runs?" >> $out
-
-if (scala_compile collatz.scala)
-then
- echo -e " --> success" >> $out
- tsts0=$(( 0 ))
-else
- echo -e " --> SCALA DID NOT RUN collatz.scala\n" >> $out
- tsts0=$(( 1 ))
-fi
-
-# var, .par return, ListBuffer test
-#
-
-if [ $tsts0 -eq 0 ]
-then
- echo -e "collatz.scala does not contain VARS, RETURNS etc?" >> $out
-
- if (scala_vars collatz.scala)
- then
- echo -e " --> test failed\n" >> $out
- tsts=$(( 1 ))
- else
- echo -e " --> success" >> $out
- tsts=$(( 0 ))
- fi
-else
- tsts=$(( 1 ))
-fi
-
-
-echo >> $out
-
-### collatz tests
-
-if [ $tsts -eq 0 ]
-then
- echo "collatz.scala tests:" | tee -a $out
- echo " collatz(1) == 0" | tee -a $out
- echo " collatz(6) == 8" | tee -a $out
- echo " collatz(9) == 19" | tee -a $out
- echo " collatz(9000) == 47" | tee -a $out
-
- if (scala_assert "collatz.scala" "collatz_test1.scala")
- then
- echo " --> success" | tee -a $out
- marks=$(( marks + 1 ))
- else
- echo " --> one of the tests failed" | tee -a $out
- fi
-fi
-
-### collatz-max tests
-
-if [ $tsts -eq 0 ]
-then
- echo " collatz_max(10) == (19, 9)" | tee -a $out
- echo " collatz_max(100) == (118, 97)" | tee -a $out
- echo " collatz_max(1000) == (178, 871)" | tee -a $out
- echo " collatz_max(10000) == (261, 6171)" | tee -a $out
- echo " collatz_max(100000) == (350, 77031)" | tee -a $out
- echo " collatz_max(1000000) == (524, 837799)" | tee -a $out
- # echo " collatz_max(2) == (1, 2) || collatz_max(2) == (0, 1)" | tee -a $out
- echo " collatz_max(2) == (1, 2)" | tee -a $out
- echo " collatz_max(77000) == (339, 52527)" | tee -a $out
-
- if (scala_assert "collatz.scala" "collatz_test2.scala")
- then
- echo " --> success" | tee -a $out
- marks=$(( marks + 1 ))
- else
- echo " --> one of the tests failed" | tee -a $out
- fi
-fi
-
-### last-odd tests
-
-if [ $tsts -eq 0 ]
-then
- echo " last_odd(113) == 85" | tee -a $out
- echo " last_odd(84) == 21" | tee -a $out
- echo " last_odd(605) == 341" | tee -a $out
-
- if (scala_assert "collatz.scala" "collatz_test3.scala")
- then
- echo " --> success" | tee -a $out
- marks=$(( marks + 1 ))
- else
- echo " --> one of the tests failed" | tee -a $out
- fi
-fi
-
-
-
-## final marks
-echo >> $out
-echo "Overall mark for the Preliminary Part 1 (Scala)" | tee -a $out
-echo " $marks" | tee -a $out
-
-
--- a/pre_marking1/collatz_test1.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-
-
-assert(CW6a.collatz(1) == 0)
-assert(CW6a.collatz(6) == 8)
-assert(CW6a.collatz(9) == 19)
-assert(CW6a.collatz(9000) == 47)
-
-
--- a/pre_marking1/collatz_test2.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-//def myassert(cond : => Boolean) = {
-// try {
-// assert(cond)
-// } catch {
-// case _ : Throwable => System.exit(1)
-// }
-//}
-
-assert(CW6a.collatz_max(10) == (19, 9))
-assert(CW6a.collatz_max(100) == (118, 97))
-assert(CW6a.collatz_max(1000) == (178, 871))
-assert(CW6a.collatz_max(10000) == (261, 6171))
-assert(CW6a.collatz_max(100000) == (350, 77031))
-assert(CW6a.collatz_max(1000000) == (524, 837799))
-assert(CW6a.collatz_max(2) == (1, 2))
-assert(CW6a.collatz_max(77000) == (339, 52527))
--- a/pre_marking1/collatz_test3.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-
-assert(CW6a.last_odd(113) == 85)
-assert(CW6a.last_odd(84) == 21)
-assert(CW6a.last_odd(605) == 341)
--- a/pre_marking1/mk Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-#!/bin/bash
-set -euo pipefail
-
-trap "exit" INT
-
-files=${1:-*/pre1}
-
-for sd in $files; do
- cd $sd
- echo $sd
- sleep 5
- touch .
- cp ../../../../../pre_marking1/collatz_test.sh .
- cp ../../../../../pre_marking1/collatz_test1.scala .
- cp ../../../../../pre_marking1/collatz_test2.scala .
- cp ../../../../../pre_marking1/collatz_test3.scala .
- ./collatz_test.sh output
- rm collatz_test.sh
- rm collatz_test1.scala
- rm collatz_test2.scala
- rm collatz_test3.scala
- cd ..
- cd ..
-done
-
-
--- a/pre_marking2/docdiff.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +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] =
- ("""\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.
-
-*/
-
-
-}
--- a/pre_marking2/docdiff_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-#!/bin/zsh
-
-# to make the script fail safely
-set -euo pipefail
-
-
-out=${1:-output}
-
-echo "" > $out
-
-echo `date` >> $out
-echo -e "Below is the feedback and provisional marks for your submission" >> $out
-echo -e "for the Preliminary Part of Part 2 (Scala). Please note all marks are provisional until" >> $out
-echo -e "ratified by the assessment board -- this is not an official" >> $out
-echo -e "results transcript." >> $out
-echo -e "" >> $out
-
-echo -e "Below is the feedback for your submission docdiff.scala" >> $out
-echo -e "" >> $out
-
-# marks for CW7 preliminary part
-marks=$(( 0.0 ))
-
-
-# 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 -nc -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?" | tee -a $out
-
-if (scala_compile docdiff.scala)
-then
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
-else
- echo -e " --> SCALA DID NOT RUN docdiff.scala\n" | tee -a $out
- tsts=$(( 1 ))
-fi
-
-
-# var, .par return, ListBuffer test
-#
-
-if [ $tsts -eq 0 ]
-then
- echo -e "docdiff.scala does not contain VARS, RETURNS etc?" | tee -a $out
-
- if (scala_vars docdiff.scala)
- then
- echo -e " --> test failed\n" | tee -a $out
- tsts=$(( 1 ))
- else
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
- fi
-else
- tsts=$(( 1 ))
-fi
-
-echo >> $out
-
-
-### docdiff clean tests
-
-if [ $tsts -eq 0 ]
-then
- echo -e "docdiff.scala tests:" | tee -a $out
- echo -e " clean(\"ab a abc\") == List(\"ab\", \"a\", \"abc\")" | tee -a $out
- echo -e " clean(\"ab*a abc1\") == List(\"ab\", \"a\", \"abc1\")" | tee -a $out
-
- if (scala_assert "docdiff.scala" "docdiff_test1.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 0.5 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-### docdiff occurrences tests
-
-if [ $tsts -eq 0 ]
-then
- echo -e " occurrences(List(\"a\", \"b\", \"b\", \"c\", \"d\")) == " | tee -a $out
- echo -e " Map(\"a\" -> 1, \"b\" -> 2, \"c\" -> 1, \"d\" -> 1)" | tee -a $out
- echo -e " " | tee -a $out
- echo -e " occurrences(List(\"d\", \"b\", \"d\", \"b\", \"d\")) == " | tee -a $out
- echo -e " Map(\"d\" -> 3, \"b\" -> 2)" | tee -a $out
- echo -e " " | tee -a $out
- echo -e " occurrences(Nil) == Map() " | tee -a $out
- echo -e " " | tee -a $out
- echo -e " occurrences(List(\"b\", \"b\", \"b\", \"b\", \"b\")) == Map(\"b\" -> 5)" | tee -a $out
-
- if (scala_assert "docdiff.scala" "docdiff_test2.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1.0 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-### docdiff prod tests
-
-if [ $tsts -eq 0 ]
-then
- echo -e " val l1 = List(\"a\", \"b\", \"b\", \"c\", \"d\")" | tee -a $out
- echo -e " val l2 = List(\"d\", \"b\", \"d\", \"b\", \"d\")" | tee -a $out
- echo -e " " | tee -a $out
- echo -e " prod(l1, l2) == 7 " | tee -a $out
- echo -e " prod(l1, l1) == 7 " | tee -a $out
- echo -e " prod(l2, l2) == 13 " | tee -a $out
- echo -e " " | tee -a $out
- echo -e " val l3 = List(\"1\", \"2\", \"3\", \"4\", \"5\")" | tee -a $out
- echo -e " prod(l1, l3) == 0 " | tee -a $out
-
- if (scala_assert "docdiff.scala" "docdiff_test3.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1.0 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-### docdiff overlap tests
-
-if [ $tsts -eq 0 ]
-then
- echo -e " val l1 = List(\"a\", \"b\", \"b\", \"c\", \"d\")" | tee -a $out
- echo -e " val l2 = List(\"d\", \"b\", \"d\", \"b\", \"d\")" | tee -a $out
- echo -e " " | tee -a $out
- echo -e " overlap(l1, l2) == 0.5384615384615384 " | tee -a $out
- echo -e " overlap(l1, l1) == 1.0 " | tee -a $out
- echo -e " overlap(l2, l2) == 1.0 " | tee -a $out
-
- if (scala_assert "docdiff.scala" "docdiff_test4.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 0.5 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-
-## final marks
-echo -e "Overall mark for the Preliminary Part 2 (Scala)" | tee -a $out
-printf " %0.1f\n" $marks | tee -a $out
-
-
-#echo -e " $marks" | tee -a $out
-
--- a/pre_marking2/docdiff_test1.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-
-import CW7a._
-
-assert(clean("ab a abc") == List("ab", "a", "abc"))
-assert(clean("ab*a abc1") == List("ab", "a", "abc1"))
--- a/pre_marking2/docdiff_test2.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +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))
-
-assert(occurrences(List("b", "b", "b", "b", "b")) == Map("b" -> 5))
-
-assert(occurrences(Nil) == Map())
--- a/pre_marking2/docdiff_test3.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +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)
-
-
-val urban_listA = List("a", "b", "b", "c", "d")
-val urban_listB = List("1", "2", "3", "4", "5")
-
-assert(prod(urban_listA, urban_listB) == 0)
--- a/pre_marking2/docdiff_test4.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +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_marking2/mk Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#!/bin/bash
-set -euo pipefail
-
-
-trap "exit" INT
-
-files=${1:-*/pre2}
-
-for sd in $files; do
- cd $sd
- echo $sd
- touch .
- cp ../../../../../pre_marking2/docdiff_test.sh .
- cp ../../../../../pre_marking2/docdiff_test1.scala .
- cp ../../../../../pre_marking2/docdiff_test2.scala .
- cp ../../../../../pre_marking2/docdiff_test3.scala .
- cp ../../../../../pre_marking2/docdiff_test4.scala .
- ./docdiff_test.sh output
- rm docdiff_test.sh
- rm docdiff_test1.scala
- rm docdiff_test2.scala
- rm docdiff_test3.scala
- rm docdiff_test4.scala
- cd ..
- cd ..
-done
-
-
--- a/pre_marking3/mk Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-#!/bin/bash
-set -euo pipefail
-
-
-trap "exit" INT
-
-files=${1:-*/pre3}
-
-for sd in $files; do
- cd $sd
- echo $sd
- touch .
- cp ../../../../../pre_marking3/postfix_test.sh .
- cp ../../../../../pre_marking3/postfix_test1.scala .
- cp ../../../../../pre_marking3/postfix_test2.scala .
- cp ../../../../../pre_marking3/postfix_test3.scala .
- cp ../../../../../pre_marking3/postfix_test4.scala .
- ./postfix_test.sh output
- rm postfix_test.sh
- rm postfix_test1.scala
- rm postfix_test2.scala
- rm postfix_test3.scala
- rm postfix_test4.scala
- cd ..
- cd ..
-done
-
-
--- a/pre_marking3/postfix.scala Thu Jan 13 12:55:03 2022 +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_marking3/postfix2.scala Thu Jan 13 12:55:03 2022 +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_marking3/postfix_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-#!/bin/zsh
-set -euo pipefail
-
-
-out=${1:-output}
-
-echo -e "" > $out
-
-echo `date` >> $out
-echo -e "Below is the feedback and provisional marks for your submission" >> $out
-echo -e "of the Preliminary Part of Part 3 (Scala). Please note all marks are provisional until" >> $out
-echo -e "ratified by the assessment board -- this is not an official" >> $out
-echo -e "results transcript." >> $out
-echo -e "" >> $out
-
-echo -e "Below is the feedback for your submission docdiff.scala" >> $out
-echo -e "" >> $out
-
-
-# marks for CW9 preliminary
-marks=$(( 0.0 ))
-
-
-# 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?" | tee -a $out
-
-if (scala_compile postfix.scala)
-then
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
-else
- echo -e " --> SCALA DID NOT RUN postfix.scala\n" | tee -a $out
- tsts=$(( 1 ))
-fi
-
-
-
-# var, return, ListBuffer test
-#
-if [ $tsts -eq 0 ]
- then
- echo -e "postfix.scala does not contain VARS, RETURNS etc?" | tee -a $out
-
- if (scala_vars postfix.scala)
- then
- echo -e " --> FAIL\n" | tee -a $out
- tsts=$(( 1 ))
- else
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
- fi
-else
- tsts=$(( 1 ))
-fi
-
-
-
-### postfix tests
-
-if [ $tsts -eq 0 ]
-then
- echo -e " syard(split(\"3 + 4 * ( 2 - 1 )\")) == List(\"3\", \"4\", \"2\", \"1\", \"-\", \"*\", \"+\")" | tee -a $out
- echo -e " syard(split(\"( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )\")) == List(\"3\", \"4\", \"5\", \"+\", \"+\")" | tee -a $out
- echo -e " syard(split(\"5 + 7 / 2\")) == List(\"5\", \"7\", \"2\", \"/\", \"+\")" | tee -a $out
- echo -e " syard(split(\"5 * 7 / 2\")) == List(\"5\", \"7\", \"*\", \"2\", \"/\")" | tee -a $out
-
- if (scala_assert "postfix.scala" "postfix_test1.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1.0 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-
-
-if [ $tsts -eq 0 ]
-then
- echo -e " compute(syard(split(\"3 + 4 * ( 2 - 1 )\"))) == 7" | tee -a $out
- echo -e " compute(syard(split(\"10 + 12 * 33\"))) == 406" | tee -a $out
- echo -e " compute(syard(split(\"( 5 + 7 ) * 2\"))) == 24" | tee -a $out
- echo -e " compute(syard(split(\"5 + 7 / 2\"))) == 8" | tee -a $out
- echo -e " compute(syard(split(\"5 * 7 / 2\"))) == 17" | tee -a $out
- echo -e " compute(syard(split(\"9 + 24 / ( 7 - 3 )\"))) == 15" | tee -a $out
-
- if (scala_assert "postfix.scala" "postfix_test2.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1.0 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-
-
-### postfix2 tests
-
-echo -e "Below is the feedback for your submission postfix2.scala" >> $out
-echo -e "" >> $out
-
-# compilation test
-
-echo -e "postfix2.scala runs?" | tee -a $out
-
-if (scala_compile postfix2.scala)
-then
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
-else
- echo -e " --> SCALA DID NOT RUN postfix2.scala\n" | tee -a $out
- tsts=$(( 1 ))
-fi
-
-
-# var, return, ListBuffer test
-#
-if [ $tsts -eq 0 ]
-then
- echo -e "postfix2.scala does not contain VARS, RETURNS etc?" | tee -a $out
-
- if (scala_vars postfix2.scala)
- then
- echo -e " --> FAIL\n" | tee -a $out
- tsts=$(( 1 ))
- else
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
- fi
-else
- tsts=$(( 1 ))
-fi
-
-
-
-
-if [ $tsts -eq 0 ]
-then
- echo -e " syard(split(\"3 + 4 * ( 2 - 1 )\")) == List(\"3\", \"4\", \"2\", \"1\", \"-\", \"*\", \"+\")" | tee -a $out
- echo -e " syard(split(\"( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )\")) == List(\"3\", \"4\", \"5\", \"+\", \"+\")" | tee -a $out
- echo -e " syard(split(\"5 + 7 / 2\")) == List(\"5\", \"7\", \"2\", \"/\", \"+\")" | tee -a $out
- echo -e " syard(split(\"5 * 7 / 2\")) == List(\"5\", \"7\", \"*\", \"2\", \"/\")" | tee -a $out
- echo -e " syard(split(\"3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3\")) == " | tee -a $out
- echo -e " List(\"3\", \"4\", \"8\", \"*\", \"5\", \"1\", \"-\", \"2\", \"3\", \"^\", \"^\", \"/\", \"+\")" | tee -a $out
-
- if (scala_assert "postfix2.scala" "postfix_test3.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 0.5 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-if [ $tsts -eq 0 ]
-then
- echo -e " compute(syard(split(\"3 + 4 * ( 2 - 1 )\"))) == 7" | tee -a $out
- echo -e " compute(syard(split(\"10 + 12 * 33\"))) == 406" | tee -a $out
- echo -e " compute(syard(split(\"( 5 + 7 ) * 2\"))) == 24" | tee -a $out
- echo -e " compute(syard(split(\"5 + 7 / 2\"))) == 8" | tee -a $out
- echo -e " compute(syard(split(\"5 * 7 / 2\"))) == 17" | tee -a $out
- echo -e " compute(syard(split(\"9 + 24 / ( 7 - 3 )\"))) == 15" | tee -a $out
- echo -e " compute(syard(split(\"4 ^ 3 ^ 2\"))) == 262144" | tee -a $out
- echo -e " compute(syard(split(\"4 ^ ( 3 ^ 2 )\"))) == 262144" | tee -a $out
- echo -e " compute(syard(split(\"( 4 ^ 3 ) ^ 2\"))) == 4096" | tee -a $out
- echo -e " compute(syard(split(\"( 3 + 1 ) ^ 2 ^ 3\"))) == 65536" | tee -a $out
-
- if (scala_assert "postfix2.scala" "postfix_test4.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 0.5 ))
- else
- echo -e " --> ONE OF THE TESTS FAILED\n" | tee -a $out
- fi
-fi
-
-## final marks
-echo -e "Overall mark for the Preliminary Part 3 (Scala)" | tee -a $out
-printf " %0.1f\n" $marks | tee -a $out
-
--- a/pre_marking3/postfix_test1.scala Thu Jan 13 12:55:03 2022 +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_marking3/postfix_test2.scala Thu Jan 13 12:55:03 2022 +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_marking3/postfix_test3.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +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", "^", "^", "/", "+"))
-
--- a/pre_marking3/postfix_test4.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-import CW8b._
-
-
-assert(compute(syard(split("3 + 4 * ( 2 - 1 )"))) == 7)
-assert(compute(syard(split("10 + 12 * 33"))) == 406)
-assert(compute(syard(split("( 5 + 7 ) * 2"))) == 24)
-assert(compute(syard(split("5 + 7 / 2"))) == 8)
-assert(compute(syard(split("5 * 7 / 2"))) == 17)
-assert(compute(syard(split("9 + 24 / ( 7 - 3 )"))) == 15)
-assert(compute(syard(split("4 ^ 3 ^ 2"))) == 262144)
-assert(compute(syard(split("4 ^ ( 3 ^ 2 )"))) == 262144)
-assert(compute(syard(split("( 4 ^ 3 ) ^ 2"))) == 4096)
-assert(compute(syard(split("( 3 + 1 ) ^ 2 ^ 3"))) == 65536)
--- a/pre_marking4/knight1_test.sh Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-#!/bin/zsh
-
-# to make the script fail safely
-set -euo pipefail
-
-out=${1:-output}
-
-echo "" > $out
-
-echo `date` >> $out
-echo -e "" >> $out
-echo -e "Below is the feedback and provisional marks for your submission" >> $out
-echo -e "of the Preliminary Part of Part 4 (Scala). Please note all marks are provisional until" >> $out
-echo -e "ratified by the assessment board -- this is not an official" >> $out
-echo -e "results transcript." >> $out
-echo -e "" >> $out
-
-echo -e "" >> $out
-echo -e "Below is the feedback for your submission knight1.scala" >> $out
-echo -e "" >> $out
-
-
-
-# marks for CW8 part 1
-marks=$(( 0.0 ))
-
-# 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)
-}
-
-function scala_assert_slow {
- (ulimit -t 120; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
-}
-
-function scala_assert_thirty {
- (ulimit -t 40; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
-}
-
-function scala_assert_quick {
- (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
-}
-
-function scala_assert_long {
- (ulimit -t 60; JAVA_OPTS="-Xmx1g" scala -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null)
-}
-
-function scala_assert_elong {
- (ulimit -t 90; 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 "knight1.scala runs?" | tee -a $out
-
-if (scala_compile knight1.scala)
-then
- echo -e " --> success " | tee -a $out
- tsts=$(( 0 ))
-else
- echo -e " --> SCALA DID NOT RUN KNIGHT1.SCALA\n" | tee -a $out
- tsts=$(( 1 ))
-fi
-
-
-# knights1: purity test
-if [ $tsts -eq 0 ]
- then
- echo -e "knight1.scala does not contain VARS, RETURNS etc?" | tee -a $out
-
- if (scala_vars knight1.scala)
- then
- echo -e " --> FAIL\n" | tee -a $out
- tsts=$(( 1 ))
- else
- echo -e " --> success" | tee -a $out
- tsts=$(( 0 ))
- fi
-else
- tsts=$(( 1 ))
-fi
-
-echo >> $out
-
-### knight1 test
-
-if [ $tsts -eq 0 ]
-then
- echo " is_legal(8, Nil, (3, 4)) == true " | tee -a $out
- echo " is_legal(8, List((4, 1), (1, 0)), (4, 1)) == false " | tee -a $out
- echo " is_legal(2, Nil, (0, 0)) == true" | tee -a $out
-
- if (scala_assert "knight1.scala" "knight1_test1.scala")
- then
- echo -e " --> success" | tee -a $out
- marks=$(( marks + 1.0 ))
- else
- echo -e " --> \n ONE TEST FAILED\n"| tee -a $out
- fi
-fi
-
-### knight2 test
-
-if [ $tsts -eq 0 ]
-then
- echo " legal_moves(8, Nil, (2,2)) == List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4))" | tee -a $out
- echo " legal_moves(8, Nil, (7,7)) == List((6,5), (5,6))" | tee -a $out
- echo " legal_moves(8, List((4,1), (1,0)), (2,2)) == List((3,4), (4,3), (3,0), (0,1), (0,3), (1,4))" | tee -a $out
- echo " legal_moves(8, Nil, (0,1)) == List((1,3), (2,2), (2,0))" | tee -a $out
- echo " legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6))" | tee -a $out
- echo " legal_moves(1, Nil, (0,0)) == Nil" | tee -a $out
- echo " legal_moves(2, Nil, (0,0)) == Nil" | tee -a $out
- echo " legal_moves(3, Nil, (0,0)) == List((1,2), (2,1))" | tee -a $out
-
- if (scala_assert "knight1.scala" "knight1_test2.scala")
- then
- echo -e " --> success\n" | tee -a $out
- marks=$(( marks + 1 ))
- else
- echo -e " --> ONE TEST FAILED\n" | tee -a $out
- fi
-fi
-
-
-### knight3 test
-
-if [ $tsts -eq 0 ]
-then
- echo " count_tours from every position on the board 1 - 4 (0.5% marks)" | tee -a $out
- echo " dim = 1: 1" | tee -a $out
- echo " 2: 0,0,0,0" | tee -a $out
- echo " 3: 0,0,0,0,0,0,0,0,0" | tee -a $out
- echo " 4: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" | tee -a $out
- START=$(date +%s)
-
- if (scala_assert_thirty "knight1.scala" "knight1_test3a.scala")
- then
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- #echo " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> success\n" | tee -a $out
- marks=$(( marks + 0.5 ))
- else
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> ONE TEST FAILED\n" | tee -a $out
- fi
-fi
-
-
-
-if [ $tsts -eq 0 ]
-then
- echo " count_tours from every position on the board of dim 5 for the first 3 rows (0.5% marks)" | tee -a $out
- echo " dim = 5: 304,0,56,0,304,0,56,0,56,0,56,0,64,0,56)" | tee -a $out
- START=$(date +%s)
-
- if (scala_assert_thirty "knight1.scala" "knight1_test3b.scala")
- then
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- #echo " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> success\n" | tee -a $out
- marks=$(( marks + 0.5 ))
- else
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> ONE TEST FAILED\n" | tee -a $out
- fi
-fi
-
-
-
-if [ $tsts -eq 0 ]
-then
- echo " enum_tours(5, List((0,2)) ) => 56 tours? and all correct?" | tee -a $out
- echo " enum_tours(5, List((0,0)) ) => 304 tours? and all correct?" | tee -a $out
- START=$(date +%s)
-
- if (scala_assert_thirty "knight1.scala" "knight1_test3c.scala")
- then
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- #echo " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> success\n" | tee -a $out
- marks=$(( marks + 1.0 ))
- else
- END=$(date +%s)
- DIFF=$(( $END - $START ))
- echo " This test ran for $DIFF seconds." | tee -a $out
- echo -e " --> \n ONE TEST FAILED\n" | tee -a $out
- fi
-fi
-
-
-## final marks
-echo -e "Overall mark for the Preliminary Part 4 (Scala)" | tee -a $out
-printf " %0.1f\n" $marks | tee -a $out
-
-
-
--- a/pre_marking4/knight1_test1.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-import CW9a._
-
-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)
-
-
-
-
--- a/pre_marking4/knight1_test2.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-import CW9a._
-
-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, Nil, (0,1)) == List((1,3), (2,2), (2,0)))
-assert(legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6)))
-assert(legal_moves(1, Nil, (0,0)) == Nil)
-assert(legal_moves(2, Nil, (0,0)) == Nil)
-assert(legal_moves(3, Nil, (0,0)) == List((1,2), (2,1)))
-
--- a/pre_marking4/knight1_test3a.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-import CW9a._
-
-def count_all_tours_urban(dim: Int) = {
- for (i <- (0 until dim).toList;
- j <- (0 until dim).toList) yield count_tours(dim, List((i, j)))
-}
-
-
-assert(count_all_tours_urban(1) == List(1))
-assert(count_all_tours_urban(2) == List(0, 0, 0, 0))
-assert(count_all_tours_urban(3) == List(0, 0, 0, 0, 0, 0, 0, 0, 0))
-assert(count_all_tours_urban(4) == List(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
-
-
--- a/pre_marking4/knight1_test3b.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-import CW9a._
-//type Pos = (Int, Int) // a position on a chessboard
-//type Path = List[Pos] // a path...a list of positions
-
-/*
-def count_all_tours_urban(dim: Int) = {
- for (i <- (0 until dim).toList;
- j <- (0 until dim).toList) yield count_tours(dim, List((i, j)))
-}
-*/
-
-def count_all_tours_urban(dim: Int) = {
- for (i <- (0 until 3).toList;
- j <- (0 until dim).toList) yield count_tours(dim, List((i, j)))
-}
-
-
-assert(count_all_tours_urban(5) == List(304, 0, 56, 0, 304, 0, 56, 0, 56, 0, 56, 0, 64, 0, 56))
-
--- a/pre_marking4/knight1_test3c.scala Thu Jan 13 12:55:03 2022 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-import CW9a._
-
-//type Pos = (Int, Int) // a position on a chessboard
-//type Path = List[Pos] // a path...a list of positions
-
-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 ts00_urban = enum_tours(5, List((0, 0)))
-assert(ts00_urban.map(correct_urban(5)).forall(_ == true) == true)
-assert(ts00_urban.length == 304)
-
-
-val ts_urban = enum_tours(5, List((0, 2)))
-assert(ts_urban.map(correct_urban(5)).forall(_ == true) == true)
-assert(ts_urban.length == 56)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/progs/mandelbrot3.sc Mon Apr 11 23:55:27 2022 +0100
@@ -0,0 +1,201 @@
+// Mandelbrot pictures
+//=====================
+//
+// see https://en.wikipedia.org/wiki/Mandelbrot_set
+//
+// under scala 2.13.1 needs to be called with
+//
+// scala -cp scala-parallel-collections_2.13-0.2.0.jar mandelbrot.scala
+//
+// scala-cli run --jar scala-parallel-collections_3-1.0.4.jar mandelbrot3.sc
+
+
+import java.awt.Color
+import java.awt.Dimension
+import java.awt.Graphics
+import java.awt.Graphics2D
+import java.awt.image.BufferedImage
+import javax.swing.JFrame
+import javax.swing.JPanel
+import javax.swing.WindowConstants
+import scala.language.implicitConversions
+import scala.collection.parallel.CollectionConverters._
+
+object Test {
+
+def main() = {
+
+// complex numbers
+case class Complex(val re: Double, val im: Double) {
+ // represents the complex number re + im * i
+ def +(that: Complex) = Complex(this.re + that.re, this.im + that.im)
+ def -(that: Complex) = Complex(this.re - that.re, this.im - that.im)
+ def *(that: Complex) = Complex(this.re * that.re - this.im * that.im,
+ this.re * that.im + that.re * this.im)
+ def *(that: Double) = Complex(this.re * that, this.im * that)
+ def abs() = Math.sqrt(this.re * this.re + this.im * this.im)
+}
+
+// to allow the notation n + m * i
+object i extends Complex(0, 1)
+
+given Conversion[Double, Complex] = Complex(_, 0)
+
+
+// some customn colours for the "sliding effect"
+val colours = List(
+ new Color(66, 30, 15), new Color(25, 7, 26),
+ new Color(9, 1, 47), new Color(4, 4, 73),
+ new Color(0, 7, 100), new Color(12, 44, 138),
+ new Color(24, 82, 177), new Color(57, 125, 209),
+ new Color(134, 181, 229), new Color(211, 236, 248),
+ new Color(241, 233, 191), new Color(248, 201, 95),
+ new Color(255, 170, 0), new Color(204, 128, 0),
+ new Color(153, 87, 0), new Color(106, 52, 3))
+
+// the viewer panel with an image canvas
+class Viewer(width: Int, height: Int) extends JPanel {
+ val canvas = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
+
+ override def paintComponent(g: Graphics) =
+ g.asInstanceOf[Graphics2D].drawImage(canvas, null, null)
+
+ override def getPreferredSize() =
+ new Dimension(width, height)
+
+ def clearCanvas(color: Color) = {
+ for (x <- 0 to width - 1; y <- 0 to height - 1)
+ canvas.setRGB(x, y, color.getRGB())
+ repaint()
+ }
+}
+
+// initialising the viewer panel
+def openViewer(width: Int, height: Int) : Viewer = {
+ val frame = new JFrame("XYPlane")
+ val viewer = new Viewer(width, height)
+ frame.add(viewer)
+ frame.pack()
+ frame.setVisible(true)
+ frame.setResizable(false)
+ frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE)
+ viewer
+}
+
+// some hardcoded parameters
+val W = 900 // width
+val H = 800 // height
+val black = Color.black
+val viewer = openViewer(W, H)
+
+// draw a pixel on the canvas
+def pixel(x: Int, y: Int, color: Color) =
+ viewer.canvas.setRGB(x, y, color.getRGB())
+
+
+// calculates the number of iterations using lazy lists (streams)
+// the iteration goes on for a maximum of max steps,
+// but might leave early when the pred is satisfied
+def iterations(c: Complex, max: Int) : Int = {
+ def next(z: Complex) = z * z + c
+ def pred(z: Complex) = z.abs() < 2 // exit condition
+ LazyList.iterate(0.0 * i, max)(next).takeWhile(pred).size
+}
+
+// main function
+// start and end are the upper-left and lower-right corners,
+// max is the number of maximum iterations
+def mandelbrot(start: Complex, end: Complex, max: Int) : Unit = {
+ viewer.clearCanvas(black)
+
+ // deltas for each grid step
+ val d_x = (end.re - start.re) / W
+ val d_y = (end.im - start.im) / H
+
+ for (y <- (0 until H).par) {
+ for (x <- (0 until W).par) {
+
+ val c = start +
+ (x * d_x + y * d_y * i)
+ val iters = iterations(c, max)
+ val col =
+ if (iters == max) black
+ else colours(iters % 16)
+
+ pixel(x, y, col)
+ }
+ viewer.updateUI()
+ }
+}
+
+
+// Examples
+//==========
+
+//for measuring time
+def time_needed[T](code: => T) = {
+ val start = System.nanoTime()
+ code
+ val end = System.nanoTime()
+ (end - start) / 1.0e9
+}
+
+
+
+// example 1
+val exa1 = -2.0 + -1.5 * i
+val exa2 = 1.0 + 1.5 * i
+
+println(s"${time_needed(mandelbrot(exa1, exa2, 1000))} secs")
+
+// example 2
+val exb1 = -0.37465401 + 0.659227668 * i
+val exb2 = -0.37332410 + 0.66020767 * i
+
+//time_needed(mandelbrot(exb1, exb2, 1000))
+
+// example 3
+val exc1 = 0.435396403 + 0.367981352 * i
+val exc2 = 0.451687191 + 0.380210061 * i
+
+//time_needed(mandelbrot(exc1, exc2, 1000))
+
+
+
+// some more computations with example 3
+
+val delta = (exc2 - exc1) * 0.0333
+
+println(s"${time_needed(
+ for (n <- (0 to 12))
+ mandelbrot(exc1 + delta * n,
+ exc2 - delta * n, 100))} secs")
+
+
+
+// Larry Paulson's example
+val exl1 = -0.74364990 + 0.13188170 * i
+val exl2 = -0.74291189 + 0.13261971 * i
+
+//println(s"${time_needed(mandelbrot(exl1, exl2, 1000))} secs")
+
+
+// example by Jorgen Villadsen
+val exj1 = 0.10284 - 0.63275 * i
+val exj2 = 0.11084 - 0.64075 * i
+
+//time_needed(mandelbrot(exj1, exj2, 1000))
+
+
+// another example
+val exA = 0.3439274 + 0.6516478 * i
+val exB = 0.3654477 + 0.6301795 * i
+
+//time_needed(mandelbrot(exA, exB, 1000))
+
+
+}
+
+}
+
+Test.main()