diff -r 029e2862bb4e -r b84ea52bfd8f progs/lecture2.scala --- a/progs/lecture2.scala Tue Nov 12 00:41:00 2019 +0000 +++ b/progs/lecture2.scala Tue Nov 12 10:47:27 2019 +0000 @@ -75,11 +75,14 @@ // the same for files Try(Some(Source.fromFile("text.txt").mkString)).getOrElse(None) -// how to implement a function for reading something from files... +// how to implement a function for reading +// (lines) something from files... +// def get_contents(name: String) : List[String] = Source.fromFile(name).getLines.toList +get_contents("text.txt") get_contents("test.txt") // slightly better - return Nil @@ -156,6 +159,7 @@ //======================== // functions can take functions as arguments +// and produce functions as result def even(x: Int) : Boolean = x % 2 == 0 def odd(x: Int) : Boolean = x % 2 == 1 @@ -204,8 +208,8 @@ lst.map(square) -// this is actually how for-comprehensions -// defined as in Scala +// this is actually how for-comprehensions are +// defined in Scala lst.map(n => square(n)) for (n <- lst) yield square(n) @@ -232,7 +236,8 @@ // same function using pattern matching: a kind // of switch statement on steroids (see more later on) -def my_map_int(lst: List[Int], f: Int => Int) : List[Int] = lst match { +def my_map_int(lst: List[Int], f: Int => Int) : List[Int] = +lst match { case Nil => Nil case x::xs => f(x)::my_map_int(xs, f) } @@ -268,10 +273,10 @@ // sometimes it is needed that you specify the type. (1 to 100).filter((x: Int) => x % 2 == 0).sum -// in this case it is clear that x mist be an Int +// in this case it is clear that x must be an Int (1 to 100).filter(x => x % 2 == 0).sum -// As each parameter (only x in this case) is passed only once +// When each parameter (only x in this case) is used only once // you can use the wizardy placeholder syntax (1 to 100).filter(_ % 2 == 0).sum @@ -334,7 +339,7 @@ facsMap.get(1) facsMap2.get(1) -// groupBy function on maps +// groupBy function on Maps val ls = List("one", "two", "three", "four", "five") ls.groupBy(_.length) @@ -361,18 +366,17 @@ // } - - -// remember? +// recall val lst = List(None, Some(1), Some(2), None, Some(3)).flatten - def my_flatten(xs: List[Option[Int]]): List[Int] = xs match { case Nil => Nil case None::rest => my_flatten(rest) case Some(v)::rest => v :: my_flatten(rest) } +my_flatten(List(None, Some(1), Some(2), None, Some(3))) + // another example with a default case def get_me_a_string(n: Int): String = n match { @@ -538,4 +542,73 @@ +// Jumping Towers +//================ + +def moves(xs: List[Int], n: Int) : List[List[Int]] = (xs, n) match { + case (Nil, _) => Nil + case (xs, 0) => Nil + case (x::xs, n) => (x::xs) :: moves(xs, n - 1) +} + + +moves(List(5,1,0), 1) +moves(List(5,1,0), 2) +moves(List(5,1,0), 5) + +// checks whether a jump tour exists at all + +def search(xs: List[Int]) : Boolean = xs match { + case Nil => true + case (x::xs) => + if (xs.length < x) true else moves(xs, x).exists(search(_)) +} + + +search(List(5,3,2,5,1,1)) +search(List(3,5,1,0,0,0,1)) +search(List(3,5,1,0,0,0,0,1)) +search(List(3,5,1,0,0,0,1,1)) +search(List(3,5,1)) +search(List(5,1,1)) +search(Nil) +search(List(1)) +search(List(5,1,1)) +search(List(3,5,1,0,0,0,0,0,0,0,0,1)) + +// generate *all* jump tours +// if we are only interested in the shortes one, we could +// shortcircut the calculation and only return List(x) in +// case where xs.length < x, because no tour can be shorter +// than 1 +// + +def jumps(xs: List[Int]) : List[List[Int]] = xs match { + case Nil => Nil + case (x::xs) => { + val children = moves(xs, x) + val results = children.map(cs => jumps(cs).map(x :: _)).flatten + if (xs.length < x) List(x) :: results else results + } +} + +jumps(List(3,5,1,2,1,2,1)) +jumps(List(3,5,1,2,3,4,1)) +jumps(List(3,5,1,0,0,0,1)) +jumps(List(3,5,1)) +jumps(List(5,1,1)) +jumps(Nil) +jumps(List(1)) +jumps(List(5,1,2)) +moves(List(1,2), 5) +jumps(List(1,5,1,2)) +jumps(List(3,5,1,0,0,0,0,0,0,0,0,1)) + +jumps(List(5,3,2,5,1,1)).minBy(_.length) +jumps(List(1,3,5,8,9,2,6,7,6,8,9)).minBy(_.length) +jumps(List(1,3,6,1,0,9)).minBy(_.length) +jumps(List(2,3,1,1,2,4,2,0,1,1)).minBy(_.length) + + +