updated
authorChristian Urban <christian.urban@kcl.ac.uk>
Mon, 07 Dec 2020 01:25:41 +0000
changeset 383 c02929f2647c
parent 382 1bd800376e0c
child 384 6e1237691307
updated
progs/lecture4.scala
progs/lecture5.scala
progs/sudoku.scala
progs/sudoku_test.scala
slides/slides05.pdf
slides/slides05.tex
--- a/progs/lecture4.scala	Wed Dec 02 01:15:14 2020 +0000
+++ b/progs/lecture4.scala	Mon Dec 07 01:25:41 2020 +0000
@@ -271,40 +271,47 @@
               |1..5...92
               |..7.9.41.""".stripMargin.replaceAll("\\n", "")
 
-candidates(game0, (0, 0))
+
 
 type Pos = (Int, Int)
 val EmptyValue = '.'
 val MaxValue = 9
 
+def pretty(game: String): String = 
+  "\n" + (game.grouped(MaxValue).mkString("\n"))
+
+pretty(game0)
+
+
 val allValues = "123456789".toList
 val indexes = (0 to 8).toList
 
-
 def empty(game: String) = game.indexOf(EmptyValue)
 def isDone(game: String) = empty(game) == -1 
-def emptyPosition(game: String) = 
-  (empty(game) % MaxValue, empty(game) / MaxValue)
-
+def emptyPosition(game: String) = {
+  val e = empty(game)
+  (e % MaxValue, e / MaxValue)
+}
 
 def get_row(game: String, y: Int) = 
   indexes.map(col => game(y * MaxValue + col))
 def get_col(game: String, x: Int) = 
   indexes.map(row => game(x + row * MaxValue))
 
-get_row(game0, 0)
+//get_row(game0, 0)
+//get_row(game0, 1)
+//get_col(game0, 0)
 
 def get_box(game: String, pos: Pos): List[Char] = {
     def base(p: Int): Int = (p / 3) * 3
     val x0 = base(pos._1)
     val y0 = base(pos._2)
     val ys = (y0 until y0 + 3).toList
-    (x0 until x0 + 3).toList.flatMap(x => ys.map(y => game(x + y * MaxValue)))
+    (x0 until x0 + 3).toList
+      .flatMap(x => ys.map(y => game(x + y * MaxValue)))
 }
 
-//get_row(game0, 0)
-//get_row(game0, 1)
-//get_col(game0, 0)
+
 //get_box(game0, (3, 1))
 
 
@@ -313,26 +320,25 @@
   game.updated(pos, value)
 
 def toAvoid(game: String, pos: Pos): List[Char] = 
-  (get_col(game, pos._1) ++ get_row(game, pos._2) ++ get_box(game, pos))
+  (get_col(game, pos._1) ++ 
+   get_row(game, pos._2) ++ 
+   get_box(game, pos))
 
 def candidates(game: String, pos: Pos): List[Char] = 
   allValues.diff(toAvoid(game, pos))
 
 //candidates(game0, (0,0))
 
-def pretty(game: String): String = 
-  "\n" + (game.sliding(MaxValue, MaxValue).mkString("\n"))
 
 def search(game: String): List[String] = {
   if (isDone(game)) List(game)
   else {
     val cs = candidates(game, emptyPosition(game))
-    cs.map(c => search(update(game, empty(game), c))).toList.flatten
+    cs.map(c => search(update(game, empty(game), c))).flatten
   }
 }
 
-List(List("sol1"), List("sol2", "sol3")).flatten
-
+pretty(game0)
 search(game0).map(pretty)
 
 val game1 = """23.915...
--- a/progs/lecture5.scala	Wed Dec 02 01:15:14 2020 +0000
+++ b/progs/lecture5.scala	Mon Dec 07 01:25:41 2020 +0000
@@ -1,8 +1,6 @@
 // Scala Lecture 5
 //=================
 
-// TODO: word count for a very large file (40GB or so)
-// Transform Farenheit into Celsius
 
 
 // Laziness with style
@@ -174,7 +172,6 @@
 
 // (Immutable)
 // Object Oriented Programming in Scala
-//
 // =====================================
 
 
