19 bcollatz(9.toBinaryString)  | 
    84 bcollatz(9.toBinaryString)  | 
    20 bcollatz(837799.toBinaryString)  | 
    85 bcollatz(837799.toBinaryString)  | 
    21 bcollatz(100000000000000000L.toBinaryString)  | 
    86 bcollatz(100000000000000000L.toBinaryString)  | 
    22 bcollatz(BigInt("1000000000000000000000000000000000000000000000000000000000000000000000000000").toString(2)) | 
    87 bcollatz(BigInt("1000000000000000000000000000000000000000000000000000000000000000000000000000").toString(2)) | 
    23   | 
    88   | 
    24 def conv(c: Char) : Int = c match { | 
    89   | 
    25   case '0' => 0  | 
    90   | 
    26   case '1' => 1  | 
    91   | 
    27 }  | 
    92 // User-defined Datatypes  | 
    28   | 
    93 //========================  | 
    29 def badds(s1: String, s2: String, carry: Int) : String = (s1, s2, carry) match { | 
    94   | 
    30   case ("", "", 1) => "1" | 
    95 abstract class Colour  | 
    31   case ("", "", 0) => "" | 
    96 case class Red() extends Colour   | 
    32   case (cs1, cs2, carry) => (conv(cs1.last) + conv(cs2.last) + carry) match { | 
    97 case class Green() extends Colour   | 
    33     case 3 => badds(cs1.dropRight(1), cs2.dropRight(1), 1) + '1'  | 
    98 case class Blue() extends Colour  | 
    34     case 2 => badds(cs1.dropRight(1), cs2.dropRight(1), 1) + '0'  | 
    99   | 
    35     case 1 => badds(cs1.dropRight(1), cs2.dropRight(1), 0) + '1'  | 
   100 def fav_colour(c: Colour) : Boolean = c match { | 
    36     case 0 => badds(cs1.dropRight(1), cs2.dropRight(1), 0) + '0'  | 
   101   case Red()   => false  | 
    37   }  | 
   102   case Green() => true  | 
    38 }   | 
   103   case Blue()  => false   | 
    39   | 
   104 }  | 
    40 def bcollatz2(s: String) : Long = (s.dropRight(1), s.last) match { | 
   105   | 
    41   case ("", '1') => 1                                          // we reached 1 | 
   106   | 
    42   case (rest, '0') => 1 + bcollatz2(rest)                      // even number => divide by two  | 
   107 // actually colors can be written with "object",  | 
    43   case (rest, '1') => 1 + bcollatz2(badds(s + '1', '0' + s, 0))   // odd number => s + '1' is 2 * s + 1  | 
   108 // because they do not take any arguments  | 
    44                                                                   //         add another s gives 3 * s + 1    | 
         | 
    45 }   | 
         | 
    46   | 
         | 
    47 bcollatz2(9.toBinaryString)  | 
         | 
    48 bcollatz2(837799.toBinaryString)  | 
         | 
    49 bcollatz2(100000000000000000L.toBinaryString)  | 
         | 
    50 bcollatz2(BigInt("1000000000000000000000000000000000000000000000000000000000000000000000000000").toString(2)) | 
         | 
    51   | 
   109   | 
    52   | 
   110   | 
    53   | 
   111   | 
    54 // Roman Numerals  | 
   112 // Roman Numerals  | 
    55 abstract class RomanDigit   | 
   113 abstract class RomanDigit   | 
    86 RomanNumeral2Int(List(I,X))             // 9  | 
   144 RomanNumeral2Int(List(I,X))             // 9  | 
    87 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979  | 
   145 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979  | 
    88 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017  | 
   146 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017  | 
    89   | 
   147   | 
    90   | 
   148   | 
         | 
   149   | 
         | 
   150 // another example  | 
         | 
   151 //=================  | 
         | 
   152   | 
         | 
   153 // Once upon a time, in a complete fictional country there were persons...  | 
         | 
   154   | 
         | 
   155 abstract class Person  | 
         | 
   156 case class King() extends Person  | 
         | 
   157 case class Peer(deg: String, terr: String, succ: Int) extends Person  | 
         | 
   158 case class Knight(name: String) extends Person  | 
         | 
   159 case class Peasant(name: String) extends Person  | 
         | 
   160   | 
         | 
   161   | 
         | 
   162 def title(p: Person): String = p match { | 
         | 
   163   case King() => "His Majesty the King"  | 
         | 
   164   case Peer(deg, terr, _) => s"The ${deg} of ${terr}" | 
         | 
   165   case Knight(name) => s"Sir ${name}" | 
         | 
   166   case Peasant(name) => name  | 
         | 
   167 }  | 
         | 
   168   | 
         | 
   169   | 
         | 
   170 def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { | 
         | 
   171   case (King(), _) => true  | 
         | 
   172   case (Peer(_,_,_), Knight(_)) => true  | 
         | 
   173   case (Peer(_,_,_), Peasant(_)) => true  | 
         | 
   174   case (Peer(_,_,_), Clown()) => true  | 
         | 
   175   case (Knight(_), Peasant(_)) => true  | 
         | 
   176   case (Knight(_), Clown()) => true  | 
         | 
   177   case (Clown(), Peasant(_)) => true  | 
         | 
   178   case _ => false  | 
         | 
   179 }  | 
         | 
   180   | 
         | 
   181 val people = List(Knight("David"),  | 
         | 
   182                   Peer("Duke", "Norfolk", 84),  | 
         | 
   183                   Peasant("Christian"),  | 
         | 
   184                   King(),   | 
         | 
   185                   Clown())  | 
         | 
   186   | 
         | 
   187 println(people.sortWith(superior(_, _)).mkString(", ")) | 
         | 
   188   | 
         | 
   189   | 
         | 
   190   | 
         | 
   191   | 
    91 // Tail recursion  | 
   192 // Tail recursion  | 
    92 //================  | 
   193 //================  | 
    93   | 
   194   | 
    94 def my_contains(elem: Int, lst: List[Int]): Boolean = lst match { | 
         | 
    95   case Nil => false  | 
         | 
    96   case x::xs =>   | 
         | 
    97     if (x == elem) true else my_contains(elem, xs)  | 
         | 
    98 }  | 
         | 
    99   | 
         | 
   100 my_contains(4, List(1,2,3))  | 
         | 
   101 my_contains(2, List(1,2,3))  | 
         | 
   102   | 
         | 
   103 my_contains(1000000, (1 to 1000000).toList)  | 
         | 
   104 my_contains(1000001, (1 to 1000000).toList)  | 
         | 
   105   | 
         | 
   106   | 
         | 
   107 //factorial V0.1  | 
         | 
   108 import scala.annotation.tailrec  | 
         | 
   109   | 
         | 
   110   | 
   195   | 
   111 def fact(n: Long): Long =   | 
   196 def fact(n: Long): Long =   | 
   112   if (n == 0) 1 else n * fact(n - 1)  | 
   197   if (n == 0) 1 else n * fact(n - 1)  | 
   113   | 
   198   | 
   114 fact(10000)                        // produces a stackoverflow  | 
   199 fact(10)              //ok  | 
         | 
   200 fact(10000)           // produces a stackoverflow  | 
         | 
   201   | 
         | 
   202 def factT(n: BigInt, acc: BigInt): BigInt =  | 
         | 
   203   if (n == 0) acc else factT(n - 1, n * acc)  | 
         | 
   204   | 
         | 
   205 factT(100000, 1)  | 
         | 
   206   | 
         | 
   207 // there is a flag for ensuring a function is tail recursive  | 
         | 
   208 import scala.annotation.tailrec  | 
   115   | 
   209   | 
   116 @tailrec  | 
   210 @tailrec  | 
   117 def factT(n: BigInt, acc: BigInt): BigInt =  | 
   211 def factT(n: BigInt, acc: BigInt): BigInt =  | 
   118   if (n == 0) acc else factT(n - 1, n * acc)  | 
   212   if (n == 0) acc else factT(n - 1, n * acc)  | 
   119   | 
   213   | 
   120   | 
   214   | 
   121 println(factT(10000, 1))  | 
   215   | 
   122   | 
   216 // for tail-recursive functions the Scala compiler  | 
   123 // the functions my_contains and factT are tail-recursive   | 
         | 
   124 // you can check this with   | 
         | 
   125   | 
         | 
   126 import scala.annotation.tailrec  | 
         | 
   127   | 
         | 
   128 // and the annotation @tailrec  | 
         | 
   129   | 
         | 
   130 // for tail-recursive functions the scala compiler  | 
         | 
   131 // generates loop-like code, which does not need  | 
   217 // generates loop-like code, which does not need  | 
   132 // to allocate stack-space in each recursive  | 
   218 // to allocate stack-space in each recursive  | 
   133 // call; scala can do this only for tail-recursive  | 
   219 // call; Scala can do this only for tail-recursive  | 
   134 // functions  | 
   220 // functions  | 
   135   | 
   221   | 
   136 // consider the following "stupid" version of the  | 
   222   | 
   137 // coin exchange problem: given some coins and a  | 
   223   | 
   138 // total, what is the change can you get?  | 
   224 // sudoku again  | 
   139   | 
   225   | 
   140 val coins = List(4,5,6,8,10,13,19,20,21,24,38,39,40)  | 
   226 val game0 = """.14.6.3..  | 
   141   | 
   227               |62...4..9  | 
   142 def first_positive[B](lst: List[Int], f: Int => Option[B]): Option[B] = lst match { | 
   228               |.8..5.6..  | 
         | 
   229               |.6.2....3  | 
         | 
   230               |.7..1..5.  | 
         | 
   231               |5....9.6.  | 
         | 
   232               |..6.2..3.  | 
         | 
   233               |1..5...92  | 
         | 
   234               |..7.9.41.""".stripMargin.replaceAll("\\n", "") | 
         | 
   235   | 
         | 
   236 type Pos = (Int, Int)  | 
         | 
   237 val EmptyValue = '.'  | 
         | 
   238 val MaxValue = 9  | 
         | 
   239   | 
         | 
   240 val allValues = "123456789".toList  | 
         | 
   241 val indexes = (0 to 8).toList  | 
         | 
   242   | 
         | 
   243   | 
         | 
   244 def empty(game: String) = game.indexOf(EmptyValue)  | 
         | 
   245 def isDone(game: String) = empty(game) == -1   | 
         | 
   246 def emptyPosition(game: String) =   | 
         | 
   247   (empty(game) % MaxValue, empty(game) / MaxValue)  | 
         | 
   248   | 
         | 
   249   | 
         | 
   250 def get_row(game: String, y: Int) =   | 
         | 
   251   indexes.map(col => game(y * MaxValue + col))  | 
         | 
   252 def get_col(game: String, x: Int) =   | 
         | 
   253   indexes.map(row => game(x + row * MaxValue))  | 
         | 
   254   | 
         | 
   255 def get_box(game: String, pos: Pos): List[Char] = { | 
         | 
   256     def base(p: Int): Int = (p / 3) * 3  | 
         | 
   257     val x0 = base(pos._1)  | 
         | 
   258     val y0 = base(pos._2)  | 
         | 
   259     val ys = (y0 until y0 + 3).toList  | 
         | 
   260     (x0 until x0 + 3).toList.flatMap(x => ys.map(y => game(x + y * MaxValue)))  | 
         | 
   261 }  | 
         | 
   262   | 
         | 
   263 // this is not mutable!!  | 
         | 
   264 def update(game: String, pos: Int, value: Char): String =   | 
         | 
   265   game.updated(pos, value)  | 
         | 
   266   | 
         | 
   267 def toAvoid(game: String, pos: Pos): List[Char] =   | 
         | 
   268   (get_col(game, pos._1) ++ get_row(game, pos._2) ++ get_box(game, pos))  | 
         | 
   269   | 
         | 
   270 def candidates(game: String, pos: Pos): List[Char] =   | 
         | 
   271   allValues.diff(toAvoid(game,pos))  | 
         | 
   272   | 
         | 
   273 //candidates(game0, (0,0))  | 
         | 
   274   | 
         | 
   275 def pretty(game: String): String =   | 
         | 
   276   "\n" + (game sliding (MaxValue, MaxValue) mkString "\n")  | 
         | 
   277   | 
         | 
   278 // not tail recursive   | 
         | 
   279 def search(game: String): List[String] = { | 
         | 
   280   if (isDone(game)) List(game)  | 
         | 
   281   else { | 
         | 
   282     val cs = candidates(game, emptyPosition(game))  | 
         | 
   283     cs.map(c => search(update(game, empty(game), c))).toList.flatten  | 
         | 
   284   }  | 
         | 
   285 }  | 
         | 
   286   | 
         | 
   287 // tail recursive version that searches   | 
         | 
   288 // for all solution  | 
         | 
   289 def searchT(games: List[String], sols: List[String]): List[String] = games match { | 
         | 
   290   case Nil => sols  | 
         | 
   291   case game::rest => { | 
         | 
   292     if (isDone(game)) searchT(rest, game::sols)  | 
         | 
   293     else { | 
         | 
   294       val cs = candidates(game, emptyPosition(game))  | 
         | 
   295       searchT(cs.map(c => update(game, empty(game), c)) ::: rest, sols)  | 
         | 
   296     }  | 
         | 
   297   }  | 
         | 
   298 }  | 
         | 
   299   | 
         | 
   300 // tail recursive version that searches   | 
         | 
   301 // for a single solution  | 
         | 
   302 def search1T(games: List[String]): Option[String] = games match { | 
   143   case Nil => None  | 
   303   case Nil => None  | 
   144   case x::xs =>   | 
   304   case game::rest => { | 
   145     if (x <= 0) first_positive(xs, f)  | 
   305     if (isDone(game)) Some(game)  | 
   146     else { | 
   306     else { | 
   147       val fx = f(x)  | 
   307       val cs = candidates(game, emptyPosition(game))  | 
   148       if (fx.isDefined) fx else first_positive(xs, f)  | 
   308       search1T(cs.map(c => update(game, empty(game), c)) ::: rest)  | 
         | 
   309     }  | 
   149   }  | 
   310   }  | 
   150 }  | 
   311 }  | 
   151   | 
   312   | 
   152   | 
   313 // game with multiple solutions  | 
   153 import scala.annotation.tailrec  | 
   314 val game3 = """.8...9743  | 
   154   | 
   315               |.5...8.1.  | 
   155 def search(total: Int, coins: List[Int], cs: List[Int]): Option[List[Int]] = { | 
   316               |.1.......  | 
   156   if (total < cs.sum) None   | 
   317               |8....5...  | 
   157   else if (cs.sum == total) Some(cs)   | 
   318               |...8.4...  | 
   158   else first_positive(coins, (c: Int) => search(total, coins, c::cs))  | 
   319               |...3....6  | 
   159 }  | 
   320               |.......7.  | 
   160   | 
   321               |.3.5...8.  | 
   161 search(11, coins, Nil)  | 
   322               |9724...5.""".stripMargin.replaceAll("\\n", "") | 
   162 search(111, coins, Nil)  | 
   323   | 
   163 search(111111, coins, Nil)  | 
   324 searchT(List(game3), List()).map(pretty)  | 
   164   | 
   325 search1T(List(game3)).map(pretty)  | 
   165 val junk_coins = List(4,-2,5,6,8,0,10,13,19,20,-3,21,24,38,39, 40)  | 
         | 
   166 search(11, junk_coins, Nil)  | 
         | 
   167 search(111, junk_coins, Nil)  | 
         | 
   168   | 
         | 
   169   | 
         | 
   170 import scala.annotation.tailrec  | 
         | 
   171   | 
         | 
   172 @tailrec  | 
         | 
   173 def searchT(total: Int, coins: List[Int],   | 
         | 
   174             acc_cs: List[List[Int]]): Option[List[Int]] = acc_cs match { | 
         | 
   175   case Nil => None  | 
         | 
   176   case x::xs =>   | 
         | 
   177     if (total < x.sum) searchT(total, coins, xs)  | 
         | 
   178     else if (x.sum == total) Some(x)   | 
         | 
   179     else searchT(total, coins, coins.filter(_ > 0).map(_::x) ::: xs)  | 
         | 
   180 }  | 
         | 
   181   | 
         | 
   182 val start_acc = coins.filter(_ > 0).map(List(_))  | 
         | 
   183 searchT(11, junk_coins, start_acc)  | 
         | 
   184 searchT(111, junk_coins, start_acc)  | 
         | 
   185 searchT(111111, junk_coins, start_acc)  | 
         | 
   186   | 
   326   | 
   187 // Moral: Whenever a recursive function is resource-critical  | 
   327 // Moral: Whenever a recursive function is resource-critical  | 
   188 // (i.e. works with large recursion depths), then you need to  | 
   328 // (i.e. works with large recursion depths), then you need to  | 
   189 // write it in tail-recursive fashion.  | 
   329 // write it in tail-recursive fashion.  | 
   190 //   | 
   330 //   | 
   191 // Unfortuantely, the Scala is because of current limitations in   | 
   331 // Unfortuantely, Scala because of current limitations in   | 
   192 // the JVM not as clever as other functional languages. It can   | 
   332 // the JVM is not as clever as other functional languages. It can   | 
   193 // only optimise "self-tail calls". This excludes the cases of   | 
   333 // only optimise "self-tail calls". This excludes the cases of   | 
   194 // multiple functions making tail calls to each other. Well,  | 
   334 // multiple functions making tail calls to each other. Well,  | 
   195 // nothing is perfect.   | 
   335 // nothing is perfect.   | 
   196   | 
   336   | 
   197   | 
   337   | 
   228   | 
   368   | 
   229 // Remember?  | 
   369 // Remember?  | 
   230 def first[A, B](xs: List[A], f: A => Option[B]): Option[B] = ...  | 
   370 def first[A, B](xs: List[A], f: A => Option[B]): Option[B] = ...  | 
   231   | 
   371   | 
   232   | 
   372   | 
   233 // polymorphic classes  | 
   373   | 
   234 //(trees with some content)  | 
   374 // Cool Stuff  | 
   235   | 
   375 //============  | 
   236 abstract class Tree[+A]  | 
   376   | 
   237 case class Node[A](elem: A, left: Tree[A], right: Tree[A]) extends Tree[A]  | 
   377   | 
   238 case object Leaf extends Tree[Nothing]  | 
   378   | 
   239   | 
   379   | 
   240 val t0 = Node('4', Node('2', Leaf, Leaf), Node('7', Leaf, Leaf)) | 
   380 // Implicits   | 
   241   | 
   381 //===========  | 
   242 def insert[A](tr: Tree[A], n: A): Tree[A] = tr match { | 
   382 //  | 
   243   case Leaf => Node(n, Leaf, Leaf)  | 
   383 // For example adding your own methods to Strings:  | 
   244   case Node(m, left, right) =>   | 
   384 // Imagine you want to increment strings, like  | 
   245     if (n == m) Node(m, left, right)   | 
   385 //  | 
   246     else if (n < m) Node(m, insert(left, n), right)  | 
   386 //     "HAL".increment  | 
   247     else Node(m, left, insert(right, n))  | 
   387 //  | 
   248 }  | 
   388 // you can avoid ugly fudges, like a MyString, by  | 
   249   | 
   389 // using implicit conversions.  | 
   250   | 
   390   | 
   251 // the A-type needs to be ordered  | 
   391   | 
   252   | 
   392 implicit class MyString(s: String) { | 
   253 abstract class Tree[+A <% Ordered[A]]  | 
   393   def increment = for (c <- s) yield (c + 1).toChar   | 
   254 case class Node[A <% Ordered[A]](elem: A, left: Tree[A],   | 
   394 }  | 
   255                                  right: Tree[A]) extends Tree[A]  | 
   395   | 
   256 case object Leaf extends Tree[Nothing]  | 
   396 "HAL".increment  | 
   257   | 
   397   | 
   258   | 
         | 
   259 def insert[A <% Ordered[A]](tr: Tree[A], n: A): Tree[A] = tr match { | 
         | 
   260   case Leaf => Node(n, Leaf, Leaf)  | 
         | 
   261   case Node(m, left, right) =>   | 
         | 
   262     if (n == m) Node(m, left, right)   | 
         | 
   263     else if (n < m) Node(m, insert(left, n), right)  | 
         | 
   264     else Node(m, left, insert(right, n))  | 
         | 
   265 }  | 
         | 
   266   | 
         | 
   267   | 
         | 
   268 val t1 = Node(4, Node(2, Leaf, Leaf), Node(7, Leaf, Leaf))  | 
         | 
   269 insert(t1, 3)  | 
         | 
   270   | 
         | 
   271 val t2 = Node('b', Node('a', Leaf, Leaf), Node('f', Leaf, Leaf)) | 
         | 
   272 insert(t2, 'e')  | 
         | 
   273   | 
   398   | 
   274   | 
   399   | 
   275   | 
   400   | 
   276 // Regular expressions - the power of DSLs in Scala  | 
   401 // Regular expressions - the power of DSLs in Scala  | 
   277 //==================================================  | 
   402 //==================================================  | 
   278   | 
   403   | 
   279   | 
         | 
   280 abstract class Rexp  | 
   404 abstract class Rexp  | 
   281 case object ZERO extends Rexp  | 
   405 case object ZERO extends Rexp                       // nothing  | 
   282 case object ONE extends Rexp  | 
   406 case object ONE extends Rexp                        // the empty string  | 
   283 case class CHAR(c: Char) extends Rexp  | 
   407 case class CHAR(c: Char) extends Rexp               // a character c  | 
   284 case class ALT(r1: Rexp, r2: Rexp) extends Rexp     // alternative  r1 + r2  | 
   408 case class ALT(r1: Rexp, r2: Rexp) extends Rexp     // alternative  r1 + r2  | 
   285 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp     // sequence     r1 r2    | 
   409 case class SEQ(r1: Rexp, r2: Rexp) extends Rexp     // sequence     r1 o r2    | 
   286 case class STAR(r: Rexp) extends Rexp               // star         r*  | 
   410 case class STAR(r: Rexp) extends Rexp               // star         r*  | 
   287   | 
   411   | 
   288   | 
   412   | 
   289 // (ab)*  | 
   413 // (ab)*  | 
   290 val r0 = STAR(SEQ(CHAR('a'), CHAR('b'))) | 
   414 val r0 = STAR(SEQ(CHAR('a'), CHAR('b'))) |