|     23 // remember |     24 // remember | 
|     24 val lst = List(None, Some(1), Some(2), None, Some(3)).flatten |     25 val lst = List(None, Some(1), Some(2), None, Some(3)).flatten | 
|     25  |     26  | 
|     26  |     27  | 
|     27 def my_flatten(xs: List[Option[Int]]): List[Int] = { |     28 def my_flatten(xs: List[Option[Int]]): List[Int] = { | 
|     28   ...? |     29   if (xs == Nil) Nil | 
|     29 } |     30   else if (xs.head == None) my_flatten(xs.tail) | 
|     30  |     31   else xs.head.get :: my_flatten(xs.tail) | 
|     31  |     32 } | 
|     32  |     33  | 
|     33  |     34  | 
|         |     35  | 
|         |     36 val lst = List(None, Some(1), Some(2), None, Some(3)) | 
|     34  |     37  | 
|     35 def my_flatten(lst: List[Option[Int]]): List[Int] = lst match { |     38 def my_flatten(lst: List[Option[Int]]): List[Int] = lst match { | 
|     36   case Nil => Nil |     39   case Nil => Nil | 
|     37   case None::xs => my_flatten(xs) |     40   case None::xs => my_flatten(xs) | 
|     38   case Some(n)::xs => n::my_flatten(xs) |     41   case Some(n)::xs => n::my_flatten(xs) | 
|     39 } |     42 } | 
|         |     43  | 
|         |     44 my_flatten(lst) | 
|         |     45  | 
|         |     46 Nil == List() | 
|     40  |     47  | 
|     41  |     48  | 
|     42 // another example including a catch-all pattern |     49 // another example including a catch-all pattern | 
|     43 def get_me_a_string(n: Int): String = n match { |     50 def get_me_a_string(n: Int): String = n match { | 
|     44   case 0 => "zero" |     51   case 0 => "zero" | 
|     45   case 1 => "one" |     52   case 1 => "one" | 
|     46   case 2 => "two" |     53   case 2 => "two" | 
|     47   case _ => "many" |     54   case _ => "many" | 
|     48 } |     55 } | 
|     49  |     56  | 
|     50 get_me_a_string(0) |     57 get_me_a_string(10) | 
|     51  |     58  | 
|     52 // you can also have cases combined |     59 // you can also have cases combined | 
|     53 def season(month: String) = month match { |     60 def season(month: String) = month match { | 
|     54   case "March" | "April" | "May" => "It's spring" |     61   case "March" | "April" | "May" => "It's spring" | 
|     55   case "June" | "July" | "August" => "It's summer" |     62   case "June" | "July" | "August" => "It's summer" | 
|     62 // What happens if no case matches? |     69 // What happens if no case matches? | 
|     63  |     70  | 
|     64 println(season("foobar")) |     71 println(season("foobar")) | 
|     65  |     72  | 
|     66  |     73  | 
|     67 // Collatz function on binary strings |     74 // we can also match more complicated pattern | 
|         |     75 // | 
|         |     76 // let's look at the Collatz function on binary strings | 
|     68  |     77  | 
|     69 // adding two binary strings in a very, very lazy manner |     78 // adding two binary strings in a very, very lazy manner | 
|     70  |     79  | 
|     71 def badd(s1: String, s2: String) : String =  |     80 def badd(s1: String, s2: String) : String =  | 
|     72   (BigInt(s1, 2) + BigInt(s2, 2)).toString(2) |     81   (BigInt(s1, 2) + BigInt(s2, 2)).toString(2) | 
|     73  |     82  | 
|     74  |     83  | 
|     75 // collatz function on binary numbers |     84 "111".dropRight(1) | 
|         |     85 "111".last | 
|     76  |     86  | 
|     77 def bcollatz(s: String) : Long = (s.dropRight(1), s.last) match { |     87 def bcollatz(s: String) : Long = (s.dropRight(1), s.last) match { | 
|     78   case ("", '1') => 1                                  // we reached 1 |     88   case ("", '1') => 1                               // we reached 1 | 
|     79   case (rest, '0') => 1 + bcollatz(rest)               // even number => divide by two |     89   case (rest, '0') => 1 + bcollatz(rest)             | 
|     80   case (rest, '1') => 1 + bcollatz(badd(s + '1', s))   // odd number => s + '1' is 2 * s + 1 |     90                                   // even number => divide by two | 
|     81                                                        //               add another s gives 3 * s + 1   |     91   case (rest, '1') => 1 + bcollatz(badd(s + '1', s)) | 
|         |     92                                   // odd number => s + '1' is 2 * s + 1 | 
|         |     93                                   // add another s gives 3 * s + 1   | 
|     82 }  |     94 }  | 
|     83  |     95  | 
|     84 bcollatz(9.toBinaryString) |     96 bcollatz(6.toBinaryString) | 
|     85 bcollatz(837799.toBinaryString) |     97 bcollatz(837799.toBinaryString) | 
|     86 bcollatz(100000000000000000L.toBinaryString) |     98 bcollatz(100000000000000000L.toBinaryString) | 
|     87 bcollatz(BigInt("1000000000000000000000000000000000000000000000000000000000000000000000000000").toString(2)) |     99 bcollatz(BigInt("1000000000000000000000000000000000000000000000000000000000000000000000000000").toString(2)) | 
|     88  |    100  | 
|     89  |    101  | 
|     91  |    103  | 
|     92 // User-defined Datatypes |    104 // User-defined Datatypes | 
|     93 //======================== |    105 //======================== | 
|     94  |    106  | 
|     95 abstract class Colour |    107 abstract class Colour | 
|     96 case class Red() extends Colour  |    108 case object Red extends Colour  | 
|     97 case class Green() extends Colour  |    109 case object Green extends Colour  | 
|     98 case class Blue() extends Colour |    110 case object Blue extends Colour | 
|     99  |    111  | 
|    100 def fav_colour(c: Colour) : Boolean = c match { |    112 def fav_colour(c: Colour) : Boolean = c match { | 
|    101   case Red()   => false |    113   case Red   => false | 
|    102   case Green() => true |    114   case Green => true | 
|    103   case Blue()  => false  |    115   case Blue  => false  | 
|    104 } |    116 } | 
|         |    117  | 
|         |    118 fav_colour(Green) | 
|    105  |    119  | 
|    106  |    120  | 
|    107 // actually colors can be written with "object", |    121 // actually colors can be written with "object", | 
|    108 // because they do not take any arguments |    122 // because they do not take any arguments | 
|    109  |    123  | 
|    110  |    124  | 
|    111  |    125 // ... a bit more useful: Roman Numerals | 
|    112 // Roman Numerals |    126  | 
|    113 abstract class RomanDigit  |    127 abstract class RomanDigit  | 
|    114 case object I extends RomanDigit  |    128 case object I extends RomanDigit  | 
|    115 case object V extends RomanDigit  |    129 case object V extends RomanDigit  | 
|    116 case object X extends RomanDigit  |    130 case object X extends RomanDigit  | 
|    117 case object L extends RomanDigit  |    131 case object L extends RomanDigit  | 
|    136   case V::r    => 5 + RomanNumeral2Int(r) |    150   case V::r    => 5 + RomanNumeral2Int(r) | 
|    137   case I::V::r => 4 + RomanNumeral2Int(r) |    151   case I::V::r => 4 + RomanNumeral2Int(r) | 
|    138   case I::r    => 1 + RomanNumeral2Int(r) |    152   case I::r    => 1 + RomanNumeral2Int(r) | 
|    139 } |    153 } | 
|    140  |    154  | 
|    141 RomanNumeral2Int(List(I,I,I,I))         // 4 (invalid roman number) |         | 
|    142 RomanNumeral2Int(List(I,V))             // 4 |    155 RomanNumeral2Int(List(I,V))             // 4 | 
|         |    156 RomanNumeral2Int(List(I,I,I,I))         // 4 (invalid Roman number) | 
|    143 RomanNumeral2Int(List(V,I))             // 6 |    157 RomanNumeral2Int(List(V,I))             // 6 | 
|    144 RomanNumeral2Int(List(I,X))             // 9 |    158 RomanNumeral2Int(List(I,X))             // 9 | 
|    145 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979 |    159 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979 | 
|    146 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017 |    160 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017 | 
|    147  |    161  | 
|    148  |    162  | 
|    149  |    163  | 
|    150 // another example |    164 // another example | 
|    151 //================= |    165 //================= | 
|    152  |    166  | 
|    153 // Once upon a time, in a complete fictional country there were persons... |    167 // Once upon a time, in a complete fictional country there were Persons... | 
|    154  |    168  | 
|    155 abstract class Person |    169 abstract class Person | 
|    156 case class King() extends Person |    170 case object King extends Person | 
|    157 case class Peer(deg: String, terr: String, succ: Int) extends Person |    171 case class Peer(deg: String, terr: String, succ: Int) extends Person | 
|    158 case class Knight(name: String) extends Person |    172 case class Knight(name: String) extends Person | 
|    159 case class Peasant(name: String) extends Person |    173 case class Peasant(name: String) extends Person | 
|    160  |    174 case object Clown extends Person | 
|    161  |    175  | 
|    162 def title(p: Person): String = p match { |    176 def title(p: Person): String = p match { | 
|    163   case King() => "His Majesty the King" |    177   case King => "His Majesty the King" | 
|    164   case Peer(deg, terr, _) => s"The ${deg} of ${terr}" |    178   case Peer(deg, terr, _) => s"The ${deg} of ${terr}" | 
|    165   case Knight(name) => s"Sir ${name}" |    179   case Knight(name) => s"Sir ${name}" | 
|    166   case Peasant(name) => name |    180   case Peasant(name) => name | 
|    167 } |    181   case Clown => "My name is Boris Johnson" | 
|         |    182  | 
|         |    183 } | 
|         |    184  | 
|         |    185 title(Clown) | 
|         |    186  | 
|    168  |    187  | 
|    169  |    188  | 
|    170 def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { |    189 def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { | 
|    171   case (King(), _) => true |    190   case (King, _) => true | 
|    172   case (Peer(_,_,_), Knight(_)) => true |    191   case (Peer(_,_,_), Knight(_)) => true | 
|    173   case (Peer(_,_,_), Peasant(_)) => true |    192   case (Peer(_,_,_), Peasant(_)) => true | 
|    174   case (Peer(_,_,_), Clown()) => true |    193   case (Peer(_,_,_), Clown) => true | 
|    175   case (Knight(_), Peasant(_)) => true |    194   case (Knight(_), Peasant(_)) => true | 
|    176   case (Knight(_), Clown()) => true |    195   case (Knight(_), Clown) => true | 
|    177   case (Clown(), Peasant(_)) => true |    196   case (Clown, Peasant(_)) => true | 
|    178   case _ => false |    197   case _ => false | 
|    179 } |    198 } | 
|    180  |    199  | 
|    181 val people = List(Knight("David"),  |    200 val people = List(Knight("David"),  | 
|    182                   Peer("Duke", "Norfolk", 84),  |    201                   Peer("Duke", "Norfolk", 84),  | 
|    183                   Peasant("Christian"),  |    202                   Peasant("Christian"),  | 
|    184                   King(),  |    203                   King,  | 
|    185                   Clown()) |    204                   Clown) | 
|    186  |    205  | 
|    187 println(people.sortWith(superior(_, _)).mkString(", ")) |    206 println(people.sortWith(superior(_, _)).mkString(", ")) | 
|    188  |    207  | 
|    189  |    208  | 
|    190  |    209  | 
|    273 //candidates(game0, (0,0)) |    293 //candidates(game0, (0,0)) | 
|    274  |    294  | 
|    275 def pretty(game: String): String =  |    295 def pretty(game: String): String =  | 
|    276   "\n" + (game sliding (MaxValue, MaxValue) mkString "\n") |    296   "\n" + (game sliding (MaxValue, MaxValue) mkString "\n") | 
|    277  |    297  | 
|         |    298 ///////////////////// | 
|    278 // not tail recursive  |    299 // not tail recursive  | 
|    279 def search(game: String): List[String] = { |    300 def search(game: String): List[String] = { | 
|    280   if (isDone(game)) List(game) |    301   if (isDone(game)) List(game) | 
|    281   else { |    302   else { | 
|    282     val cs = candidates(game, emptyPosition(game)) |    303     val cs = candidates(game, emptyPosition(game)) | 
|    283     cs.map(c => search(update(game, empty(game), c))).toList.flatten |    304     cs.map(c => search(update(game, empty(game), c))).toList.flatten | 
|    284   } |    305   } | 
|    285 } |    306 } | 
|    286  |    307  | 
|    287 // tail recursive version that searches  |    308 // tail recursive version that searches  | 
|    288 // for all solution |    309 // for all solutions | 
|         |    310  | 
|    289 def searchT(games: List[String], sols: List[String]): List[String] = games match { |    311 def searchT(games: List[String], sols: List[String]): List[String] = games match { | 
|    290   case Nil => sols |    312   case Nil => sols | 
|    291   case game::rest => { |    313   case game::rest => { | 
|    292     if (isDone(game)) searchT(rest, game::sols) |    314     if (isDone(game)) searchT(rest, game::sols) | 
|    293     else { |    315     else { | 
|    295       searchT(cs.map(c => update(game, empty(game), c)) ::: rest, sols) |    317       searchT(cs.map(c => update(game, empty(game), c)) ::: rest, sols) | 
|    296     } |    318     } | 
|    297   } |    319   } | 
|    298 } |    320 } | 
|    299  |    321  | 
|         |    322 searchT(List(game3), List()).map(pretty) | 
|         |    323  | 
|         |    324  | 
|    300 // tail recursive version that searches  |    325 // tail recursive version that searches  | 
|    301 // for a single solution |    326 // for a single solution | 
|         |    327  | 
|    302 def search1T(games: List[String]): Option[String] = games match { |    328 def search1T(games: List[String]): Option[String] = games match { | 
|    303   case Nil => None |    329   case Nil => None | 
|    304   case game::rest => { |    330   case game::rest => { | 
|    305     if (isDone(game)) Some(game) |    331     if (isDone(game)) Some(game) | 
|    306     else { |    332     else { | 
|    307       val cs = candidates(game, emptyPosition(game)) |    333       val cs = candidates(game, emptyPosition(game)) | 
|    308       search1T(cs.map(c => update(game, empty(game), c)) ::: rest) |    334       search1T(cs.map(c => update(game, empty(game), c)) ::: rest) | 
|    309     } |    335     } | 
|    310   } |    336   } | 
|    311 } |    337 } | 
|         |    338  | 
|         |    339 search1T(List(game3)).map(pretty) | 
|    312  |    340  | 
|    313 // game with multiple solutions |    341 // game with multiple solutions | 
|    314 val game3 = """.8...9743 |    342 val game3 = """.8...9743 | 
|    315               |.5...8.1. |    343               |.5...8.1. | 
|    316               |.1....... |    344               |.1....... | 
|    319               |...3....6 |    347               |...3....6 | 
|    320               |.......7. |    348               |.......7. | 
|    321               |.3.5...8. |    349               |.3.5...8. | 
|    322               |9724...5.""".stripMargin.replaceAll("\\n", "") |    350               |9724...5.""".stripMargin.replaceAll("\\n", "") | 
|    323  |    351  | 
|    324 searchT(List(game3), List()).map(pretty) |    352 searchT(List(game3), Nil).map(pretty) | 
|    325 search1T(List(game3)).map(pretty) |    353 search1T(List(game3)).map(pretty) | 
|    326  |    354  | 
|    327 // Moral: Whenever a recursive function is resource-critical |    355 // Moral: Whenever a recursive function is resource-critical | 
|    328 // (i.e. works with large recursion depths), then you need to |    356 // (i.e. works with large recursion depth), then you need to | 
|    329 // write it in tail-recursive fashion. |    357 // write it in tail-recursive fashion. | 
|    330 //  |    358 //  | 
|    331 // Unfortuantely, Scala because of current limitations in  |    359 // Unfortuantely, Scala because of current limitations in  | 
|    332 // the JVM is not as clever as other functional languages. It can  |    360 // the JVM is not as clever as other functional languages. It can  | 
|    333 // only optimise "self-tail calls". This excludes the cases of  |    361 // only optimise "self-tail calls". This excludes the cases of  | 
|    347 def length_string_list(lst: List[String]): Int = lst match { |    375 def length_string_list(lst: List[String]): Int = lst match { | 
|    348   case Nil => 0 |    376   case Nil => 0 | 
|    349   case x::xs => 1 + length_string_list(xs) |    377   case x::xs => 1 + length_string_list(xs) | 
|    350 } |    378 } | 
|    351  |    379  | 
|         |    380 def length_int_list(lst: List[Int]): Int = lst match { | 
|         |    381   case Nil => 0 | 
|         |    382   case x::xs => 1 + length_int_list(xs) | 
|         |    383 } | 
|         |    384  | 
|    352 length_string_list(List("1", "2", "3", "4")) |    385 length_string_list(List("1", "2", "3", "4")) | 
|    353  |    386 length_int_list(List(1, 2, 3, 4)) | 
|    354  |    387  | 
|         |    388 //----- | 
|    355 def length[A](lst: List[A]): Int = lst match { |    389 def length[A](lst: List[A]): Int = lst match { | 
|    356   case Nil => 0 |    390   case Nil => 0 | 
|    357   case x::xs => 1 + length(xs) |    391   case x::xs => 1 + length(xs) | 
|    358 } |    392 } | 
|    359  |    393 length(List("1", "2", "3", "4")) | 
|    360  |    394 length(List(King, Knight("foo"), Clown)) | 
|    361 def map_int_list(lst: List[Int], f: Int => Int): List[Int] = lst match { |    395 length(List(1, 2, 3, 4)) | 
|         |    396  | 
|         |    397 def map[A, B](lst: List[A], f: A => B): List[B] = lst match { | 
|    362   case Nil => Nil |    398   case Nil => Nil | 
|    363   case x::xs => f(x)::map_int_list(xs, f)  |    399   case x::xs => f(x)::map_int_list(xs, f)  | 
|    364 } |    400 } | 
|    365  |    401  | 
|    366 map_int_list(List(1, 2, 3, 4), square) |    402 map_int_list(List(1, 2, 3, 4), square) |