# HG changeset patch # User Christian Urban # Date 1753112287 -3600 # Node ID 253d1ccb65de705471eaee44a1f9b0b945af833f # Parent 244df77507c203821b73615726c5e4f19bafd1a0 updated diff -r 244df77507c2 -r 253d1ccb65de core_marking1/collatz_test.sh --- a/core_marking1/collatz_test.sh Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking1/collatz_test.sh Mon Jul 21 16:38:07 2025 +0100 @@ -22,17 +22,21 @@ # marks for core part 1 marks=$(( 0 )) + +# compilation tests + # compilation tests function scala_compile { - (JAVA_OPTS="-Xmx1g" scala -Xprint:parser "$1" 2> c$out 1> c$out) + (ulimit -t 30; scala-cli compile --server=false -color never -Xprint:parser "$1" 2> c$out 1> c$out) } # functional tests function scala_assert { - (JAVA_OPTS="-Xmx1g" scala -nc -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null) + (ulimit -t 30; scala-cli --server=false -i "$1" "$2" -e "urbanmain()" 2> /dev/null 1> /dev/null) } + # purity test function scala_vars { diff -r 244df77507c2 -r 253d1ccb65de core_marking1/collatz_test1.scala --- a/core_marking1/collatz_test1.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking1/collatz_test1.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,8 +1,11 @@ +def urbanmain() = { + import C1._ -assert(C1.collatz(1) == 0) -assert(C1.collatz(6) == 8) -assert(C1.collatz(9) == 19) -assert(C1.collatz(9000) == 47) + assert(C1.collatz(1) == 0) + assert(C1.collatz(6) == 8) + assert(C1.collatz(9) == 19) + assert(C1.collatz(9000) == 47) +} diff -r 244df77507c2 -r 253d1ccb65de core_marking1/collatz_test2.scala --- a/core_marking1/collatz_test2.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking1/collatz_test2.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,10 +1,12 @@ -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)) +def urbanmain() = { + 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)) +} diff -r 244df77507c2 -r 253d1ccb65de core_marking1/collatz_test3.scala --- a/core_marking1/collatz_test3.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking1/collatz_test3.scala Mon Jul 21 16:38:07 2025 +0100 @@ -3,10 +3,13 @@ import ExecutionContext.Implicits.global import scala.language.postfixOps -lazy val f = Future { -assert(C1.last_odd(113) == 85) -assert(C1.last_odd(84) == 21) -assert(C1.last_odd(605) == 341) +def urbanmain() = { + + lazy val f = Future { + assert(C1.last_odd(113) == 85) + assert(C1.last_odd(84) == 21) + assert(C1.last_odd(605) == 341) + } + + Await.result(f, 32 second) } - -Await.result(f, 32 second) diff -r 244df77507c2 -r 253d1ccb65de core_marking2/docdiff_test.sh --- a/core_marking2/docdiff_test.sh Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking2/docdiff_test.sh Mon Jul 21 16:38:07 2025 +0100 @@ -25,13 +25,13 @@ # compilation tests function scala_compile { - (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -Xprint:parser "$1" 2> c$out 1> c$out) + (ulimit -t 30; scala-cli compile --server=false -color never -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) + (ulimit -t 30; scala-cli --server=false -i "$1" "$2" -e "urbanmain()" 2> /dev/null 1> /dev/null) } # purity test diff -r 244df77507c2 -r 253d1ccb65de core_marking2/docdiff_test1.scala --- a/core_marking2/docdiff_test1.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking2/docdiff_test1.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,4 +1,7 @@ -import C2._ + +def urbanmain() = { + import C2._ -assert(clean("ab a abc") == List("ab", "a", "abc")) -assert(clean("ab*a abc1") == List("ab", "a", "abc1")) + assert(clean("ab a abc") == List("ab", "a", "abc")) + assert(clean("ab*a abc1") == List("ab", "a", "abc1")) +} diff -r 244df77507c2 -r 253d1ccb65de core_marking2/docdiff_test2.scala --- a/core_marking2/docdiff_test2.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking2/docdiff_test2.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,10 +1,12 @@ -import C2._ +def urbanmain() = { + import C2._ -assert(occurrences(List("a", "b", "b", "c", "d")) == Map("a" -> 1, "b" -> 2, "c" -> 1, "d" -> 1)) + 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("d", "b", "d", "b", "d")) == Map("d" -> 3, "b" -> 2)) -assert(occurrences(List("b", "b", "b", "b", "b")) == Map("b" -> 5)) + assert(occurrences(List("b", "b", "b", "b", "b")) == Map("b" -> 5)) -assert(occurrences(Nil) == Map()) + assert(occurrences(Nil) == Map()) +} diff -r 244df77507c2 -r 253d1ccb65de core_marking2/docdiff_test3.scala --- a/core_marking2/docdiff_test3.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking2/docdiff_test3.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,15 +1,17 @@ -import C2._ +def urbanmain() = { + import C2._ -val urban_list1 = List("a", "b", "b", "c", "d") -val urban_list2 = List("d", "b", "d", "b", "d") + 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) + 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") + 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) + assert(prod(urban_listA, urban_listB) == 0) +} diff -r 244df77507c2 -r 253d1ccb65de core_marking2/docdiff_test4.scala --- a/core_marking2/docdiff_test4.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking2/docdiff_test4.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,9 +1,12 @@ -import C2._ + +def urbanmain() = { + import C2._ -val urban_list1 = List("a", "b", "b", "c", "d") -val urban_list2 = List("d", "b", "d", "b", "d") + 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) + assert(overlap(urban_list1, urban_list2) == 0.5384615384615384) + assert(overlap(urban_list1, urban_list1) == 1.0) + assert(overlap(urban_list2, urban_list2) == 1.0) +} diff -r 244df77507c2 -r 253d1ccb65de core_marking3/postfix_test.sh --- a/core_marking3/postfix_test.sh Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking3/postfix_test.sh Mon Jul 21 16:38:07 2025 +0100 @@ -20,17 +20,16 @@ # 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) + (ulimit -t 30; scala-cli compile --server=false -color never -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) + (ulimit -t 30; scala-cli --server=false -i "$1" "$2" -e "urbanmain()" 2> /dev/null 1> /dev/null) } # purity test diff -r 244df77507c2 -r 253d1ccb65de core_marking3/postfix_test1.scala --- a/core_marking3/postfix_test1.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking3/postfix_test1.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,7 +1,10 @@ -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", "/")) +def urbanmain() = { + 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", "/")) +} diff -r 244df77507c2 -r 253d1ccb65de core_marking3/postfix_test2.scala --- a/core_marking3/postfix_test2.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking3/postfix_test2.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,8 +1,11 @@ -import C3a._ + +def urbanmain() = { + 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) + 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) +} diff -r 244df77507c2 -r 253d1ccb65de core_marking3/postfix_test3.scala --- a/core_marking3/postfix_test3.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking3/postfix_test3.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,9 +1,11 @@ -import C3b._ + +def urbanmain() = { + import C3b._ -assert(syard(split("3 + 4 * ( 2 - 1 )")) == List("3", "4", "2", "1", "-", "*", "+")) -assert(syard(split("( ( ( 3 ) ) + ( ( 4 + ( 5 ) ) ) )")) == List("3", "4", "5", "+", "+")) -assert(syard(split("5 + 7 / 2")) == List("5", "7", "2", "/", "+")) -assert(syard(split("5 * 7 / 2")) == List("5", "7", "*", "2", "/")) -assert(syard(split("3 + 4 * 8 / ( 5 - 1 ) ^ 2 ^ 3")) == List("3", "4", "8", "*", "5", "1", "-", "2", "3", "^", "^", "/", "+")) - + assert(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", "^", "^", "/", "+")) +} diff -r 244df77507c2 -r 253d1ccb65de core_marking3/postfix_test4.scala --- a/core_marking3/postfix_test4.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/core_marking3/postfix_test4.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,13 +1,16 @@ -import C3b._ + +def urbanmain() = { + 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) + 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) +} diff -r 244df77507c2 -r 253d1ccb65de cws/disclaimer.sty --- a/cws/disclaimer.sty Sun Sep 15 12:57:59 2024 +0100 +++ b/cws/disclaimer.sty Mon Jul 21 16:38:07 2025 +0100 @@ -98,7 +98,7 @@ your \textbf{own} effort! You have implemented the code entirely on your own. You have not copied from anyone else. Do not be tempted to ask Copilot for help or -do any other shenanigans like this! An exception is the Scala +do any other AI-shenanigans like this! An exception is the Scala code I showed during the lectures or uploaded to KEATS, which you can freely use.\bigskip } diff -r 244df77507c2 -r 253d1ccb65de cws/main_cw05.pdf Binary file cws/main_cw05.pdf has changed diff -r 244df77507c2 -r 253d1ccb65de cws/main_cw05.tex --- a/cws/main_cw05.tex Sun Sep 15 12:57:59 2024 +0100 +++ b/cws/main_cw05.tex Mon Jul 21 16:38:07 2025 +0100 @@ -24,7 +24,7 @@ \noindent This part is about a small (esoteric) programming language called -brainf***. We will implement an interpreter and compiler for +brainf***. The task is to implement an interpreter and compiler for this language.\bigskip %\IMPORTANT{This part is worth 10\% and you need to submit it on \cwTEN{} at 5pm. @@ -113,7 +113,9 @@ Some relatively sophisticated sample programs in brainf*** are given in the file \texttt{bf.scala}, including a brainf*** program for the -Sierpinski triangle and the Mandelbrot set. There seems to be even a +Sierpinski triangle and the Mandelbrot set.\footnote{Of course somebody +tried LLMs for writing bf-programs. As expected, they did spectacularly +badly in this task. \hr{https://www.reddit.com/r/programming/comments/1m4rk3r/comment/n49qrnv/}} There seems to be even a dedicated Windows IDE for bf programs, though I am not sure whether this is just an elaborate April fools' joke---judge yourself: diff -r 244df77507c2 -r 253d1ccb65de cws/resit2.tex --- a/cws/resit2.tex Sun Sep 15 12:57:59 2024 +0100 +++ b/cws/resit2.tex Mon Jul 21 16:38:07 2025 +0100 @@ -52,9 +52,9 @@ \noindent You are asked to implement a Scala program for playing the Shogun -board game. The deadline for your submission is on 26th July at +board game. The deadline for your submission is on 31th July at 16:00. Make sure you use \texttt{scala-cli} and Scala version \textbf{3.XX} -for the resit---the same version as during the lectures. \medskip +for the resit. \medskip \IMPORTANTNONE{} @@ -115,7 +115,7 @@ above. What sets Shogun apart from chess and checkers is that each piece has, what I call, a kind of \textit{energy}---which for pawns is a number between 1 and 4, and for kings between 1 and 2. The energy -determines how far a piece has to move. In the physical version of +determines how far a piece can move. In the physical version of Shogun, the pieces and the board have magnets that can change the energy of a piece from move to move---so a piece on one field can have energy 2 and on a different field the same piece might have energy @@ -136,7 +136,7 @@ \begin{itemize} \item The energy of a piece determines how far, that is how many - fields, a piece has to move (remember pawns have an energy between 1 -- + fields, a piece can move (remember pawns have an energy between 1 -- 4, kings have an energy of only 1 -- 2). The energy of a piece might change when the piece moves to new field. \item Pieces can move in straight lines (up, down, left, right), or in @@ -251,7 +251,7 @@ Useful functions about pieces and boards are defined at the beginning of the template file. The function \texttt{.map} applies a function to -each element of a list or set; \texttt{.flatMap} works like +each element of a list or a set; \texttt{.flatMap} works like \texttt{map} followed by a \texttt{.flatten}---this is useful if a function returns a set of sets, which need to be ``unioned up''. Sets can be partitioned according to a predicate with the function @@ -317,8 +317,8 @@ case object D extends Move // down case object R extends Move // right case object L extends Move // left -case object RU extends Move // ... -case object LU extends Move +case object RU extends Move // right-up +case object LU extends Move // ... case object RD extends Move case object LD extends Move case object UR extends Move diff -r 244df77507c2 -r 253d1ccb65de handouts/pep-ho.pdf Binary file handouts/pep-ho.pdf has changed diff -r 244df77507c2 -r 253d1ccb65de handouts/pep-ho.tex --- a/handouts/pep-ho.tex Sun Sep 15 12:57:59 2024 +0100 +++ b/handouts/pep-ho.tex Mon Jul 21 16:38:07 2025 +0100 @@ -186,24 +186,24 @@ \noindent\alert For PEP, make sure you are using the version 3(!) of Scala. This is the version I am going to use in the lectures and in the coursework. This -can be any version of Scala 3.X where $X=\{3,4\}$. Also the minor +can be any version of Scala 3.X where $X=\{4,5\}$. Also the minor number does not matter. Note that this will be the second year I am using this newer version of Scala -- some hiccups can still happen. Apologies in advance!\bigskip -\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black] - I will be using the \textbf{\texttt{scala-cli}} REPL for Scala 3, rather - than the ``plain'' Scala REPL. This is a batteries included version of - Scala 3 and is easier to use and to install. In fact - \texttt{scala-cli} is designated to replace - the ``plain'' Scala REPL in future versions of Scala. - So why not using it now? - It can be downloaded from: - - \begin{center} - \url{https://scala-cli.virtuslab.org} - \end{center} -\end{tcolorbox}\medskip +%\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black] +% I will be using the \textbf{\texttt{scala-cli}} REPL for Scala 3, rather +% than the ``plain'' Scala REPL. This is a batteries included version of +% Scala 3 and is easier to use and to install. In fact +% \texttt{scala-cli} is designated to replace +% the ``plain'' Scala REPL in future versions of Scala. +% So why not using it now? +% It can be downloaded from:% +% +% \begin{center} +% \url{https://scala-cli.virtuslab.org} +% \end{center} +%\end{tcolorbox}\medskip \noindent @@ -251,7 +251,7 @@ I have also bound the keys \keys{Ctrl} \keys{Ret} to the action ``Run-Selected-Text-In-Active-Terminal'' in order to quickly evaluate small code snippets in the Scala REPL. I use Codium's internal - terminal to run \texttt{scala-cli} version 1.0.5 which + terminal to run \texttt{scala} version 1.0.5 which uses Scala 3.3.1.\label{vscode}} \end{boxedminipage} \end{figure} @@ -284,7 +284,7 @@ \noindent But you should be careful if you use them for your coursework: they are meant to play around, not really for serious work. Therefore make -sure \texttt{scala-cli} works on your own machine ASAP! +sure \texttt{scala} works on your own machine ASAP! As one might expect, Scala can be used with the heavy-duty IDEs Eclipse and IntelliJ. For example IntelliJ includes plugins for @@ -534,30 +534,30 @@ \subsection*{The Very Basics} -Let us get back to Scala and \texttt{scala-cli}: One advantage of +Let us get back to Scala: One advantage of Scala over Java is that it includes an interpreter (a REPL, or \underline{R}ead-\underline{E}val-\underline{P}rint-\underline{L}oop) with which you can run and test small code snippets without the need of a compiler. This helps a lot with interactively developing programs. It is my preferred way of writing small Scala programs. Once -you installed \texttt{scala-cli}, you can start the interpreter by typing on the +you installed \texttt{scala}, you can start the interpreter by typing on the command line: \begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small] -$ scala-cli -Welcome to Scala 3.4.1 (21.0.2, Java OpenJDK 64-Bit Server VM). -Type in expressions for evaluation. Or try :help. +$ scala +Welcome to Scala 3.5.1 (21.0.4, Java OpenJDK 64-Bit Server VM). +Type in expressions for evaluation. Or try :help. scala> \end{lstlisting}%$ \noindent The precise response may vary depending on the version and -platform where you installed \texttt{scala-cli}. Make sure however that -\texttt{scala-cli} uses Scala version 3---you can find the version +platform where you installed \texttt{scala}. Make sure however that +\texttt{scala} uses version 3---you can find the version number in the welcome message. Also note that at the first time -\texttt{scala-cli} runs, it might download various components, for +\texttt{scala} runs, it might download various components, for example the Scala compiler, Scala runtimes etc. Once -\texttt{scala-cli} is up and running, you can type at the prompt +\texttt{scala} is up and running, you can type at the prompt expressions like \code{2 + 3}\;\keys{Ret} and the output will be \begin{lstlisting}[numbers=none,language={}] @@ -595,7 +595,7 @@ now, the latter kind of functions always has \code{Unit} as return type. It is just not printed by Scala. -You can try more examples with the \texttt{scala-cli} REPL, but feel free to +You can try more examples with the \texttt{scala} REPL, but feel free to first guess what the result is (not all answers by Scala are obvious): \begin{lstlisting}[numbers=none,language={}] @@ -654,11 +654,11 @@ %} \noindent save it in a file, say {\tt hello-world.scala}, and -then use \texttt{scala-cli} (which compiles the +then use \texttt{scala} (which compiles the scala file and runs it): \begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small] -$ scala-cli hello-world.scala +$ scala hello-world.scala hello world \end{lstlisting} @@ -668,7 +668,7 @@ Runtime. This can be done as follows: \begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small] -$ scala-cli --power package --assembly hello-world.scala +$ scala --power package --assembly hello-world.scala $ java -jar Hello.jar hello world \end{lstlisting} diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test.sh --- a/main_marking3/re_test.sh Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test.sh Mon Jul 21 16:38:07 2025 +0100 @@ -21,19 +21,20 @@ # compilation tests function scala_compile { - (ulimit -t 30; JAVA_OPTS="-Xmx1g" scala -Xprint:parser "$1" 2> c$out 1> c$out) + (ulimit -t 30; scala-cli compile --server=false -color never -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) + (ulimit -t 30; scala-cli --server=false -i "$1" "$2" -e "urbanmain()" 2> /dev/null 1> /dev/null) } function scala_assert_thirty { - (ulimit -t 40; JAVA_OPTS="-Xmx1g" scala -nc -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null) + (ulimit -t 40; scala-cli --server=false -i "$1" "$2" -e "urbanmain()" 2> /dev/null 1> /dev/null) } + # purity test function scala_vars { (sed 's/immutable/ok/g' c$out > cb$out; diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test0.scala --- a/main_marking3/re_test0.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test0.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,6 +1,8 @@ -import M3._ + +def urbanmain() = { + import M3._ -assert(ALTs.getClass == ALTs.getClass) -assert(SEQs.getClass == SEQs.getClass) + assert(ALTs.getClass == ALTs.getClass) + assert(SEQs.getClass == SEQs.getClass) +} - diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test1.scala --- a/main_marking3/re_test1.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test1.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,14 +1,17 @@ -import M3._ - -assert(nullable(ZERO) == false) -assert(nullable(ONE) == true) -assert(nullable(CHAR('a')) == false) -assert(nullable(ZERO | ONE) == true) -assert(nullable(ZERO | CHAR('a')) == false) -assert(nullable(ONE ~ ONE) == true) -assert(nullable(ONE ~ CHAR('a')) == false) -assert(nullable(STAR(ZERO)) == true) -assert(nullable(ALTs(List(ONE, CHAR('a'), ZERO))) == true) -assert(nullable(SEQs(List(ONE, ALTs(List(ONE, CHAR('a'), ZERO)), STAR(ZERO)))) == true) +def urbanmain() = { + import M3._ + + assert(nullable(ZERO) == false) + assert(nullable(ONE) == true) + assert(nullable(CHAR('a')) == false) + assert(nullable(ZERO | ONE) == true) + assert(nullable(ZERO | CHAR('a')) == false) + assert(nullable(ONE ~ ONE) == true) + assert(nullable(ONE ~ CHAR('a')) == false) + assert(nullable(STAR(ZERO)) == true) + assert(nullable(ALTs(List(ONE, CHAR('a'), ZERO))) == true) + assert(nullable(SEQs(List(ONE, ALTs(List(ONE, CHAR('a'), ZERO)), STAR(ZERO)))) == true) +} + diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test2.scala --- a/main_marking3/re_test2.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test2.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,26 +1,30 @@ -import M3._ + +def urbanmain() = { + + import M3._ -assert(der('a', ZERO | ONE) == ALT(ZERO, ZERO)) -assert(der('a', (CHAR('a') | ONE) ~ CHAR('a')) == ALTs(List(SEQ(ALT(ONE, ZERO), CHAR('a')), SEQs(List(ONE))))) -assert(der('a', (CHAR('a') | CHAR('a')) ~ CHAR('a')) == (ONE | ONE) ~ CHAR('a')) -assert(der('a', STAR(CHAR('a'))) == (ONE ~ STAR(CHAR('a')))) -assert(der('b', STAR(CHAR('a'))) == (ZERO ~ STAR(CHAR('a')))) + assert(der('a', ZERO | ONE) == ALT(ZERO, ZERO)) + assert(der('a', (CHAR('a') | ONE) ~ CHAR('a')) == ALTs(List(SEQ(ALT(ONE, ZERO), CHAR('a')), SEQs(List(ONE))))) + assert(der('a', (CHAR('a') | CHAR('a')) ~ CHAR('a')) == (ONE | ONE) ~ CHAR('a')) + assert(der('a', STAR(CHAR('a'))) == (ONE ~ STAR(CHAR('a')))) + assert(der('b', STAR(CHAR('a'))) == (ZERO ~ STAR(CHAR('a')))) -val r0_urban = "a" ~ "b" ~ "c" -assert(der('a', r0_urban) == (ONE ~ "b") ~ "c") -assert(der('b', r0_urban) == (ZERO ~ "b") ~ "c") -assert(der('c', r0_urban) == (ZERO ~ "b") ~ "c") + val r0_urban = "a" ~ "b" ~ "c" + assert(der('a', r0_urban) == (ONE ~ "b") ~ "c") + assert(der('b', r0_urban) == (ZERO ~ "b") ~ "c") + assert(der('c', r0_urban) == (ZERO ~ "b") ~ "c") -val r1_urban = (ONE ~ "b") ~ "c" + val r1_urban = (ONE ~ "b") ~ "c" -assert(der('a', r1_urban) == ((ZERO ~ "b") | SEQs(List(ZERO))) ~ "c") -assert(der('b', r1_urban) == ((ZERO ~ "b") | SEQs(List(ONE))) ~ "c") -assert(der('c', r1_urban) == ((ZERO ~ "b") | SEQs(List(ZERO))) ~ "c") + assert(der('a', r1_urban) == ((ZERO ~ "b") | SEQs(List(ZERO))) ~ "c") + assert(der('b', r1_urban) == ((ZERO ~ "b") | SEQs(List(ONE))) ~ "c") + assert(der('c', r1_urban) == ((ZERO ~ "b") | SEQs(List(ZERO))) ~ "c") + + val r2_urban = ((ZERO ~ "b") | ONE) ~ "c" -val r2_urban = ((ZERO ~ "b") | ONE) ~ "c" + assert(der('a', r2_urban) == ((((ZERO ~ "b") | ZERO) ~ "c") | SEQs(List(ZERO)))) + assert(der('b', r2_urban) == ((((ZERO ~ "b") | ZERO) ~ "c") | SEQs(List(ZERO)))) + assert(der('c', r2_urban) == ((((ZERO ~ "b") | ZERO) ~ "c") | SEQs(List(ONE)))) +} -assert(der('a', r2_urban) == ((((ZERO ~ "b") | ZERO) ~ "c") | SEQs(List(ZERO)))) -assert(der('b', r2_urban) == ((((ZERO ~ "b") | ZERO) ~ "c") | SEQs(List(ZERO)))) -assert(der('c', r2_urban) == ((((ZERO ~ "b") | ZERO) ~ "c") | SEQs(List(ONE)))) - diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test3.scala --- a/main_marking3/re_test3.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test3.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,22 +1,24 @@ -import M3._ + +def urbanmain() = { + import M3._ -assert(simp(ZERO | ONE) == ONE) -assert(simp(STAR(ZERO | ONE)) == STAR(ZERO | ONE)) -assert(simp(ONE ~ (ONE ~ (ONE ~ CHAR('a')))) == CHAR('a')) -assert(simp(((ONE ~ ONE) ~ ONE) ~ CHAR('a')) == CHAR('a')) -assert(simp(((ONE | ONE) ~ ONE) ~ CHAR('a')) == CHAR('a')) -assert(simp(ONE ~ (ONE ~ (ONE ~ ZERO))) == ZERO) -assert(simp(ALT(ONE ~ (ONE ~ (ONE ~ ZERO)), CHAR('a'))) == CHAR('a')) -assert(simp(CHAR('a') | CHAR('a')) == CHAR('a')) -assert(simp(CHAR('a') ~ CHAR('a')) == CHAR('a') ~ CHAR('a')) -assert(simp(ONE | CHAR('a')) == (ONE | CHAR('a'))) -assert(simp(ALT((CHAR('a') | ZERO) ~ ONE, + assert(simp(ZERO | ONE) == ONE) + assert(simp(STAR(ZERO | ONE)) == STAR(ZERO | ONE)) + assert(simp(ONE ~ (ONE ~ (ONE ~ CHAR('a')))) == CHAR('a')) + assert(simp(((ONE ~ ONE) ~ ONE) ~ CHAR('a')) == CHAR('a')) + assert(simp(((ONE | ONE) ~ ONE) ~ CHAR('a')) == CHAR('a')) + assert(simp(ONE ~ (ONE ~ (ONE ~ ZERO))) == ZERO) + assert(simp(ALT(ONE ~ (ONE ~ (ONE ~ ZERO)), CHAR('a'))) == CHAR('a')) + assert(simp(CHAR('a') | CHAR('a')) == CHAR('a')) + assert(simp(CHAR('a') ~ CHAR('a')) == CHAR('a') ~ CHAR('a')) + assert(simp(ONE | CHAR('a')) == (ONE | CHAR('a'))) + assert(simp(ALT((CHAR('a') | ZERO) ~ ONE, ((ONE | CHAR('b')) | CHAR('c')) ~ (CHAR('d') ~ ZERO))) == CHAR('a')) -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'))) -assert(simp(ALTs(Nil)) == ZERO) -assert(simp(SEQs(List(CHAR('a')))) == CHAR('a')) - + 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'))) + assert(simp(ALTs(Nil)) == ZERO) + assert(simp(SEQs(List(CHAR('a')))) == CHAR('a')) +} diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test3a.scala --- a/main_marking3/re_test3a.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test3a.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,10 +1,12 @@ -import M3._ +def urbanmain() = { + import M3._ -assert(flts(Nil) == Nil) -assert(flts(ZERO::ZERO::Nil) == List(ZERO)) -assert(flts(ZERO::ONE::ZERO::ONE::Nil) == List(ZERO)) -assert(flts(ONE::ALTs(List(ONE))::ONE::Nil) == List(ALTs(List(ONE)))) -assert(flts(ONE::ALTs(List(ONE))::ONE::ALTs(List(ONE))::Nil) == List(ALTs(List(ONE)), ALTs(List(ONE)))) -assert(flts(List(CHAR('a'), ONE, ONE, CHAR('b')), Nil) == List(CHAR('a'), CHAR('b'))) -assert(flts(List(ONE ~ CHAR('a'), CHAR('b') ~ ONE), Nil) == List(ONE, CHAR('a'), CHAR('b'), ONE)) + assert(flts(Nil) == Nil) + assert(flts(ZERO::ZERO::Nil) == List(ZERO)) + assert(flts(ZERO::ONE::ZERO::ONE::Nil) == List(ZERO)) + assert(flts(ONE::ALTs(List(ONE))::ONE::Nil) == List(ALTs(List(ONE)))) + assert(flts(ONE::ALTs(List(ONE))::ONE::ALTs(List(ONE))::Nil) == List(ALTs(List(ONE)), ALTs(List(ONE)))) + assert(flts(List(CHAR('a'), ONE, ONE, CHAR('b')), Nil) == List(CHAR('a'), CHAR('b'))) + assert(flts(List(ONE ~ CHAR('a'), CHAR('b') ~ ONE), Nil) == List(ONE, CHAR('a'), CHAR('b'), ONE)) +} diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test4.scala --- a/main_marking3/re_test4.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test4.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,5 +1,8 @@ -import M3._ + +def urbanmain() = { -assert(denest(List(ONE, ZERO, ALTs(List(ONE, CHAR('a'))))) - == List(ONE, ONE, CHAR('a'))) -assert(denest(List(ONE ~ ONE, ZERO, ZERO | ONE)) == List(ONE ~ ONE, ZERO, ONE)) + import M3._ + + assert(denest(List(ONE, ZERO, ALTs(List(ONE, CHAR('a'))))) == List(ONE, ONE, CHAR('a'))) + assert(denest(List(ONE ~ ONE, ZERO, ZERO | ONE)) == List(ONE ~ ONE, ZERO, ONE)) +} diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test5.scala --- a/main_marking3/re_test5.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test5.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,6 +1,9 @@ -import M3._ + +def urbanmain() = { + + import M3._ -assert(flts(List(CHAR('a'), ZERO, ONE), Nil) == List(ZERO)) -assert(flts(List(CHAR('a'), ONE, ONE, CHAR('b')), Nil) == List(CHAR('a'), CHAR('b'))) -assert(flts(List(ONE ~ CHAR('a'), CHAR('b') ~ ONE), Nil) == List(ONE, CHAR('a'), CHAR('b'), ONE)) - + assert(flts(List(CHAR('a'), ZERO, ONE), Nil) == List(ZERO)) + assert(flts(List(CHAR('a'), ONE, ONE, CHAR('b')), Nil) == List(CHAR('a'), CHAR('b'))) + assert(flts(List(ONE ~ CHAR('a'), CHAR('b') ~ ONE), Nil) == List(ONE, CHAR('a'), CHAR('b'), ONE)) +} diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test6.scala --- a/main_marking3/re_test6.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test6.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,10 +1,13 @@ -import M3._ + +def urbanmain() = { + import M3._ -assert(SEQs_smart(Nil) == ONE) -assert(SEQs_smart(List(ZERO)) == ZERO) -assert(SEQs_smart(List(CHAR('a'))) == CHAR('a')) -assert(SEQs_smart(List(ONE ~ ONE)) == ONE ~ ONE) -assert(SEQs_smart(List(ONE, ONE)) == SEQs(List(ONE, ONE))) -assert(ALTs_smart(Nil) == ZERO) -assert(ALTs_smart(List(ONE ~ ONE)) == ONE ~ ONE) -assert(ALTs_smart(List(ZERO, ZERO)) == ALTs(List(ZERO, ZERO))) + assert(SEQs_smart(Nil) == ONE) + assert(SEQs_smart(List(ZERO)) == ZERO) + assert(SEQs_smart(List(CHAR('a'))) == CHAR('a')) + assert(SEQs_smart(List(ONE ~ ONE)) == ONE ~ ONE) + assert(SEQs_smart(List(ONE, ONE)) == SEQs(List(ONE, ONE))) + assert(ALTs_smart(Nil) == ZERO) + assert(ALTs_smart(List(ONE ~ ONE)) == ONE ~ ONE) + assert(ALTs_smart(List(ZERO, ZERO)) == ALTs(List(ZERO, ZERO))) +} diff -r 244df77507c2 -r 253d1ccb65de main_marking3/re_test7.scala --- a/main_marking3/re_test7.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking3/re_test7.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,19 +1,22 @@ -import M3._ -val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b')) +def urbanmain() = { + import M3._ + + val EVIL_urban = SEQ(STAR(STAR(CHAR('a'))), CHAR('b')) -assert(ders(("a" * 5).toList, EVIL_urban) == SEQs(List(STAR(CHAR('a')), STAR(STAR(CHAR('a'))), CHAR('b')))) -assert(ders(List('b'), EVIL_urban) == ONE) -assert(ders(List('b','b'), EVIL_urban) == ZERO) -assert(matcher(EVIL_urban, "a" * 5 ++ "b") == true) -assert(matcher(EVIL_urban, "a" * 50 ++ "b") == true) -assert(matcher(EVIL_urban, "a" * 50) == false) -assert(matcher(EVIL_urban, "b") == true) -assert(matcher(EVIL_urban, "bb") == false) -assert(matcher("abc", "abc") == true) -assert(matcher("abc", "ab") == false) -assert(matcher(("ab" | "a") ~ (ONE | "bc"), "abc") == true) -assert(matcher(ONE, "") == true) -assert(matcher(ZERO, "") == false) -assert(matcher(ONE | CHAR('a'), "") == true) -assert(matcher(ONE | CHAR('a'), "a") == true) + assert(ders(("a" * 5).toList, EVIL_urban) == SEQs(List(STAR(CHAR('a')), STAR(STAR(CHAR('a'))), CHAR('b')))) + assert(ders(List('b'), EVIL_urban) == ONE) + assert(ders(List('b','b'), EVIL_urban) == ZERO) + assert(matcher(EVIL_urban, "a" * 5 ++ "b") == true) + assert(matcher(EVIL_urban, "a" * 50 ++ "b") == true) + assert(matcher(EVIL_urban, "a" * 50) == false) + assert(matcher(EVIL_urban, "b") == true) + assert(matcher(EVIL_urban, "bb") == false) + assert(matcher("abc", "abc") == true) + assert(matcher("abc", "ab") == false) + assert(matcher(("ab" | "a") ~ (ONE | "bc"), "abc") == true) + assert(matcher(ONE, "") == true) + assert(matcher(ZERO, "") == false) + assert(matcher(ONE | CHAR('a'), "") == true) + assert(matcher(ONE | CHAR('a'), "a") == true) +} diff -r 244df77507c2 -r 253d1ccb65de main_marking4/mk_main4 --- a/main_marking4/mk_main4 Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking4/mk_main4 Mon Jul 21 16:38:07 2025 +0100 @@ -10,33 +10,21 @@ 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 . - cp ../../../../../main_marking4/knight4_test10.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 - rm knight4_test10.scala + cp ../../../../main_marking4/shogun_test.sh . + cp ../../../../main_marking4/shogun_test1.scala . + cp ../../../../main_marking4/shogun_test2.scala . + cp ../../../../main_marking4/shogun_test3.scala . + cp ../../../../main_marking4/shogun_test4.scala . + cp ../../../../main_marking4/shogun_test5.scala . + cp ../../../../main_marking4/shogun_test6.scala . + ./shogun_test.sh output + rm shogun_test.sh + rm shogun_test1.scala + rm shogun_test2.scala + rm shogun_test3.scala + rm shogun_test4.scala + rm shogun_test5.scala + rm shogun_test6.scala cd .. cd .. done diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test.sh --- a/main_marking5/bf_test.sh Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test.sh Mon Jul 21 16:38:07 2025 +0100 @@ -25,19 +25,20 @@ # compilation tests function scala_compile { - (JAVA_OPTS="-Xmx1g" scala -Xprint:parser "$1" 2> c$out 1> c$out) + (timeout 35s scala-cli compile --server=false -color never -Xprint:parser "$1" 2> c$out 1> c$out) } # functional tests function scala_assert { - (JAVA_OPTS="-Xmx1g" scala -nc -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null) + (timeout 35s scala-cli --server=false -i "$1" "$2" -e "urbanmain()" 2> /dev/null 1> /dev/null) } function scala_assert_thirty { - (JAVA_OPTS="-Xmx1g" scala -nc -i "$1" -- "$2" -e "" 2> /dev/null 1> /dev/null) + (timeout 35s scala-cli --server=false -i "$1" "$2" -e "urbanmain()" 2> /dev/null 1> /dev/null) } + # purity test function scala_vars { (sed 's/immutable/ok/g' c$out > cb$out; diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test1.scala --- a/main_marking5/bf_test1.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test1.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,4 +1,8 @@ -import M5a._ + +def urbanmain() = { + import M5a._ -assert(load_bff("benchmark.bf").length == 188) -assert(load_bff("foobar.bf") == "") + assert(load_bff("benchmark.bf").length == 188) + assert(load_bff("foobar.bf") == "") + +} diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test2.scala --- a/main_marking5/bf_test2.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test2.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,6 +1,10 @@ -import M5a._ + +def urbanmain() = { + + import M5a._ -assert(sread(Map(), 2) == 0) -assert(sread(Map(2 -> 1), 2) == 1) -assert(write(Map(), 1, 2) == Map(1 -> 2)) -assert(write(Map(1 -> 0), 1, 2) == Map(1 -> 2)) + assert(sread(Map(), 2) == 0) + assert(sread(Map(2 -> 1), 2) == 1) + assert(write(Map(), 1, 2) == Map(1 -> 2)) + assert(write(Map(1 -> 0), 1, 2) == Map(1 -> 2)) +} diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test3.scala --- a/main_marking5/bf_test3.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test3.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,19 +1,22 @@ -import M5a._ + +def urbanmain() = { + import M5a._ -import scala.concurrent._ -import scala.concurrent.duration._ -import ExecutionContext.Implicits.global -import scala.language.postfixOps + import scala.concurrent._ + import scala.concurrent.duration._ + import ExecutionContext.Implicits.global + import scala.language.postfixOps -lazy val f = Future { -assert(jumpRight("[xxxxxx]xxx", 1, 0) == 8) -assert(jumpRight("[xx[x]x]xxx", 1, 0) == 8) -assert(jumpRight("[xx[x]x]xxx", 1, 0) == 8) -assert(jumpRight("[xx[xxx]xxx", 1, 0) == 11) -assert(jumpRight("[x[][]x]xxx", 1, 0) == 8) -assert(jumpLeft("[xxxxxx]xxx", 6, 0) == 1) -assert(jumpLeft("[xxxxxx]xxx", 7, 0) == -1) -assert(jumpLeft("[x[][]x]xxx", 6, 0) == 1) + lazy val f = Future { + assert(jumpRight("[xxxxxx]xxx", 1, 0) == 8) + assert(jumpRight("[xx[x]x]xxx", 1, 0) == 8) + assert(jumpRight("[xx[x]x]xxx", 1, 0) == 8) + assert(jumpRight("[xx[xxx]xxx", 1, 0) == 11) + assert(jumpRight("[x[][]x]xxx", 1, 0) == 8) + assert(jumpLeft("[xxxxxx]xxx", 6, 0) == 1) + assert(jumpLeft("[xxxxxx]xxx", 7, 0) == -1) + assert(jumpLeft("[x[][]x]xxx", 6, 0) == 1) + } + + Await.result(f, 32 second) } - -Await.result(f, 32 second) diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test4.scala --- a/main_marking5/bf_test4.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test4.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,28 +1,31 @@ -import M5a._ + +def urbanmain() = { + + import M5a._ -import scala.concurrent._ -import scala.concurrent.duration._ -import ExecutionContext.Implicits.global -import scala.language.postfixOps + import scala.concurrent._ + import scala.concurrent.duration._ + import ExecutionContext.Implicits.global + import scala.language.postfixOps -lazy val f = Future { + lazy val f = Future { -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 -> 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 = """+++++[->++++++++++<]>--<+++[->>++++++++++ + val hw_urban = """+++++[->++++++++++<]>--<+++[->>++++++++++ <<]>>++<<----------[+>.>.<+<]""" -assert(run(hw_urban) == Map(0 -> 0, 1 -> 58, 2 -> 32)) + assert(run(hw_urban) == Map(0 -> 0, 1 -> 58, 2 -> 32)) -val hw_urban1 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---. + val hw_urban1 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---. +++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.""" -assert(run(hw_urban1) == Map(0 -> 0, 5 -> 33, 1 -> 0, 6 -> 10, 2 -> 72, 3 -> 100, 4 -> 87)) + assert(run(hw_urban1) == Map(0 -> 0, 5 -> 33, 1 -> 0, 6 -> 10, 2 -> 72, 3 -> 100, 4 -> 87)) + } + + Await.result(f, 32 second) } - -Await.result(f, 32 second) - diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test4b.scala --- a/main_marking5/bf_test4b.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test4b.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,21 +1,23 @@ -import M5a._ +def urbanmain() = { + + import M5a._ -import scala.concurrent._ -import scala.concurrent.duration._ -import ExecutionContext.Implicits.global -import scala.language.postfixOps + import scala.concurrent._ + import scala.concurrent.duration._ + import ExecutionContext.Implicits.global + import scala.language.postfixOps -lazy val f = Future { -val urban_bench = -""">+[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++ + lazy val f = Future { + val urban_bench = + """>+[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++ [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++ ++++++++[>++++++++++[>++++++++++[>++++++++++[>+ +++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++.""" -assert(run(urban_bench, Map()) == - Map(0 -> 10, 5 -> 0, 1 -> 0, 6 -> 0, 2 -> 0, 7 -> 0, 3 -> 0, 4 -> 0)) + assert(run(urban_bench, Map()) == Map(0 -> 10, 5 -> 0, 1 -> 0, 6 -> 0, 2 -> 0, 7 -> 0, 3 -> 0, 4 -> 0)) -} + } -Await.result(f, 32 second) + Await.result(f, 32 second) +} diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test4c.scala --- a/main_marking5/bf_test4c.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test4c.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,6 +1,10 @@ -import M5a._ + +def urbanmain() = { + import M5a._ -val urban_generate = -"""+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-]""" + val urban_generate = + """+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-]++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-]+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.[-]""" -assert(generate("ABC".toList) == urban_generate) + assert(generate("ABC".toList) == urban_generate) + +} diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test5.scala --- a/main_marking5/bf_test5.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test5.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,34 +1,34 @@ -import M5b._ +def urbanmain() = { + import M5b._ -import scala.concurrent._ -import scala.concurrent.duration._ -import ExecutionContext.Implicits.global -import scala.language.postfixOps + import scala.concurrent._ + import scala.concurrent.duration._ + import ExecutionContext.Implicits.global + import scala.language.postfixOps -lazy val f = Future { -val hw_urban = """+++++[->++++++++++<]>--<+++[->>++++++++++<<]>>++<<----------[+>.>.<+<]""" -assert(jtable(hw_urban) == Map(69 -> 61, 5 -> 20, 60 -> 70, 27 -> 44, 43 -> 28, 19 -> 6)) + lazy val f = Future { + val hw_urban = """+++++[->++++++++++<]>--<+++[->>++++++++++<<]>>++<<----------[+>.>.<+<]""" -val hw_urban1 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.""" + assert(jtable(hw_urban) == Map(69 -> 61, 5 -> 20, 60 -> 70, 27 -> 44, 43 -> 28, 19 -> 6)) -assert(jtable(hw_urban1) == Map(14 -> 34, 33 -> 15, 45 -> 44, 48 -> 9, 43 -> 46, 8 -> 49)) + val hw_urban1 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.""" - + assert(jtable(hw_urban1) == Map(14 -> 34, 33 -> 15, 45 -> 44, 48 -> 9, 43 -> 46, 8 -> 49)) -assert(run2("[-]", Map(0 -> 100)) == Map(0 -> 0)) -assert(run2("[->+<]", Map(0 -> 10)) == Map(0 -> 0, 1 -> 10)) -assert(run2("[>>+>>+<<<<-]", Map(0 -> 42)) == Map(0 -> 0, 2 -> 42, 4 -> 42)) -val hw_urban2 = """+++++[->++++++++++<]>--<+++[->>++++++++++ + assert(run2("[-]", Map(0 -> 100)) == Map(0 -> 0)) + assert(run2("[->+<]", Map(0 -> 10)) == Map(0 -> 0, 1 -> 10)) + assert(run2("[>>+>>+<<<<-]", Map(0 -> 42)) == Map(0 -> 0, 2 -> 42, 4 -> 42)) + val hw_urban2 = """+++++[->++++++++++<]>--<+++[->>++++++++++ <<]>>++<<----------[+>.>.<+<]""" -assert(run2(hw_urban2) == Map(0 -> 0, 1 -> 58, 2 -> 32)) + assert(run2(hw_urban2) == Map(0 -> 0, 1 -> 58, 2 -> 32)) -val hw_urban3 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---. + val hw_urban3 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---. +++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.""" -assert(run2(hw_urban3) == Map(0 -> 0, 5 -> 33, 1 -> 0, 6 -> 10, 2 -> 72, 3 -> 100, 4 -> 87)) + assert(run2(hw_urban3) == Map(0 -> 0, 5 -> 33, 1 -> 0, 6 -> 10, 2 -> 72, 3 -> 100, 4 -> 87)) + } + + Await.result(f, 32 second) } - -Await.result(f, 32 second) - diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test6.scala --- a/main_marking5/bf_test6.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test6.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,33 +1,35 @@ -import M5b._ -import io.Source -import scala.util._ +def urbanmain() = { + import M5b._ -def urban_load_bff(name: String) : String = - Try(Source.fromFile(name)("ISO-8859-1").mkString).getOrElse("") + import io.Source + import scala.util._ -import scala.concurrent._ -import scala.concurrent.duration._ -import ExecutionContext.Implicits.global -import scala.language.postfixOps + def urban_load_bff(name: String) : String = + Try(Source.fromFile(name)("ISO-8859-1").mkString).getOrElse("") -lazy val f = Future { - assert(optimise(urban_load_bff("benchmark.bf")).length == 181) - assert(optimise(urban_load_bff("sierpinski.bf")).length == 110) + import scala.concurrent._ + import scala.concurrent.duration._ + import ExecutionContext.Implicits.global + import scala.language.postfixOps + + lazy val f = Future { + assert(optimise(urban_load_bff("benchmark.bf")).length == 181) + assert(optimise(urban_load_bff("sierpinski.bf")).length == 110) - assert(run3("[-]", Map(0 -> 100)) == Map(0 -> 0)) - assert(run3("[->+<]", Map(0 -> 10)) == Map(0 -> 0, 1 -> 10)) - assert(run3("[>>+>>+<<<<-]", Map(0 -> 42)) == Map(0 -> 0, 2 -> 42, 4 -> 42)) - val hw_urban2 = """+++++[->++++++++++<]>--<+++[->>++++++++++ + assert(run3("[-]", Map(0 -> 100)) == Map(0 -> 0)) + assert(run3("[->+<]", Map(0 -> 10)) == Map(0 -> 0, 1 -> 10)) + assert(run3("[>>+>>+<<<<-]", Map(0 -> 42)) == Map(0 -> 0, 2 -> 42, 4 -> 42)) + val hw_urban2 = """+++++[->++++++++++<]>--<+++[->>++++++++++ <<]>>++<<----------[+>.>.<+<]""" - assert(run3(hw_urban2) == Map(0 -> 0, 1 -> 58, 2 -> 32)) + assert(run3(hw_urban2) == Map(0 -> 0, 1 -> 58, 2 -> 32)) - val hw_urban3 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---. + val hw_urban3 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---. +++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.""" - assert(run3(hw_urban3) == Map(0 -> 0, 5 -> 33, 1 -> 0, 6 -> 10, 2 -> 72, 3 -> 100, 4 -> 87)) + assert(run3(hw_urban3) == Map(0 -> 0, 5 -> 33, 1 -> 0, 6 -> 10, 2 -> 72, 3 -> 100, 4 -> 87)) + } + + Await.result(f, 32 second) } - -Await.result(f, 32 second) - diff -r 244df77507c2 -r 253d1ccb65de main_marking5/bf_test7.scala --- a/main_marking5/bf_test7.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/bf_test7.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,33 +1,36 @@ -import M5b._ + +def urbanmain() = { + + import M5b._ -import io.Source -import scala.util._ + import io.Source + import scala.util._ -def urban_load_bff(name: String) : String = - Try(Source.fromFile(name)("ISO-8859-1").mkString).getOrElse("") - + def urban_load_bff(name: String) : String = + Try(Source.fromFile(name)("ISO-8859-1").mkString).getOrElse("") -import scala.concurrent._ -import scala.concurrent.duration._ -import ExecutionContext.Implicits.global -import scala.language.postfixOps + import scala.concurrent._ + import scala.concurrent.duration._ + import ExecutionContext.Implicits.global + import scala.language.postfixOps -lazy val f = Future { -assert(combine(optimise(urban_load_bff("benchmark.bf"))).length == 134) -assert(combine(optimise(urban_load_bff("sierpinski.bf"))).length == 122) + lazy val f = Future { + assert(combine(optimise(urban_load_bff("benchmark.bf"))).length == 134) + assert(combine(optimise(urban_load_bff("sierpinski.bf"))).length == 122) -assert(run4("[-]", Map(0 -> 100)) == Map(0 -> 0)) -assert(run4("[->+<]", Map(0 -> 10)) == Map(0 -> 0, 1 -> 10)) -assert(run4("[>>+>>+<<<<-]", Map(0 -> 42)) == Map(0 -> 0, 2 -> 42, 4 -> 42)) -val hw_urban2 = """+++++[->++++++++++<]>--<+++[->>++++++++++ + assert(run4("[-]", Map(0 -> 100)) == Map(0 -> 0)) + assert(run4("[->+<]", Map(0 -> 10)) == Map(0 -> 0, 1 -> 10)) + assert(run4("[>>+>>+<<<<-]", Map(0 -> 42)) == Map(0 -> 0, 2 -> 42, 4 -> 42)) + val hw_urban2 = """+++++[->++++++++++<]>--<+++[->>++++++++++ <<]>>++<<----------[+>.>.<+<]""" -assert(run4(hw_urban2) == Map(0 -> 0, 1 -> 58, 2 -> 32)) + assert(run4(hw_urban2) == Map(0 -> 0, 1 -> 58, 2 -> 32)) -val hw_urban3 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---. + val hw_urban3 = """++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---. +++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.""" -assert(run4(hw_urban3) == Map(0 -> 0, 5 -> 33, 1 -> 0, 6 -> 10, 2 -> 72, 3 -> 100, 4 -> 87)) + assert(run4(hw_urban3) == Map(0 -> 0, 5 -> 33, 1 -> 0, 6 -> 10, 2 -> 72, 3 -> 100, 4 -> 87)) + } + + Await.result(f, 32 second) } - -Await.result(f, 32 second) diff -r 244df77507c2 -r 253d1ccb65de main_marking5/mk_main5 --- a/main_marking5/mk_main5 Sun Sep 15 12:57:59 2024 +0100 +++ b/main_marking5/mk_main5 Mon Jul 21 16:38:07 2025 +0100 @@ -10,17 +10,17 @@ 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_test4c.scala . - cp ../../../../../main_marking5/bf_test5.scala . - cp ../../../../../main_marking5/bf_test6.scala . - cp ../../../../../main_marking5/bf_test7.scala . - cp ../../../../../main_marking5/*.bf . + 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_test4c.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 diff -r 244df77507c2 -r 253d1ccb65de main_solution3/re.scala --- a/main_solution3/re.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_solution3/re.scala Mon Jul 21 16:38:07 2025 +0100 @@ -142,6 +142,34 @@ } +def draw_rs(rs: List[Rexp], prefix: String) : String = { + val rsi = rs.iterator + rsi.map(r => draw_r(r, prefix, rsi.hasNext)).mkString +} + +def draw_r(e: Rexp, prefix: String, more: Boolean) : String = { + val full_prefix = s"$prefix${if more then "├" else "└"}" + val childPrefix = s"$prefix${if more then "│" else " "} " + s"\n${full_prefix}" ++ + (e match { + case ZERO => s"0" + case ONE => s"1" + case CHAR(c) => s"$c" + case ALTs(rs) => s"ALTs" ++ draw_rs(rs, childPrefix) + case SEQs(rs) => s"SEQs" ++ draw_rs(rs, childPrefix) + case STAR(r) => s"STAR" ++ draw_r(r, childPrefix, false) + }) +} + +def draw(e: Rexp) = + draw_r(e, "", false) + + +val re = STAR(STAR("aa" | "aaa")) + +for (n <- 1 to 100) { + println(s"$n: ${size(ders(("a" * n).toList, re))}") +} // some testing data /* diff -r 244df77507c2 -r 253d1ccb65de main_solution5/bfc.scala --- a/main_solution5/bfc.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/main_solution5/bfc.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,5 +1,6 @@ -// Part 2 about a "Compiler" for the Brainf*** language -//====================================================== +// Main Part 5 about a "Compiler" for the Brainf*** language +//============================================================ + object M5b { @@ -10,306 +11,324 @@ // templates below. -def time_needed[T](n: Int, code: => T) = { +// DEBUGGING INFORMATION FOR COMPILERS!!! +// +// Compiler, even real ones, are fiendishly difficult to get +// to produce correct code. One way to debug them is to run +// example programs ``unoptimised''; and then optimised. Does +// the optimised version still produce the same result? + + +// for timing purposes +def time_needed[T](n: Int, code: => T) ={ val start = System.nanoTime() for (i <- 0 until n) code val end = System.nanoTime() (end - start)/(n * 1.0e9) } + type Mem = Map[Int, Int] - import io.Source import scala.util._ -def load_bff(name: String) : String = - Try(Source.fromFile(name)("ISO-8859-1").mkString).getOrElse("") - -def sread(mem: Mem, mp: Int) : Int = - mem.getOrElse(mp, 0) - -def write(mem: Mem, mp: Int, v: Int) : Mem = - mem.updated(mp, v) +// ADD YOUR CODE BELOW +//====================== -def jumpRight(prog: String, pc: Int, level: Int) : Int = { - if (prog.length <= pc) pc - else (prog(pc), level) match { - case (']', 0) => pc + 1 - case (']', l) => jumpRight(prog, pc + 1, l - 1) - case ('[', l) => jumpRight(prog, pc + 1, l + 1) - case (_, l) => jumpRight(prog, pc + 1, l) - } -} - -def jumpLeft(prog: String, pc: Int, level: Int) : Int = { - if (pc < 0) pc - else (prog(pc), level) match { - case ('[', 0) => pc + 1 - case ('[', l) => jumpLeft(prog, pc - 1, l - 1) - case (']', l) => jumpLeft(prog, pc - 1, l + 1) - case (_, l) => jumpLeft(prog, pc - 1, l) - } -} +def compute(prog: String, pc: Int, mp: Int, mem: Mem) : Mem = -def compute(prog: String, pc: Int, mp: Int, mem: Mem) : Mem = { - if (0 <= pc && pc < prog.length) { - val (new_pc, new_mp, new_mem) = prog(pc) match { - case '>' => (pc + 1, mp + 1, mem) - case '<' => (pc + 1, mp - 1, mem) - 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 '[' => 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) - case _ => (pc + 1, mp, mem) - } - compute(prog, new_pc, new_mp, new_mem) - } - else mem -} + if(pc<0 || pc>= prog.length()) + mem + else + prog.charAt(pc) match + case '>' => compute(prog, pc+1, mp+1, mem) -def run(prog: String, m: Mem = Map()) = compute(prog, 0, 0, m) - - -// The baseline to what we can compare our "compiler" -// implemented below. It should require something like -// 60 seconds for the calculation on my laptop -// -//time_needed(1, run(load_bff("benchmark.bf"))) - + case '<' => compute(prog, pc+1, mp-1, mem) + case '+' => compute(prog, pc+1, mp, write(mem, mp, sread(mem, mp)+1)) -// DEBUGGING INFORMATION!!! -// -// Compiler, even real ones, are fiedishly difficult to get -// to prduce correct code. The point is that for example for -// the sierpinski program, they need to still generate code -// that displays such a triangle. If yes, then one usually -// can take comfort that all is well. If not, then something -// went wrong during the optimisations. + case '-' => compute(prog, pc+1, mp, write(mem, mp, sread(mem, mp)-1)) - - -// (5) Write a function jtable that precomputes the "jump -// table" for a bf-program. This function takes a bf-program -// as an argument and Returns a Map[Int, Int]. The -// purpose of this map is to record the information -// that given on the position pc is a '[' or a ']', -// then to which pc-position do we need to jump next? -// -// For example for the program -// -// "+++++[->++++++++++<]>--<+++[->>++++++++++<<]>>++<<----------[+>.>.<+<]" -// -// we obtain the map -// -// Map(69 -> 61, 5 -> 20, 60 -> 70, 27 -> 44, 43 -> 28, 19 -> 6) -// -// This states that for the '[' on position 5, we need to -// jump to position 20, which is just after the corresponding ']'. -// Similarly, for the ']' on position 19, we need to jump to -// position 6, which is just after the '[' on position 5, and so -// on. The idea is to not calculate this information each time -// we hit a bracket, but just look up this information in the -// jtable. You can use the jumpLeft and jumpRight functions -// from Part 1 for calculating the jtable. -// -// Then adapt the compute and run functions from Part 1 in order -// to take advantage of the information stored in the jtable. -// This means whenever jumpLeft and jumpRight was called previously, -// you should look up the jump address in the jtable. - + case '.' => + compute(prog, pc+1, mp, mem) -def jtable(pg: String) : Map[Int, Int] = - (0 until pg.length).collect { pc => pg(pc) match { - case '[' => (pc -> jumpRight(pg, pc + 1, 0)) - case ']' => (pc -> jumpLeft(pg, pc - 1, 0)) - }}.toMap - - -// testcase -// jtable("""+++++[->++++++++++<]>--<+++[->>++++++++++<<]>>++<<----------[+>.>.<+<]""") -// => Map(69 -> 61, 5 -> 20, 60 -> 70, 27 -> 44, 43 -> 28, 19 -> 6) - + case '[' => + if(sread(mem, mp) == 0) + compute(prog, jumpRight(prog, pc+1, 0), mp, mem) + else + compute(prog, pc+1, mp, mem) -def compute2(pg: String, tb: Map[Int, Int], pc: Int, mp: Int, mem: Mem) : Mem = { - if (0 <= pc && pc < pg.length) { - val (new_pc, new_mp, new_mem) = pg(pc) match { - case '>' => (pc + 1, mp + 1, mem) - case '<' => (pc + 1, mp - 1, mem) - 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 '[' => if (sread(mem, mp) == 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) - case ']' => if (sread(mem, mp) != 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) - case _ => (pc + 1, mp, mem) - } - compute2(pg, tb, new_pc, new_mp, new_mem) - } - else mem -} + case ']' => + if(sread(mem, mp) == 0) + compute(prog, pc+1, mp, mem) + else + compute(prog, jumpLeft(prog, pc-1, 0), mp, mem) - -def run2(pg: String, m: Mem = Map()) = - compute2(pg, jtable(pg), 0, 0, m) - -//time_needed(1, run2(load_bff("benchmark.bf"))) + case _ => compute(prog, pc + 1, mp, mem) -// (6) Write a function optimise which deletes "dead code" (everything -// that is not a bf-command) and also replaces substrings of the form -// [-] by a new command 0. The idea is that the loop [-] just resets the -// memory at the current location to 0. In the compute3 and run3 functions -// below you implement this command by writing the number 0 to mem(mp), -// 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 -// 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 run(prog: String, m: Mem = Map()) = + compute(prog, 0, 0, m) + + +// (6) +def jumpRight(prog: String, pc: Int, level: Int) : Int = + if (pc<0 || pc>= prog.length() ) + pc + else + prog(pc) match + case '[' => jumpRight(prog, pc+1, level+1) + + case ']' => + { + if (level == 0) + pc+1 + else + jumpRight(prog, pc+1, level-1) + + } + + case _ => jumpRight(prog, pc+1, level) + -def optimise(s: String) : String = { - s.replaceAll("""[^<>+-.\[\]]""","") - .replaceAll("""\[-\]""", "0") -} +def jumpLeft(prog: String, pc: Int, level: Int) : Int = + if (pc<0 || pc>= prog.length() ) + pc + else + prog(pc) match + case '[' => + { + if (level == 0) + pc+1 + else + jumpLeft(prog, pc-1, level-1) + + } + + case ']' => jumpLeft(prog, pc-1, level+1) + + case _ => jumpLeft(prog, pc-1, level) + + +def jtable(pg: String) : Map[Int, Int] = + val b1 = (0 until pg.length) + .filter(n => pg.substring(n, n+1) == "[") + .map(n => n -> jumpRight(pg, n + 1, 0)).toMap + + val b2 = (0 until pg.length) + .filter(n => pg.substring(n, n+1) == "]") + .map(n => n -> jumpLeft(pg, n-1, 0)).toMap + + b1++b2 -def compute3(pg: String, tb: Map[Int, Int], pc: Int, mp: Int, mem: Mem) : Mem = { - if (0 <= pc && pc < pg.length) { - val (new_pc, new_mp, new_mem) = pg(pc) match { - case '0' => (pc + 1, mp, write(mem, mp, 0)) - case '>' => (pc + 1, mp + 1, mem) - case '<' => (pc + 1, mp - 1, mem) - 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 '[' => if (sread(mem, mp) == 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) - case ']' => if (sread(mem, mp) != 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) - case _ => (pc + 1, mp, mem) - } - compute3(pg, tb, new_pc, new_mp, new_mem) - } - else mem -} +// testcase +// +// jtable("""+++++[->++++++++++<]>--<+++[->>++++++++++<<]>>++<<----------[+>.>.<+<]""") +// => Map(69 -> 61, 5 -> 20, 60 -> 70, 27 -> 44, 43 -> 28, 19 -> 6) + +def load_bff(name: String) : String = + try + Source.fromFile(name).mkString + catch + case e: Exception => "" + +def sread(mem: Mem, mp: Int) : Int = + mem.getOrElse(mp,0) + +def write(mem: Mem, mp: Int, v: Int) : Mem = + mem + (mp -> v) + +def compute2(pg: String, tb: Map[Int, Int], pc: Int, mp: Int, mem: Mem) : Mem = + + if(pc<0 || pc>= pg.length()) + mem + else + pg.charAt(pc) match + case '>' => compute2(pg,tb, pc+1, mp+1, mem) -def run3(pg: String, m: Mem = Map()) = { - val pg_opt = optimise(pg) - compute3(pg_opt, jtable(pg_opt), 0, 0, m) -} + case '<' => compute2(pg,tb, pc+1, mp-1, mem) + + case '+' => compute2(pg,tb, pc+1, mp, write(mem, mp, sread(mem, mp)+1)) + + case '-' => compute2(pg,tb, pc+1, mp, write(mem, mp, sread(mem, mp)-1)) + + case '.' => + compute2(pg,tb, pc+1, mp, mem) + case '[' => + if(sread(mem, mp) == 0) + compute2(pg, tb, tb(pc), mp, mem) + else + compute2(pg, tb, pc+1, mp, mem) + + case ']' => + if(sread(mem, mp) == 0) + compute2(pg, tb, pc+1, mp, mem) + else + compute2(pg, tb, tb(pc), mp, mem) + + case _ => compute2(pg,tb,pc + 1, mp, mem) + +def run2(pg: String, m: Mem = Map()) = + compute2(pg, jtable(pg), 0, 0, m) // testcases - -//println(optimise(load_bff("collatz.bf"))) -//optimise(load_bff("benchmark.bf")) // should have inserted 0's -//optimise(load_bff("mandelbrot.bf")).length // => 11203 - -//time_needed(1, run3(load_bff("benchmark.bf"))) -//time_needed(1, run3(load_bff("mandelbrot.bf"))) +// time_needed(1, run2(load_bff("benchmark.bf"))) +// time_needed(1, run2(load_bff("sierpinski.bf"))) -// (7) Write a function combine which replaces sequences -// of repated increment and decrement commands by appropriate -// two-character commands. For example for sequences of + -// -// orig bf-cmds | replacement -// ------------------------------ -// + | +A -// ++ | +B -// +++ | +C -// | -// ... | -// | -// +++....+++ | +Z -// (where length = 26) -// -// Similar for the bf-command -, > and <. All other commands should -// be unaffected by this change. -// -// Adapt the compute4 and run4 functions such that they can deal -// appropriately with such two-character commands. +// (7) -def splice(cs: List[Char], acc: List[(Char, Int)]) : List[(Char, Int)] = (cs, acc) match { - case (Nil, acc) => acc - case ('[' :: cs, acc) => splice(cs, ('[', 1) :: acc) - case (']' :: cs, acc) => splice(cs, (']', 1) :: acc) - case ('.' :: cs, acc) => splice(cs, ('.', 1) :: acc) - case ('0' :: cs, acc) => splice(cs, ('0', 1) :: acc) - case (c :: cs, Nil) => splice(cs, List((c, 1))) - case (c :: cs, (d, n) :: acc) => - if (c == d && n < 26) splice(cs, (c, n + 1) :: acc) - else splice(cs, (c, 1) :: (d, n) :: acc) -} +def optimise(s: String) : String = + val notCommand = """[^<>+\-.\[\]]""".r + val occurrence = """\[-\]""".r -def spl(s: String) = splice(s.toList, Nil).reverse - -//spl(load_bff("benchmark.bf")) - -def combine(s: String) : String = { - (for ((c, n) <- spl(s)) yield c match { - case '>' => List('>', (n + '@').toChar) - case '<' => List('<', (n + '@').toChar) - case '+' => List('+', (n + '@').toChar) - case '-' => List('-', (n + '@').toChar) - case _ => List(c) - }).flatten.mkString -} + val deleted = notCommand.replaceAllIn(s, "") + occurrence.replaceAllIn(deleted, "0") -//combine(load_bff("benchmark.bf")) +def compute3(pg: String, tb: Map[Int, Int], pc: Int, mp: Int, mem: Mem) : Mem = + + if(pc<0 || pc>= pg.length()) + mem + else + pg.charAt(pc) match + case '>' => compute3(pg,tb, pc+1, mp+1, mem) + + case '<' => compute3(pg,tb, pc+1, mp-1, mem) + + case '+' => compute3(pg,tb, pc+1, mp, write(mem, mp, sread(mem, mp)+1)) + + case '-' => compute3(pg,tb, pc+1, mp, write(mem, mp, sread(mem, mp)-1)) + + case '.' => + compute3(pg,tb, pc+1, mp, mem) -def compute4(pg: String, tb: Map[Int, Int], pc: Int, mp: Int, mem: Mem) : Mem = { - if (0 <= pc && pc < pg.length) { - val (new_pc, new_mp, new_mem) = pg(pc) match { - case '0' => (pc + 1, mp, write(mem, mp, 0)) - case '>' => (pc + 2, mp + (pg(pc + 1) - '@'), mem) - case '<' => (pc + 2, mp - (pg(pc + 1) - '@'), mem) - case '+' => (pc + 2, mp, write(mem, mp, sread(mem, mp) + (pg(pc + 1) - '@'))) - case '-' => (pc + 2, mp, write(mem, mp, sread(mem, mp) - (pg(pc + 1) - '@'))) - case '.' => { print(sread(mem, mp).toChar); (pc + 1, mp, mem) } - case '[' => if (sread(mem, mp) == 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) - case ']' => if (sread(mem, mp) != 0) (tb(pc), mp, mem) else (pc + 1, mp, mem) - case _ => (pc + 1, mp, mem) - } - compute4(pg, tb, new_pc, new_mp, new_mem) - } - else mem -} + case '[' => + if(sread(mem, mp) == 0) + compute3(pg, tb, tb(pc), mp, mem) + else + compute3(pg, tb, pc+1, mp, mem) -def run4(pg: String, m: Mem = Map()) = { - val pg_opt = combine(optimise(pg)) - compute4(pg_opt, jtable(pg_opt), 0, 0, m) -} + case ']' => + if(sread(mem, mp) == 0) + compute3(pg, tb, pc+1, mp, mem) + else + compute3(pg, tb, tb(pc), mp, mem) + + case _ => compute3(pg,tb,pc + 1, mp, mem) + +def run3(pg: String, m: Mem = Map()) = + val opt = optimise(pg) + compute3(opt, jtable(opt), 0, 0, m) + + // testcases -//println(combine(optimise(load_bff("mandelbrot.bf").drop(123)))) - -//combine(optimise(load_bff("benchmark.bf"))) // => """>A+B[A-A] 11205 +// +// time_needed(1, run3(load_bff("benchmark.bf"))) +// (8) +// consider if the char does not exist\\ + +def counterHelper(chars: List[Char], consec: Int, charToCount: Char): Int = + chars match + case head :: tail if ((head == charToCount && head == tail.headOption.getOrElse(' ')) )=> + counterHelper(tail, consec + 1, charToCount) + + case head :: tail if (head == charToCount && head != tail.headOption.getOrElse(' '))=> + consec+1 + + case head :: tail if (head != charToCount && head != tail.headOption.getOrElse(' '))=> + consec + + +def counter(input: String, charToCount: Char): Int = + counterHelper(input.toList, 0, charToCount) + +def handleCharacter(orgin: String, newstr: String, sindex: Int, letterMap: Map[Int, Char], charToCount: Char): String = + val num = counter(orgin.substring(sindex), charToCount) + val lett = letterMap.getOrElse(num, "") + combineHelper(orgin, newstr + charToCount + lett, sindex + num, letterMap) + +def combineHelper(orgin: String, newstr: String, sindex: Int, letterMap: Map[Int, Char] ): String = + if (sindex >= orgin.length()) + newstr + else + val result = + orgin.charAt(sindex) match + case '>' => handleCharacter(orgin, newstr, sindex, letterMap, '>') + case '<' => handleCharacter(orgin, newstr, sindex, letterMap, '<') + case '+' => handleCharacter(orgin, newstr, sindex, letterMap, '+') + case '-' => handleCharacter(orgin, newstr, sindex, letterMap, '-') + case _ => combineHelper(orgin, newstr + orgin.charAt(sindex), sindex + 1, letterMap) + + result + +def combine(s: String) : String = + val letterMap = (1 to 26).zip('A' to 'Z').toMap + combineHelper(s,"",0, letterMap) + +// testcase +// combine(load_bff("benchmark.bf")) + +def compute4(pg: String, tb: Map[Int, Int], pc: Int, mp: Int, mem: Mem) : Mem = + + if(pc<0 || pc>= pg.length()) + mem + else + pg.charAt(pc) match + case '>' => compute4(pg,tb, pc+1, mp+1, mem) + + case '<' => compute4(pg,tb, pc+1, mp-1, mem) + + case '+' => compute4(pg,tb, pc+1, mp, write(mem, mp, sread(mem, mp)+1)) + + case '-' => compute4(pg,tb, pc+1, mp, write(mem, mp, sread(mem, mp)-1)) + + case '.' => + compute4(pg,tb, pc+1, mp, mem) + + case '[' => + if(sread(mem, mp) == 0) + compute4(pg, tb, tb(pc), mp, mem) + else + compute4(pg, tb, pc+1, mp, mem) + + case ']' => + if(sread(mem, mp) == 0) + compute4(pg, tb, pc+1, mp, mem) + else + compute4(pg, tb, tb(pc), mp, mem) + + case _ => compute4(pg,tb,pc + 1, mp, mem) + +// should call first optimise and then combine on the input string +// +def run4(pg: String, m: Mem = Map()) = + val opt = optimise(pg) + val com= combine(opt) + compute4(com, jtable(com), 0, 0, m) + + +// testcases +// combine(optimise(load_bff("benchmark.bf"))) // => """>A+B[A-A] LENGTH OF LIST EXAMPLE -def len(xs: List[Int], acc: Int) : Int = { - if (xs == Nil) acc - else foo(xs.tail, acc + 1) +def average(ls: List[Int]) : Int = { + println(s"$ls") + val s = ls.sum + val l = ls.length + if (l == 0) 0 + else s / l } -def len(xs: List[Int]) : Int = foo(xs, 0) +average(List(1,2,3,4,56)) +def incr(x: Int) : Int = x + 1 +def double(x: Int) : Int = x + x +def square(x: Int) : Int = x * x + +def str(x: Int) : String = x.toString + +incr(3) +double(4) +square(6) +str(3) + + + + +def len(xs: List[Int]) : Int = { + if (xs == Nil) 0 + else 1 + len(xs.tail) +} len(List(1,2,3,4,1)) -def len(xs: List[Int]) : Int = { - if (xs == Nil) 0 - else (1 + len(xs.tail)) -} - - - -len(List(1,2,3,4,1)) - def len(xs: List[Int]) : Int = xs match { @@ -322,9 +329,12 @@ // For-Comprehensions (not For-Loops) //==================================== -val lst = (1 to 10).toList -for (n <- lst) yield n * n +val lst = (1 to 10).toSet +val result = for (n <- lst) yield { + n * n +} +println(result) for (n <- lst) yield { square(n) + double(n) @@ -341,7 +351,7 @@ m <- (1 to 10).toList) yield n * m println(mult_table.mkString(",")) -mult_table.sliding(10,10).toList +mult_table.sliding(10,10).toList.mkString(",") .mkString("\n") @@ -361,7 +371,6 @@ val xs = for (n <- (1 to 3).toList; m <- (1 to 3).toList) yield (n,m) -xs.filter{case (m, n) => (n + m) % 2 == 0} for (n <- (1 to 3).toList; m <- (1 to 3).toList; @@ -397,6 +406,7 @@ val foo = for (n <- (1 to 10).toList) yield n * n +println(for (n <- (1 to 10).toList) print(n)) // BTW: a roundabout way of printing out a list, say val lst = ('a' to 'm').toList @@ -422,7 +432,12 @@ def get_length(s: String) : (String, Int) = (s, s.length) +def len(s: String) : Int = s.length + + val lst = List("zero", "one", "two", "three", "four", "ten") +lst.sorted +lst.sortBy(len(_)) val strs = for (s <- lst) yield get_length(s) strs.sortBy(_._2) @@ -476,7 +491,7 @@ // But what the heck....lets try to count to 1 Mio in parallel // // requires -// scala-cli --extra-jars scala- parallel-collections_3-1.0.4.jar +// scala --extra-jars scala- parallel-collections_3-1.0.4.jar import scala.collection.parallel.CollectionConverters._ @@ -562,21 +577,18 @@ // Further Information //===================== -// We are going to use Scala 3 and the scala-cli repl (easier to use) -// -// https://scala-cli.virtuslab.org -// -// -// The Scala homepage and general information is at +// We are going to use Scala 3. The Scala homepage +// and general information is at // // http://www.scala-lang.org // http://docs.scala-lang.org // // -// It should be fairly easy to install the scala-cli binary and +// It should be fairly easy to install the scala binary and // run Scala on the commandline. People also use Scala with -// Vim and Jedit. I currently settled on Codium +// Vim and Jedit. I currently settled on Codium / VSCode // +// https://vscodium.com // https://code.visualstudio.com // // There are also plugins for Eclipse and IntelliJ - YMMV. @@ -584,7 +596,6 @@ // running Scala applications (but do not blame me if you lose // all what you typed in): // -// https://scalafiddle.io // https://scastie.scala-lang.org // // diff -r 244df77507c2 -r 253d1ccb65de progs/lecture2.scala --- a/progs/lecture2.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/progs/lecture2.scala Mon Jul 21 16:38:07 2025 +0100 @@ -30,14 +30,23 @@ // Option[Boolean]: None, Some(true), Some(false) // Option[...]: None, Some(_) +def div(x: Int, y: Int) : Int = + x / y + def safe_div(x: Int, y: Int) : Option[Int] = if (y == 0) None else Some(x / y) -safe_div(10 + 5, 0) +def foo_calculation(x: Int) = + if (safe_div(x, x) == None) 24 else safe_div(x, x).get + +foo_calculation(3) +foo_calculation(0) + +safe_div(10 + 5, 3) List(1,2,3,4,5,6).indexOf(7) -List[Int]().min -List[Int](3,4,5).minOption +List[Int](3,4,5).min +List[Int]().minOption @@ -49,7 +58,7 @@ import scala.util._ // Try,... import io.Source // fromURL -val my_url = "https://nms.kcl.ac.uk/christian.urban2/" +val my_url = "https://nms.kcl.ac.uk/christian.urban/" Source.fromURL(my_url)("ISO-8859-1").mkString Source.fromURL(my_url)("ISO-8859-1").getLines().toList @@ -94,6 +103,11 @@ val lst = List(None, Some(1), Some(2), None, Some(3)) +for (x <- lst) yield { + if (x == None) None + else Some(x.get + 1) +} + lst.flatten Some(1).get @@ -173,10 +187,13 @@ def inc(x: Int) : Int = x + 1 val lst = (1 to 10).toList -lst.filter(_ % 2 == 0) +lst.filter(odd) +lst.exists(even) lst.count(odd) -lst.find(even) -lst.exists(even) + +lst.filter(_ % 2 == 0) + + lst.find(_ < 4) lst.filter(_ < 4) @@ -191,8 +208,8 @@ lst.filter(_ % 2 == 0) -lst.sortWith((x, y) => x < y) -lst.sortWith(_ > _) +lst.sortWith((x, y) => x > y) +lst.sortWith(_ < _) // but this only works when the arguments are clear, but // not with multiple occurences @@ -211,7 +228,7 @@ ps.sortBy(x => x._1) ps.sortBy(_._2) -ps.maxBy(_._1) +ps.maxBy(x => x._2) ps.maxBy(_._2) @@ -224,6 +241,10 @@ val lst = (1 to 10).toList lst.map(square) +lst.map(n => square(n)) + +for (n <- lst) yield square(n) + lst.map(x => (double(x), square(x))) // works also for strings diff -r 244df77507c2 -r 253d1ccb65de progs/lecture3.scala --- a/progs/lecture3.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/progs/lecture3.scala Mon Jul 21 16:38:07 2025 +0100 @@ -10,6 +10,36 @@ // - string interpolations // - Pattern-Matching +def fact(n: BigInt) : BigInt = { + if (n == 0) 1 + else n * fact(n - 1) +} + +def fib(n: BigInt) : BigInt = { + if (n == 0) 1 + else if (n == 1) 1 + else fib(n - 1) + fib(n - 2) +} + + + + + +def inc(n: Int) : Int = n + 1 + +for (n <- List(1,2,3,4)) yield inc(n) + +List().map(inc) + + + +my_map(inc, List(1,2,3,4)) + + + + + + // A Recursive Web Crawler / Email Harvester //=========================================== // @@ -79,6 +109,12 @@ // EFFICIENT AND FAST, just explaining exhaustive // depth-first search +//> using dep org.scala-lang.modules::scala-parallel-collections:1.0.4 +import scala.collection.parallel.CollectionConverters.* + + +val s1 = "s\n" +val s2 = """s\n""" val game0 = """.14.6.3.. |62...4..9 @@ -286,6 +322,14 @@ // case patternN => expressionN // } +def my_map(f: Int => Int, xs: List[Int]) : List[Int] = + xs match { + case Nil => Nil + case hd::tl => f(hd) :: my_map(f, tl) + } + +my_map(x => x * x, List(1,2,3,4)) + // recall def len(xs: List[Int]) : Int = { @@ -350,6 +394,8 @@ // more interesting patterns for lists - calculate the deltas between // elements +List(4,3,2,1) -> List(1,1,.. ) + def delta(xs: List[Int]) : List[Int] = xs match { case Nil => Nil case x::Nil => x::Nil @@ -386,6 +432,13 @@ val lf = Leaf(20) val tr = Node("foo", Leaf(10), Leaf(23)) +def sizet(t: Tree) : Int = t match { + case Leaf(_) => 1 + case Node(_, left , right) => 1 + sizet(left) + sizet(right) +} + +sizet(tr) + val lst : List[Tree] = List(lf, tr) diff -r 244df77507c2 -r 253d1ccb65de progs/lecture4.scala --- a/progs/lecture4.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/progs/lecture4.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,9 +1,84 @@ // Scala Lecture 4 //================= -// pattern-matching +//=================== +// polymorphic types +// (algebraic) datatypes and pattern-matching +// extensions and implicits // tail-recursion -// polymorphic types + + + +// You do not want to write functions like contains, first, +// length and so on for every type of lists. + +def length_int_list(lst: List[Int]): Int = lst match { + case Nil => 0 + case _::xs => 1 + length_int_list(xs) +} + +length_int_list(List(1, 2, 3, 4)) + +def length_string_list(lst: List[String]): Int = lst match { + case Nil => 0 + case _::xs => 1 + length_string_list(xs) +} + +length_string_list(List("1", "2", "3", "4")) + + +// you can make the function parametric in type(s) + +def length[A](lst: List[A]): Int = lst match { + case Nil => 0 + case x::xs => 1 + length(xs) +} +length(List("1", "2", "3", "4")) +length(List(1, 2, 3, 4)) + + +length[String](List(1, 2, 3, 4)) + + +def map[A, B](lst: List[A], f: A => B): List[B] = lst match { + case Nil => Nil + case x::xs => f(x)::map(xs, f) +} + +map(List(1, 2, 3, 4), (x: Int) => x.toString) + + +// Type inference is local in Scala + +def id[T](x: T) : T = x + +val x = id(322) // Int +val y = id("hey") // String +val z = id(Set(1,2,3,4)) // Set[Int] + + +// The type variable concept in Scala can get +// really complicated. +// +// - variance (OO) +// - bounds (subtyping) +// - quantification + +// Java has issues with this too: Java allows +// to write the following incorrect code, and +// only recovers by raising an exception +// at runtime. + +// Object[] arr = new Integer[10]; +// arr[0] = "Hello World"; + + +// Scala gives you a compile-time error, which +// is much better. + +var arr = Array[Int]() +arr(0) = "Hello World" + @@ -40,152 +115,20 @@ len(List(1,2,3,4)) -List(1,2,3,4).map(x => x * x) - -def my_map_int(lst: List[Int], f: Int => Int) : List[Int] = - lst match { - case Nil => Nil - case foo::xs => f(foo) :: my_map_int(xs, f) - } - -def my_map_option(opt: Option[Int], f: Int => Int) : Option[Int] = - opt match { - case None => None - case Some(x) => { - Some(f(x)) - } - } - -my_map_option(None, x => x * x) -my_map_option(Some(8), x => x * x) - - -// you can also have cases combined -def season(month: String) : String = month match { - case "March" | "April" | "May" => "It's spring" - case "June" | "July" | "August" => "It's summer" - case "September" | "October" | "November" => "It's autumn" - case "December" => "It's winter" - case "January" | "February" => "It's unfortunately winter" - case _ => "Wrong month" -} - -// pattern-match on integers +//================= +// Trees (example of an Algebraic Datatype) -def fib(n: Int) : Int = n match { - case 0 | 1 => 1 - case _ => fib(n - 1) + fib(n - 2) -} - -fib(10) - -// pattern-match on results - -// Silly: fizz buzz -def fizz_buzz(n: Int) : String = (n % 3, n % 5) match { - case (0, 0) => "fizz buzz" - case (0, _) => "fizz" - case (_, 0) => "buzz" - case _ => n.toString -} - -for (n <- 1 to 20) - println(fizz_buzz(n)) +abstract class Tree +case class Leaf(x: Int) extends Tree +case class Node(s: String, left: Tree, right: Tree) extends Tree -// guards in pattern-matching +val lf = Leaf(20) +val tr = Node("foo", Leaf(10), Leaf(23)) -def foo(xs: List[Int]) : String = xs match { - case Nil => s"this list is empty" - case x :: xs if x % 2 == 0 - => s"the first elemnt is even" - case x if len(x) == - => s"this list has exactly two elements" - case x :: y :: rest if x == y - => s"this has two elemnts that are the same" - case hd :: tl => s"this list is standard $hd::$tl" -} - -foo(Nil) -foo(List(1,2,3)) -foo(List(1,1)) -foo(List(1,1,2,3)) -foo(List(2,2,2,3)) - +val lst : List[Tree] = List(lf, tr) -abstract class Colour -case object Red extends Colour -case object Green extends Colour -case object Blue extends Colour -case object Yellow extends Colour - - -def fav_colour(c: Colour) : Boolean = c match { - case Green => true - case Red => true - case _ => false -} - -fav_colour(Blue) - - -// ... a tiny bit more useful: Roman Numerals - -sealed abstract class RomanDigit -case object I extends RomanDigit -case object V extends RomanDigit -case object X extends RomanDigit -case object L extends RomanDigit -case object C extends RomanDigit -case object D extends RomanDigit -case object M extends RomanDigit - -type RomanNumeral = List[RomanDigit] - -List(I, M,C,D,X,X,V,I,I, A) - -/* -I -> 1 -II -> 2 -III -> 3 -IV -> 4 -V -> 5 -VI -> 6 -VII -> 7 -VIII -> 8 -IX -> 9 -X -> 10 -*/ - -def RomanNumeral2Int(rs: RomanNumeral): Int = rs match { - case Nil => 0 - case M::r => 1000 + RomanNumeral2Int(r) - case C::M::r => 900 + RomanNumeral2Int(r) - case D::r => 500 + RomanNumeral2Int(r) - case C::D::r => 400 + RomanNumeral2Int(r) - case C::r => 100 + RomanNumeral2Int(r) - case X::C::r => 90 + RomanNumeral2Int(r) - case L::r => 50 + RomanNumeral2Int(r) - case X::L::r => 40 + RomanNumeral2Int(r) - case X::r => 10 + RomanNumeral2Int(r) - case I::X::r => 9 + RomanNumeral2Int(r) - case V::r => 5 + RomanNumeral2Int(r) - case I::V::r => 4 + RomanNumeral2Int(r) - case I::r => 1 + RomanNumeral2Int(r) -} - -RomanNumeral2Int(List(I,V)) // 4 -RomanNumeral2Int(List(I,I,I,I)) // 4 (invalid Roman number) -RomanNumeral2Int(List(V,I)) // 6 -RomanNumeral2Int(List(I,X)) // 9 -RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979 -RomanNumeral2Int(List(M,M,X,V,I,I)) // 2017 - -abstract class Tree -case class Leaf(x: Int) -case class Branch(tl: Tree, tr: Tree) - abstract class Rexp case object ZERO extends Rexp // matches nothing @@ -205,18 +148,8 @@ } -// Trees (example of an Algebraic Datatype) -abstract class Tree -case class Leaf(x: Int) extends Tree -case class Node(s: String, left: Tree, right: Tree) extends Tree - -val lf = Leaf(20) -val tr = Node("foo", Leaf(10), Leaf(23)) - -val lst : List[Tree] = List(lf, tr) - // expressions (essentially trees) @@ -327,7 +260,7 @@ if (n == 0) acc else factT(n - 1, n * acc) -factT(10, 1) +factT(1000,1) println(factT(100000, 1)) @@ -357,81 +290,31 @@ // nothing is perfect. - -// Polymorphic Types -//=================== - -// You do not want to write functions like contains, first, -// length and so on for every type of lists. - -def length_int_list(lst: List[Int]): Int = lst match { - case Nil => 0 - case _::xs => 1 + length_int_list(xs) -} - -length_int_list(List(1, 2, 3, 4)) +// default arguments -def length_string_list(lst: List[String]): Int = lst match { - case Nil => 0 - case _::xs => 1 + length_string_list(xs) -} - -length_string_list(List("1", "2", "3", "4")) - - -// you can make the function parametric in type(s) +def factT(n: BigInt, acc: BigInt = 1): BigInt = + if (n == 0) acc else factT(n - 1, n * acc) -def length[A](lst: List[A]): Int = lst match { - case Nil => 0 - case x::xs => 1 + length(xs) -} -length(List("1", "2", "3", "4")) -length(List(1, 2, 3, 4)) - - -length[String](List(1, 2, 3, 4)) +factT(1_000_000) -def map[A, B](lst: List[A], f: A => B): List[B] = lst match { - case Nil => Nil - case x::xs => f(x)::map(xs, f) +def length[A](xs: List[A]) : Int = xs match { + case Nil => 0 + case _ :: tail => 1 + length(tail) } -map(List(1, 2, 3, 4), (x: Int) => x.toString) - - -// should be -def first[A, B](xs: List[A], f: A => Option[B]) : Option[B] = ??? +length(List.fill(100000)(1)) -// Type inference is local in Scala - -def id[T](x: T) : T = x +def lengthT[A](xs: List[A], acc : Int = 0) : Int = xs match { + case Nil => acc + case _ :: tail => lengthT(tail, 1 + acc) +} -val x = id(322) // Int -val y = id("hey") // String -val z = id(Set(1,2,3,4)) // Set[Int] +lengthT(List.fill(100000)(1)) -// The type variable concept in Scala can get really complicated. -// -// - variance (OO) -// - bounds (subtyping) -// - quantification - -// Java has issues with this too: Java allows -// to write the following incorrect code, and -// only recovers by raising an exception -// at runtime. - -// Object[] arr = new Integer[10]; -// arr[0] = "Hello World"; -// Scala gives you a compile-time error, which -// is much better. - -var arr = Array[Int]() -arr(0) = "Hello World" @@ -467,26 +350,6 @@ i"add ${3+2} ${3 * 3}" -// default arguments - -def length[A](xs: List[A]) : Int = xs match { - case Nil => 0 - case _ :: tail => 1 + length(tail) -} - -def lengthT[A](xs: List[A], acc : Int = 0) : Int = xs match { - case Nil => acc - case _ :: tail => lengthT(tail, 1 + acc) -} - -lengthT(List.fill(100000)(1)) - - -def fact(n: BigInt, acc: BigInt = 1): BigInt = - if (n == 0) acc else fact(n - 1, n * acc) - -fact(10) - // currying (Haskell Curry) @@ -672,7 +535,8 @@ if (isDone(game)) searchT(rest, game::sols) else { val cs = candidates(game, emptyPosition(game)) - searchT(cs.map(c => update(game, empty(game), c)) ::: rest, sols) + searchT(cs.map(c => update(game, empty(game), c)) + ::: rest, sols) } } } @@ -730,24 +594,16 @@ // "HAL".increment // // you can avoid ugly fudges, like a MyString, by -// using implicit conversions. +// using an extension. -print("\n") -print("""\n""") -implicit class MyString(s: String) { +extension (s: String) { def increment = s.map(c => (c + 1).toChar) } "HAL".increment -// Abstract idea: -// In that version implicit conversions were used to solve the -// late extension problem; namely, given a class C and a class T, -// how to have C extend T without touching or recompiling C. -// Conversions add a wrapper when a member of T is requested -// from an instance of C. @@ -758,7 +614,7 @@ Duration(time + unit.convert(o.time, o.unit), unit) } -implicit class Int2Duration(that: Int) { +extension (that: Int) { def seconds = Duration(that, SECONDS) def minutes = Duration(that, MINUTES) } @@ -789,7 +645,6 @@ // 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 @@ -797,28 +652,22 @@ case c::s => SEQ(CHAR(c), charlist2rexp(s)) } -implicit def string2rexp(s: String): Rexp = - charlist2rexp(s.toList) +given Conversion[String, Rexp] = + (s => charlist2rexp(s.toList)) val r1 = STAR("ab") val r2 = STAR("hello") | STAR("world") -implicit def RexpOps (r: Rexp) = new { +extension (r: Rexp) { def | (s: Rexp) = ALT(r, s) def % = STAR(r) def ~ (s: Rexp) = SEQ(r, s) } -implicit def stringOps (s: String) = new { - def | (r: Rexp) = ALT(s, r) - def | (r: String) = ALT(s, r) - def % = STAR(s) - def ~ (r: Rexp) = SEQ(s, r) - def ~ (r: String) = SEQ(s, r) -} +//example regular expressions -//example regular expressions +val rex = "ab".% val digit = ("0" | "1" | "2" | "3" | "4" | @@ -850,7 +699,7 @@ import scala.language.implicitConversions val i = Complex(0, 1) -implicit def double2complex(re: Double) = Complex(re, 0) +given Conversion[Double, Complex] = (re: Double) => Complex(re, 0) val inum1 = -2.0 + -1.5 * i val inum2 = 1.0 + 1.5 * i diff -r 244df77507c2 -r 253d1ccb65de progs/lecture5.scala --- a/progs/lecture5.scala Sun Sep 15 12:57:59 2024 +0100 +++ b/progs/lecture5.scala Mon Jul 21 16:38:07 2025 +0100 @@ -1,110 +1,12 @@ // Scala Lecture 5 //================= -for (n <- (1 to 10).toList) yield { - val add = 10 - n + add -} - -println(add) - -List(1,2,3,4).sum - -// extension methods -// implicit conversions -// (Immutable) OOP - -// Cool Stuff in Scala -//===================== - - -// Extensions or How to Pimp your Library -//====================================== - -// For example adding your own methods to Strings: -// Imagine you want to increment strings, like -// -// "HAL".increment -// -// you can avoid ugly fudges, like a MyString, by -// using extensions. - -extension (s: String) { - def increment = s.map(c => (c + 1).toChar) -} - -"HAL".increment - - - -// a more relevant example - -import scala.concurrent.duration.{TimeUnit,SECONDS,MINUTES} - -case class Duration(time: Long, unit: TimeUnit) { - def +(o: Duration) = - Duration(time + unit.convert(o.time, o.unit), unit) -} - -extension (that: Int) { - def seconds = Duration(that, SECONDS) - def minutes = Duration(that, MINUTES) -} +def foo(n: Int) = ??? -2.minutes + 60.seconds -5.seconds + 2.minutes //Duration(125, SECONDS ) - - -// Implicit Conversions -//===================== - - - -// Regular expressions - the power of DSLs in Scala -//================================================== - -abstract class Rexp -case object ZERO extends Rexp // nothing -case object ONE extends Rexp // the empty string -case class CHAR(c: Char) extends Rexp // a character c -case class ALT(r1: Rexp, r2: Rexp) extends Rexp // alternative r1 + r2 -case class SEQ(r1: Rexp, r2: Rexp) extends Rexp // sequence r1 . r2 -case class STAR(r: Rexp) extends Rexp // star r* - -val r = STAR(CHAR('a')) - - -// some convenience for typing in regular expressions -import scala.language.implicitConversions -import scala.language.reflectiveCalls +fop(10) -def charlist2rexp(s: List[Char]): Rexp = s match { - case Nil => ONE - case c::Nil => CHAR(c) - case c::s => SEQ(CHAR(c), charlist2rexp(s)) -} - -given Conversion[String, Rexp] = (s => charlist2rexp(s.toList)) - -extension (r: Rexp) { - def | (s: Rexp) = ALT(r, s) - def % = STAR(r) - def ~ (s: Rexp) = SEQ(r, s) -} - -val r1 = CHAR('a') | CHAR('b') | CHAR('c') -val r2 = CHAR('a') ~ CHAR('b') - -val r3 : Rexp = "hello world" - - -//example regular expressions -val digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" -val sign = "+" | "-" | "" -val number = sign ~ digit ~ digit.% - - - +List.fill(1)(100) +// (Immutable) OOP // Object Oriented Programming in Scala // ===================================== @@ -164,50 +66,6 @@ } -// In mandelbrot.scala I used complex (imaginary) numbers -// and implemented the usual arithmetic operations for complex -// numbers. - -case class Complex(re: Double, 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) -} - -// usual way to reference methods -//object.method(....) - -val test = Complex(1, 2) + (Complex (3, 4)) - - -import scala.language.postfixOps -(List(5,4,3,2,1) sorted) reverse - -// this could have equally been written as -val test = Complex(1, 2).+(Complex (3, 4)) - -// this applies to all methods, but requires -import scala.language.postfixOps - -List(5, 2, 3, 4).sorted -List(5, 2, 3, 4) sorted - - -// ...to allow the notation n + m * i -import scala.language.implicitConversions - -val i = Complex(0, 1) - -given Conversion[Double, Complex] = (re => Complex(re, 0)) - -val inum1 = -2.0 + -1.5 * i -val inum2 = 1.0 + 1.5 * i - - // All is public by default....so no public is needed. // You can have the usual restrictions about private @@ -489,7 +347,7 @@ // up to a level def enuml(l: Int, s: String) : Set[Rexp] = l match { - case 0 => Set(ZERO, ONE) ++ s.map(CHAR).toSet + case 0 => Set(ZERO, ONE) ++ s.map(CHAR(_)).toSet case n => val rs = enuml(n - 1, s) rs ++ diff -r 244df77507c2 -r 253d1ccb65de progs/mandelbrot.sc --- a/progs/mandelbrot.sc Sun Sep 15 12:57:59 2024 +0100 +++ b/progs/mandelbrot.sc Mon Jul 21 16:38:07 2025 +0100 @@ -3,11 +3,13 @@ // // see https://en.wikipedia.org/wiki/Mandelbrot_set // -// You can run on the file one the commandline with +// You can run the file on the commandline with // // scala mandelbrot.sc // +// Or inside the REPL with // +// scala --extra-jars scala-parallel-collections_3-1.0.4.jar // // !! UPDATE ON TIMING: On my faster Mac-M1 machine // !! the times for the first example are ca. 4 secs for @@ -16,7 +18,6 @@ // for parallel collections //> using dep org.scala-lang.modules::scala-parallel-collections:1.0.4 -import scala.language.implicitConversions.* import scala.collection.parallel.CollectionConverters.* // for graphics @@ -177,7 +178,6 @@ exc2 - delta * n, 1000))} secs") - // Larry Paulson's example val exl1 = -0.74364990 + 0.13188170 * i val exl2 = -0.74291189 + 0.13261971 * i diff -r 244df77507c2 -r 253d1ccb65de slides/slides01.pdf Binary file slides/slides01.pdf has changed diff -r 244df77507c2 -r 253d1ccb65de slides/slides01.tex --- a/slides/slides01.tex Sun Sep 15 12:57:59 2024 +0100 +++ b/slides/slides01.tex Mon Jul 21 16:38:07 2025 +0100 @@ -5,7 +5,7 @@ \usepackage{../styles/langs} %\usepackage{../data} \usetikzlibrary{shapes} - +\usepackage{ulem} \hfuzz=220pt %\setmonofont[Scale=.88]{Consolas} @@ -110,7 +110,7 @@ %Office: & N\liningnums{7.07} (North Wing, Bush House)\bigskip\\ Slides \& Code: & KEATS\bigskip\\ - Office Hour: & Fridays 13:00 -- 14:00\\ + Office Hour: & Thursdays 13:00 -- 14:00\\ Location: & N7.07 (North Wing, Bush House)\bigskip\\ Pollev: & \texttt{\alert{https://pollev.com/cfltutoratki576}}\\ \\ @@ -274,8 +274,8 @@ \begin{minipage}{1.1\textwidth} \begin{itemize} -\item contains a REPL $\Rightarrow$ but this year we use - \textcolor{red}{\texttt{scala-cli}} +\item contains a REPL $\Rightarrow$ this year we use + \sout{scala-cli} \textcolor{red}{\texttt{scala}} \item I use VS Codium and a Scala extension (M'place) \begin{center} \includegraphics[scale=0.10]{../pics/vscode.png}\\[-10mm]\mbox{} @@ -312,29 +312,32 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{frame}[c, fragile] -\frametitle{This year Scala 3/ \textbf{\texttt{scala-cli}}} +\frametitle{Scala 3} \mbox{}\\ \begin{minipage}{1.3\textwidth} \begin{center} -\textbf{\texttt{scala-cli}} -$\quad\Rightarrow$ {\small\url{https://scala-cli.virtuslab.org/}}\bigskip +\textbf{\texttt{scala}} +$\quad\Rightarrow$ {\small\url{https://www.scala-lang.org/download/}}\bigskip \end{center} Installation problems: \begin{itemize} -\item Oscar Sjostedt (\texttt{\small{}oscar.sjostedt@kcl.ac.uk}) -\item Nicole Lehchevska (\texttt{\small{}nicole.lehchevska@kcl.ac.uk})\bigskip +\item Flavio Melinte Citea (\texttt{\small{}flavio.melinte\_citea@kcl.ac.uk}) +\item Zishan Rahman (\texttt{\small{}zishan.rahman@kcl.ac.uk}) +\item Opale Sjostedt (\texttt{\small{}opale.sjostedt@kcl.ac.uk}) +\item Oliver Iliffe (\texttt{\small{}oliver.iliffe@kcl.ac.uk}) + \bigskip \end{itemize} Github problems: \begin{itemize} -\item Quan Tran (\texttt{\small{}anh.tran@kcl.ac.uk})\bigskip +\item Zishan Rahman (\texttt{\small{}zishan.rahman@kcl.ac.uk}) \end{itemize} -Discussion forum: -\begin{itemize} -\item Ruben Ticehurst-James (\texttt{\small{}ruben.ticehurst-james@kcl.ac.uk}) -\end{itemize} +%Discussion forum: +%\begin{itemize} +%\item Ruben Ticehurst-James (\texttt{\small{}ruben.ticehurst-james@kcl.ac.uk}) +%\end{itemize} \end{minipage} \end{frame} @@ -964,9 +967,9 @@ \frametitle{Conclusion for Today} \begin{itemize} -\item This year we will be using Scala 3 with the \texttt{scala-cli} REPL!\\ +\item This year we will be using Scala 3 with the \texttt{scala} REPL!\\ \medskip -\item {\bf\url{https://scala-cli.virtuslab.org/}}\bigskip +\item {\bf\url{https://www.scala-lang.org/}}\bigskip \item Scala can be a rather \textbf{\alert{deep}} language\ldots i.e.~gives you a lot of rope to shoot yourself.\bigskip diff -r 244df77507c2 -r 253d1ccb65de slides/slides02.pdf Binary file slides/slides02.pdf has changed diff -r 244df77507c2 -r 253d1ccb65de slides/slides02.tex --- a/slides/slides02.tex Sun Sep 15 12:57:59 2024 +0100 +++ b/slides/slides02.tex Mon Jul 21 16:38:07 2025 +0100 @@ -48,7 +48,7 @@ %Office: & N\liningnums{7.07} (North Wing, Bush House)\bigskip\\ Slides \& Code: & KEATS\bigskip\\ - Office Hour: & Fridays 13:00 -- 14:00\\ + Office Hour: & Thursdays 13:00 -- 14:00\\ Location: & N7.07 (North Wing, Bush House)\bigskip\\ Pollev: & \texttt{\alert{https://pollev.com/cfltutoratki576}}\\ \\ @@ -67,6 +67,69 @@ \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c, fragile] +\frametitle{Scala 3} + +\mbox{}\\ + +\begin{minipage}{1.3\textwidth} +\begin{center} +\textbf{\texttt{scala}} +$\quad\Rightarrow$ {\small\url{https://www.scala-lang.org/download/}}\bigskip +\end{center} + +Installation problems: +\begin{itemize} +\item Flavio Melinte Citea (\texttt{\small{}flavio.melinte\_citea@kcl.ac.uk}) +\item Zishan Rahman (\texttt{\small{}zishan.rahman@kcl.ac.uk}) +\item Opale Sjostedt (\texttt{\small{}opale.sjostedt@kcl.ac.uk}) +\item Oliver Iliffe (\texttt{\small{}oliver.iliffe@kcl.ac.uk}) + \bigskip +\end{itemize} +Github problems: +\begin{itemize} +\item Zishan Rahman (\texttt{\small{}zishan.rahman@kcl.ac.uk}) +\end{itemize} +%Discussion forum: +%\begin{itemize} +%\item Ruben Ticehurst-James (\texttt{\small{}ruben.ticehurst-james@kcl.ac.uk}) +%\end{itemize} +\end{minipage} + +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{frame}[c, fragile] +%%\frametitle{General Scheme of} + + \small +\begin{lstlisting}[language=Scala,numbers=none] +def fname(arg1: ty1, arg2: ty2,..., argn: tyn): rty = { + + .... + +} +\end{lstlisting} + + +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{frame}[c, fragile] + +\begin{lstlisting}[language=Scala,numbers=none] +def average(xs: List[Int]) : Int = { + val s = xs.sum + val n = xs.length + s / n +} +\end{lstlisting} + + +\end{frame} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \begin{frame}[t,fragile] diff -r 244df77507c2 -r 253d1ccb65de slides/slides03.pdf Binary file slides/slides03.pdf has changed diff -r 244df77507c2 -r 253d1ccb65de slides/slides03.tex --- a/slides/slides03.tex Sun Sep 15 12:57:59 2024 +0100 +++ b/slides/slides03.tex Mon Jul 21 16:38:07 2025 +0100 @@ -64,7 +64,7 @@ %Office: & N\liningnums{7.07} (North Wing, Bush House)\bigskip\\ Slides \& Code: & KEATS\bigskip\\ - Office Hour: & Fridays 13:00 -- 14:00\\ + Office Hour: & Thursdays 13:00 -- 14:00 (send email first)\\ Location: & N7.07 (North Wing, Bush House)\bigskip\\ Pollev: & \texttt{\alert{https://pollev.com/cfltutoratki576}}\\ \\ diff -r 244df77507c2 -r 253d1ccb65de slides/slides04.pdf Binary file slides/slides04.pdf has changed diff -r 244df77507c2 -r 253d1ccb65de slides/slides04.tex --- a/slides/slides04.tex Sun Sep 15 12:57:59 2024 +0100 +++ b/slides/slides04.tex Mon Jul 21 16:38:07 2025 +0100 @@ -178,10 +178,10 @@ %%Office: & N\liningnums{7.07} (North Wing, Bush House)\bigskip\\ Slides \& Code: & KEATS\bigskip\\ - Office Hour: & Fridays 13:00 -- 14:00\\ + Office Hour: & Thursdays 13:00 -- 14:00 (send email first)\\ Location: & N7.07 (North Wing, Bush House)\bigskip\\ - Pollev: & \texttt{\alert{https://pollev.com/cfltutoratki576}}\\ \\ + %Pollev: & \texttt{\alert{https://pollev.com/cfltutoratki576}}\\ \\ \end{tabular} \end{center} @@ -518,33 +518,33 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{frame}[c,fragile] -\small -\textcolor{red}{MacOSX}\medskip - -\begin{minipage}{13cm} - \begin{itemize} - \item[0)] (if needed) \texttt{brew install java} \;\;or\;\; \texttt{brew reinstall java} - \item[1)] \texttt{curl -s "https://get.sdkman.io" | bash} - \item[2)] \texttt{sdk install scala 2.13.7} - \end{itemize} -\end{minipage}\bigskip +%\begin{frame}[c,fragile] +%\small +%\textcolor{red}{MacOSX}\medskip +% +%\begin{minipage}{13cm} +% \begin{itemize} +% \item[0)] (if needed) \texttt{brew install java} \;\;or\;\; \texttt{brew reinstall java} +% \item[1)] \texttt{curl -s "https://get.sdkman.io" | bash} +% \item[2)] \texttt{sdk install scala 2.13.7} +% \end{itemize} +%\end{minipage}\bigskip -\textcolor{red}{Windows / Linux Ubuntu}\medskip +%\textcolor{red}{Windows / Linux Ubuntu}\medskip -\begin{minipage}{13cm} - \begin{itemize} - \item[0)] (if needed) \texttt{sudo apt-get remove scala-library scala} - \item[1)] {\fontsize{8.5}{8.5}\selectfont\texttt{sudo wget https://downloads.lightbend.com/scala/2.13.7/scala-2.13.7.deb}} - \item[2)] \texttt{sudo dpkg -i scala-2.13.7.deb} - \end{itemize} -\end{minipage}\bigskip +%\begin{minipage}{13cm} +% \begin{itemize} +% \item[0)] (if needed) \texttt{sudo apt-get remove scala-library scala} +% \item[1)] {\fontsize{8.5}{8.5}\selectfont\texttt{sudo wget https://downloads.lightbend.com/scala/2.13.7/scala-2.13.7.deb}} +% \item[2)] \texttt{sudo dpkg -i scala-2.13.7.deb} +% \end{itemize} +%\end{minipage}\bigskip -\begin{minipage}{13cm} -other Linux distros: \texttt{sudo apt-get scala} -\end{minipage} +%\begin{minipage}{13cm} +%other Linux distros: \texttt{sudo apt-get scala} +%\end{minipage} -\end{frame} +%\end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff -r 244df77507c2 -r 253d1ccb65de slides/slides05.pdf Binary file slides/slides05.pdf has changed diff -r 244df77507c2 -r 253d1ccb65de slides/slides05.tex --- a/slides/slides05.tex Sun Sep 15 12:57:59 2024 +0100 +++ b/slides/slides05.tex Mon Jul 21 16:38:07 2025 +0100 @@ -164,10 +164,10 @@ %Office: & N\liningnums{7.07} (North Wing, Bush House)\bigskip\\ Slides \& Code: & KEATS\bigskip\\ - Office Hour: & Fridays 13:00 -- 14:00\\ + Office Hour: & Thursdays 13:00 -- 14:00\\ Location: & N7.07 (North Wing, Bush House)\bigskip\\ - Pollev: & \texttt{\alert{https://pollev.com/cfltutoratki576}}\\ \\ + %Pollev: & \texttt{\alert{https://pollev.com/cfltutoratki576}}\\ \\ \end{tabular} \end{center} @@ -208,7 +208,7 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{frame}[c] +\begin{frame}<1>[c] \frametitle{Main 3: Regexes} \begin{center} @@ -337,54 +337,54 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{frame}[c,fragile] -\frametitle{Polyorphic Types} +% \begin{frame}[c,fragile] +% \frametitle{Polyorphic Types} -%To be avoided:\bigskip\bigskip -\small +% %To be avoided:\bigskip\bigskip +% \small -\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-6mm] -def length_string_list(lst: List[String]): Int = - lst match { - case Nil => 0 - case x::xs => 1 + length_string_list(xs) - } +% \begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-6mm] +% def length_string_list(lst: List[String]): Int = +% lst match { +% case Nil => 0 +% case x::xs => 1 + length_string_list(xs) +% } -def length_int_list(lst: List[Int]): Int = - lst match { - case Nil => 0 - case x::xs => 1 + length_int_list(xs) - } -\end{lstlisting} +% def length_int_list(lst: List[Int]): Int = +% lst match { +% case Nil => 0 +% case x::xs => 1 + length_int_list(xs) +% } +% \end{lstlisting} -\end{frame} +% \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{frame}[c,fragile] -\frametitle{Polyorphic Types} +% \begin{frame}[c,fragile] +% \frametitle{Polyorphic Types} -\small +% \small -\begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-6mm] -def length[A](lst: List[A]): Int = lst match { - case Nil => 0 - case x::xs => 1 + length(xs) -} +% \begin{lstlisting}[language=Scala, numbers=none, xleftmargin=-6mm] +% def length[A](lst: List[A]): Int = lst match { +% case Nil => 0 +% case x::xs => 1 + length(xs) +% } -length(List("1", "2", "3", "4")) -length(List(1, 2, 3, 4)) +% length(List("1", "2", "3", "4")) +% length(List(1, 2, 3, 4)) -def map[A, B](lst: List[A], f: A => B): List[B] = - lst match { - case Nil => Nil - case x::xs => f(x)::map(xs, f) - } -\end{lstlisting} -\end{frame} +% def map[A, B](lst: List[A], f: A => B): List[B] = +% lst match { +% case Nil => Nil +% case x::xs => f(x)::map(xs, f) +% } +% \end{lstlisting} +% \end{frame} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -485,25 +485,31 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{frame}[c] +\begin{frame}[t] \frametitle{Where to go on from here?} \begin{itemize} -\item Martin Odersky (EPFL) developed now Scala 3\medskip +\item Martin Odersky (EPFL) developed Scala\medskip \item I use Ammonite by Haoyi Li\medskip \item Elm (\url{http://elm-lang.org})\ldots web applications with style\medskip -\item Haskell, Ocaml, Standard ML, Scheme, \ldots +\item Haskell, Ocaml, Standard ML, Scheme, \ldots \bigskip\bigskip\bigskip \end{itemize} \begin{textblock}{5}(12,9) \includegraphics[scale=0.15]{../pics/haojili.png} \end{textblock} + +\only<2->{C++, Scala, } +\only<3->{PHP, Python, Perl, Bash} + \end{frame} + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%