@@ -194,6 +191,13 @@
 println(Bird("Sparrow"))
 println(Bird("Sparrow").toString)
 
+Bird("Sparrow").copy(name = "House Sparrow")
+
+def group(a : Animal) = a match {
+  case Bird(_) => "It's a bird"
+  case Mammal(_) => "It's a mammal"
+}
+
 
 // There is a very convenient short-hand notation
 // for constructors:
@@ -204,11 +208,13 @@
 }
 
 val half = new Fraction(1, 2)
+half.numer
 
 case class Fraction(numer: Int, denom: Int)
 
 val half = Fraction(1, 2)
 
+half.numer
 half.denom
 
 
@@ -228,6 +234,9 @@
 
 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))
 
@@ -270,7 +279,7 @@
 }
 
 // BUT since we are completely IMMUTABLE, this is 
-// virtually of not concern to us.
+// virtually of no concern to us.
 
 
 
@@ -278,25 +287,26 @@
 import scala.language.implicitConversions
 import scala.language.reflectiveCalls
 
-
 case class Fraction(numer: Int, denom: Int) {
   override def toString = numer.toString + "/" + denom.toString
 
-  def +(other: Fraction) = Fraction(numer + other.numer, denom + other.denom)
-  def /(other: Fraction) = Fraction(numer * other.denom, denom * other.numer)
+  def +(other: Fraction) = 
+    Fraction(numer * other.denom + other.numer * denom, 
+             denom * other.denom)
+  def *(other: Fraction) = Fraction(numer * other.numer, denom * other.denom)
  }
 
 implicit def Int2Fraction(x: Int) = Fraction(x, 1)
 
-
 val half = Fraction(1, 2)
 val third = Fraction (1, 3)
 
 half + third
-half / third
+half * third
 
-(1 / 3) + half
-(1 / 2) + third
+1 + half
+
+
 
 
 // DFAs in Scala  
@@ -317,7 +327,7 @@
   }
 
   def accepts(s: List[C]) : Boolean = 
-    Try(fins(deltas(start, s))) getOrElse false
+    Try(fins(deltas(start, s))).getOrElse(false)
 }
 
 // the example shown in the handout 
@@ -359,7 +369,7 @@
   // given a state and a character, what is the set of 
   // next states? if there is none => empty set
   def next(q: A, c: C) : Set[A] = 
-    Try(delta(q, c)) getOrElse Set[A]() 
+    Try(delta(q, c)).getOrElse(Set[A]()) 
 
   def nexts(qs: Set[A], c: C) : Set[A] =
     qs.flatMap(next(_, c))
@@ -398,6 +408,7 @@
 // A: Subset construction. Here the state type for the DFA is
 //    sets of states.
 
