diff -r 2969ee4a6cee -r ca9c1cf929fa progs/lecture3.scala --- a/progs/lecture3.scala Fri Nov 22 17:01:55 2019 +0000 +++ b/progs/lecture3.scala Tue Nov 26 01:22:36 2019 +0000 @@ -300,215 +300,6 @@ // User-defined Datatypes and Pattern Matching //============================================= -// trees - - - -// expressions - -sealed abstract class Exp -case class N(n: Int) extends Exp // for numbers -case class Plus(e1: Exp, e2: Exp) extends Exp -case class Times(e1: Exp, e2: Exp) extends Exp - -def string(e: Exp) : String = e match { - case N(n) => s"$n" - case Plus(e1, e2) => s"(${string(e1)} + ${string(e2)})" - case Times(e1, e2) => s"(${string(e1)} * ${string(e2)})" -} - -val e = Plus(N(9), Times(N(3), N(4))) -println(string(e)) - -def eval(e: Exp) : Int = e match { - case N(n) => n - case Plus(e1, e2) => eval(e1) + eval(e2) - case Times(e1, e2) => eval(e1) * eval(e2) -} - -println(eval(e)) - -def simp(e: Exp) : Exp = e match { - case N(n) => N(n) - case Plus(e1, e2) => (simp(e1), simp(e2)) match { - case (N(0), e2s) => e2s - case (e1s, N(0)) => e1s - case (e1s, e2s) => Plus(e1s, e2s) - } - case Times(e1, e2) => (simp(e1), simp(e2)) match { - case (N(0), _) => N(0) - case (_, N(0)) => N(0) - case (N(1), e2s) => e2s - case (e1s, N(1)) => e1s - case (e1s, e2s) => Times(e1s, e2s) - } -} - - -val e2 = Times(Plus(N(0), N(1)), Plus(N(0), N(9))) -println(string(e2)) -println(string(simp(e2))) - - -// Tokens and Reverse Polish Notation -sealed abstract class Token -case class T(n: Int) extends Token -case object PL extends Token -case object TI extends Token - -def rp(e: Exp) : List[Token] = e match { - case N(n) => List(T(n)) - case Plus(e1, e2) => rp(e1) ::: rp(e2) ::: List(PL) - case Times(e1, e2) => rp(e1) ::: rp(e2) ::: List(TI) -} -println(string(e2)) -println(rp(e2)) - -def comp(ls: List[Token], st: List[Int]) : Int = (ls, st) match { - case (Nil, st) => st.head - case (T(n)::rest, st) => comp(rest, n::st) - case (PL::rest, n1::n2::st) => comp(rest, n1 + n2::st) - case (TI::rest, n1::n2::st) => comp(rest, n1 * n2::st) -} - -comp(rp(e), Nil) - -def proc(s: String) : Token = s match { - case "+" => PL - case "*" => TI - case _ => T(s.toInt) -} - -comp("1 2 + 4 * 5 + 3 +".split(" ").toList.map(proc), Nil) - - - - -// Sudoku -//======== - -// THE POINT OF THIS CODE IS NOT TO BE SUPER -// EFFICIENT AND FAST, just explaining exhaustive -// depth-first search - - -val game0 = """.14.6.3.. - |62...4..9 - |.8..5.6.. - |.6.2....3 - |.7..1..5. - |5....9.6. - |..6.2..3. - |1..5...92 - |..7.9.41.""".stripMargin.replaceAll("\\n", "") - -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) = - (empty(game) % MaxValue, empty(game) / 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) - val ys = (y0 until y0 + 3).toList - (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)) - - -// this is not mutable!! -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)) - -//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 - } -} - -search(game0).map(pretty) - -val game1 = """23.915... - |...2..54. - |6.7...... - |..1.....9 - |89.5.3.17 - |5.....6.. - |......9.5 - |.16..7... - |...329..1""".stripMargin.replaceAll("\\n", "") - - -// game that is in the hard category -val game2 = """8........ - |..36..... - |.7..9.2.. - |.5...7... - |....457.. - |...1...3. - |..1....68 - |..85...1. - |.9....4..""".stripMargin.replaceAll("\\n", "") - -// game with multiple solutions -val game3 = """.8...9743 - |.5...8.1. - |.1....... - |8....5... - |...8.4... - |...3....6 - |.......7. - |.3.5...8. - |9724...5.""".stripMargin.replaceAll("\\n", "") - - -search(game1).map(pretty) -search(game3).map(pretty) -search(game2).map(pretty) - -// 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() - ((end - start) / 1.0e9) + " secs" -} - -time_needed(1, search(game2)) -