|     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'))) |