+
 def subset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = {
   DFA(nfa.starts, 
       { case (qs, c) => nfa.nexts(qs, c) }, 
--- a/progs/sudoku.scala	Wed Dec 02 01:15:14 2020 +0000
+++ b/progs/sudoku.scala	Mon Dec 07 01:25:41 2020 +0000
@@ -21,8 +21,12 @@
 
 def empty(game: String) = game.indexOf(emptyValue)
 def isDone(game: String) = empty(game) == -1 
-def emptyPosition(game: String) : Pos = 
-  (empty(game) % maxValue, empty(game) / maxValue)
+//def emptyPosition(game: String) : Pos = 
+//  (empty(game) % maxValue, empty(game) / maxValue)
+def emptyPosition(game: String) = {
+  val e = empty(game)
+  (e % maxValue, e / maxValue)
+}
 
 
 def get_row(game: String, y: Int) = indexes.map(col => game(y * maxValue + col))
@@ -65,7 +69,7 @@
 }
 
 def pretty(game: String): String = 
-  "\n" + (game.sliding(maxValue, maxValue).mkString(",\n"))
+  "\n" + (game.grouped(maxValue).mkString(",\n"))
 
 
 // a list of hard games according to Andrew Coles and Peter Norvig
@@ -78,8 +82,8 @@
        "6.2.5.........3.4..........43...8....1....2........7..5..27...........81...6.....",
        ".524.........7.1..............8.2...3.....6...9.5.....1.6.3...........897........",
        "6.2.5.........4.3..........43...8....1....2........7..5..27...........81...6.....",
-       ".923.........8.1...........1.7.4...........658.........6.5.2...4.....7.....9.....",
-
+       ".923.........8.1...........1.7.4...........658.........6.5.2...4.....7.....9.....")
+/*
        "85...24..72......9..4.........1.7..23.5...9...4...........8..7..17..........36.4.",
        "..53.....8......2..7..1.5..4....53...1..7...6..32...8..6.5....9..4....3......97..",
        "12..4......5.69.1...9...5.........7.7...52.9..3......2.9.6...5.4..9..8.1..3...9.4",
@@ -183,9 +187,9 @@
        "3...8.......7....51..............36...2..4....7...........6.13..452...........8..",
        "....14....3....2...7..........9...3.6.1.............8.2.....1.4....5.6.....7.8...",
        "4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......")
-
-println("108:\n" ++ pretty(hard_games(108).replaceAll("\\.", " ")) ++ "\n")
-println("109:\n" ++ pretty(hard_games(109).replaceAll("\\.", " ")) ++ "\n")
+*/
+//println("108:\n" ++ pretty(hard_games(108).replaceAll("\\.", " ")) ++ "\n")
+//println("109:\n" ++ pretty(hard_games(109).replaceAll("\\.", " ")) ++ "\n")
 
 
 // for measuring time
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/progs/sudoku_test.scala	Mon Dec 07 01:25:41 2020 +0000
@@ -0,0 +1,88 @@
+// Sudoku
+//========
+
+// call parallel version with
+//
+// scala -cp scala-parallel-collections_2.13-0.2.0.jar sudoku_test.scala 
+//
+// or
+//
+// scalac -cp scala-parallel-collections_2.13-0.2.0.jar sudoku_test.scala
+// java -cp .:scala-library-2.13.0.jar:scala-parallel-collections_2.13-0.2.0.jar Sudoku
+
+object Sudoku extends App { 
+
+import scala.collection.parallel.CollectionConverters._
+
+type Pos = (Int, Int)
+val emptyValue = '.'
+val maxValue = 9
+
+val allValues = "123456789".toList
+val indexes = (0 to 8).toList
+
+
+def empty(game: String) = game.indexOf(emptyValue)
+def isDone(game: String) = empty(game) == -1 
+def emptyPosition(game: String) = {
+  val e = empty(game)
+  (e % maxValue, e / maxValue)
+}
+
+
+def get_row(game: String, y: Int) = indexes.map(col => game(y * maxValue + col))
+def get_col(game: String, x: Int) = indexes.map(row => game(x + row * maxValue))
+
+def get_box(game: String, pos: Pos): List[Char] = {
+    def base(p: Int): Int = (p / 3) * 3
+    val x0 = base(pos._1)
+    val y0 = base(pos._2)
+    for (x <- (x0 until x0 + 3).toList;
+         y <- (y0 until y0 + 3).toList) yield game(x + y * maxValue)
+}         
+
+
+def update(game: String, pos: Int, value: Char): String = 
+  game.updated(pos, value)
+
+def toAvoid(game: String, pos: Pos): List[Char] = 
+  (get_col(game, pos._1) ++ get_row(game, pos._2) ++ get_box(game, pos))
+
+def candidates(game: String, pos: Pos): List[Char] = 
+  allValues.diff(toAvoid(game, pos))
+
+def search(game: String): List[String] = {
+  if (isDone(game)) List(game)
+  else {
+    val cs = candidates(game, emptyPosition(game))
+    cs.par.map(c => search(update(game, empty(game), c))).toList.flatten
+  }
+}
+
+
+def pretty(game: String): String = 
+  "\n" + (game.grouped(maxValue).mkString(",\n"))
+
+
+val game2 = """8........
+              |..36.....
+              |.7..9.2..
+              |.5...7...
+              |....457..
+              |...1...3.
+              |..1....68
+              |..85...1.
+              |.9....4..""".stripMargin.replaceAll("\\n", "")
+
+// for measuring time
+def time_needed[T](i: Int, code: => T) = {
+  val start = System.nanoTime()
+  for (j <- 1 to i) code
+  val end = System.nanoTime()
+  s"${(end - start) / 1.0e9} secs"
+}
+
+
+println(time_needed(10, search(game2)))
+
+}
Binary file slides/slides05.pdf has changed
--- a/slides/slides05.tex	Wed Dec 02 01:15:14 2020 +0000
+++ b/slides/slides05.tex	Mon Dec 07 01:25:41 2020 +0000
@@ -1,5 +1,5 @@
 % !TEX program = xelatex
