--- 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}