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