-\documentclass[dvipsnames,14pt,t,xelatex]{beamer}
+\documentclass[dvipsnames,14pt,t,xelatex,aspectratio=169,xcolor={table}]{beamer}
 \usepackage{../slides}
 \usepackage{../graphics}
 \usepackage{../langs}
@@ -37,11 +37,11 @@
   \begin{center}
   \begin{tabular}{ll}
     Email:  & christian.urban at kcl.ac.uk\\
-    Office: & N\liningnums{7.07} (North Wing, Bush House)\bigskip\\
+    %Office: & N\liningnums{7.07} (North Wing, Bush House)\bigskip\\
     Slides \& Code: & KEATS\\
-                    & \onslide<2>{\alert{PDF: A Crash-Course in Scala}}\bigskip\\
-    Office Hours: &  Thursdays 12:00 -- 14:00\\
-    Additionally: & (for Scala) Tuesdays 10:45 -- 11:45\\ 
+    %                & \onslide<2>{\alert{PDF: A Crash-Course in Scala}}\bigskip\\
+    %Office Hours: &  Thursdays 12:00 -- 14:00\\
+    %Additionally: & (for Scala) Tuesdays 10:45 -- 11:45\\ 
   \end{tabular}
   \end{center}
 
@@ -50,23 +50,23 @@
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%     
 
-\begin{frame}[c]
-\frametitle{Marks for Preliminary 8}
-
-Raw marks (265 submissions):\bigskip
-
-\begin{itemize}
-\item 4\%: \hspace{4mm}211
-\item 3\%: \hspace{4mm}11
-\item 2\%: \hspace{4mm}14
-\item 1\%: \hspace{4mm}8
-\item 0\%: \hspace{4mm}21
-\end{itemize}\bigskip\bigskip  
-
-\footnotesize
-(plagiarism/collusion interviews ongoing again!)
-
-\end{frame}
+%\begin{frame}[c]
+%\frametitle{Marks for Preliminary 8}
+%
+%Raw marks (265 submissions):\bigskip
+%
+%\begin{itemize}
+%\item 4\%: \hspace{4mm}211
+%\item 3\%: \hspace{4mm}11
+%\item 2\%: \hspace{4mm}14
+%\item 1\%: \hspace{4mm}8
+%\item 0\%: \hspace{4mm}21
+%\end{itemize}\bigskip\bigskip  
+%
+%\footnotesize
+%(plagiarism/collusion interviews ongoing again!)
+%
+%\end{frame}
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%     
@@ -180,13 +180,13 @@
 \end{tikzpicture}
 \end{center}
 
-\begin{textblock}{9}(4,12)
-\LARGE{}
-\only<3->{\boldmath\alert{$a$}}%
-\only<4->{\boldmath\alert{$b$}}%
-\only<5->{\boldmath\alert{$a$}}%
-\only<6->{\boldmath\alert{$a$}}%
-\only<7->{\boldmath\alert{$a\quad\Rightarrow \textbf{yes}$}}% 
+\begin{textblock}{10}(4,12)
+\LARGE{}\phantom{b}
+\only<-2>{\boldmath\textcolor{gray}{$a$}}\only<3->{\boldmath\alert{$a$}}%
+\only<-3>{\boldmath\textcolor{gray}{$b$}}\only<4->{\boldmath\alert{$b$}}%
+\only<-4>{\boldmath\textcolor{gray}{$a$}}\only<5->{\boldmath\alert{$a$}}%
+\only<-5>{\boldmath\textcolor{gray}{$a$}}\only<6->{\boldmath\alert{$a$}}%
+\only<-6>{\boldmath\textcolor{gray}{$a$}}\only<7->{\boldmath\alert{$a\quad\Rightarrow \textbf{yes}$}}% 
 \end{textblock}
   
 \end{frame}