29 def unquote(s: String) = s.drop(1).dropRight(1)  | 
    39 def unquote(s: String) = s.drop(1).dropRight(1)  | 
    30   | 
    40   | 
    31 def get_all_URLs(page: String): Set[String] =   | 
    41 def get_all_URLs(page: String): Set[String] =   | 
    32   http_pattern.findAllIn(page).map(unquote).toSet  | 
    42   http_pattern.findAllIn(page).map(unquote).toSet  | 
    33   | 
    43   | 
    34 // naive version of crawl - searches until a given depth,  | 
    44 // a naive version of crawl - searches until a given depth,  | 
    35 // visits pages potentially more than once  | 
    45 // visits pages potentially more than once  | 
    36   | 
    46 def crawl(url: String, n: Int) : Unit = { | 
    37 def crawl(url: String, n: Int) : Set[String] = { | 
    47   if (n == 0) ()  | 
         | 
    48   else { | 
         | 
    49     println(s"  Visiting: $n $url")  | 
         | 
    50     for (u <- get_all_URLs(get_page(url))) crawl(u, n - 1)  | 
         | 
    51   }  | 
         | 
    52 }  | 
         | 
    53   | 
         | 
    54 // some starting URLs for the crawler  | 
         | 
    55 val startURL = """https://nms.kcl.ac.uk/christian.urban/"""  | 
         | 
    56   | 
         | 
    57 crawl(startURL, 2)  | 
         | 
    58   | 
         | 
    59   | 
         | 
    60   | 
         | 
    61 // a primitive email harvester  | 
         | 
    62 def emails(url: String, n: Int) : Set[String] = { | 
    38   if (n == 0) Set()  | 
    63   if (n == 0) Set()  | 
    39   else { | 
    64   else { | 
    40     println(s"  Visiting: $n $url")  | 
    65     println(s"  Visiting: $n $url")  | 
    41     val page = get_page(url)  | 
    66     val page = get_page(url)  | 
    42     val new_emails = email_pattern.findAllIn(page).toSet  | 
    67     val new_emails = email_pattern.findAllIn(page).toSet  | 
    43     new_emails ++   | 
    68     new_emails ++ (for (u <- get_all_URLs(page)) yield emails(u, n - 1)).flatten  | 
    44       (for (u <- get_all_URLs(page).par) yield crawl(u, n - 1)).flatten  | 
    69   }  | 
    45   }  | 
    70 }  | 
    46 }  | 
    71   | 
    47   | 
    72 emails(startURL, 2)  | 
    48 // some starting URLs for the crawler  | 
    73   | 
    49 val startURL = """https://nms.kcl.ac.uk/christian.urban/"""  | 
    74   | 
    50 crawl(startURL, 2)  | 
    75 // if we want to explore the internet "deeper", then we  | 
         | 
    76 // first have to parallelise the request of webpages:  | 
         | 
    77 //  | 
         | 
    78 // scala -cp scala-parallel-collections_2.13-0.2.0.jar   | 
         | 
    79 // import scala.collection.parallel.CollectionConverters._  | 
         | 
    80   | 
         | 
    81   | 
         | 
    82   | 
         | 
    83 // another well-known example  | 
         | 
    84 //============================  | 
         | 
    85   | 
         | 
    86 def move(from: Char, to: Char) =  | 
         | 
    87   println(s"Move disc from $from to $to!")  | 
         | 
    88   | 
         | 
    89 def hanoi(n: Int, from: Char, via: Char, to: Char) : Unit = { | 
         | 
    90   if (n == 0) ()  | 
         | 
    91   else { | 
         | 
    92     hanoi(n - 1, from, to, via)  | 
         | 
    93     move(from, to)  | 
         | 
    94     hanoi(n - 1, via, from, to)  | 
         | 
    95   }  | 
         | 
    96 }   | 
         | 
    97   | 
         | 
    98 hanoi(4, 'A', 'B', 'C')  | 
         | 
    99   | 
         | 
   100   | 
         | 
   101   | 
         | 
   102 // Jumping Towers  | 
         | 
   103 //================  | 
         | 
   104   | 
         | 
   105   | 
         | 
   106 // the first n prefixes of xs  | 
         | 
   107 // for 1 => include xs  | 
         | 
   108   | 
         | 
   109 def moves(xs: List[Int], n: Int) : List[List[Int]] = (xs, n) match { | 
         | 
   110   case (Nil, _) => Nil  | 
         | 
   111   case (xs, 0) => Nil  | 
         | 
   112   case (x::xs, n) => (x::xs) :: moves(xs, n - 1)  | 
         | 
   113 }  | 
         | 
   114   | 
         | 
   115   | 
         | 
   116 moves(List(5,1,0), 1)  | 
         | 
   117 moves(List(5,1,0), 2)  | 
         | 
   118 moves(List(5,1,0), 5)  | 
         | 
   119   | 
         | 
   120 // checks whether a jump tour exists at all  | 
         | 
   121   | 
         | 
   122 def search(xs: List[Int]) : Boolean = xs match { | 
         | 
   123   case Nil => true  | 
         | 
   124   case (x::xs) =>  | 
         | 
   125     if (xs.length < x) true else moves(xs, x).exists(search(_))  | 
         | 
   126 }  | 
         | 
   127   | 
         | 
   128   | 
         | 
   129 search(List(5,3,2,5,1,1))  | 
         | 
   130 search(List(3,5,1,0,0,0,1))  | 
         | 
   131 search(List(3,5,1,0,0,0,0,1))  | 
         | 
   132 search(List(3,5,1,0,0,0,1,1))  | 
         | 
   133 search(List(3,5,1))  | 
         | 
   134 search(List(5,1,1))  | 
         | 
   135 search(Nil)  | 
         | 
   136 search(List(1))  | 
         | 
   137 search(List(5,1,1))  | 
         | 
   138 search(List(3,5,1,0,0,0,0,0,0,0,0,1))  | 
         | 
   139   | 
         | 
   140 // generates *all* jump tours  | 
         | 
   141 //    if we are only interested in the shortes one, we could  | 
         | 
   142 //    shortcircut the calculation and only return List(x) in  | 
         | 
   143 //    case where xs.length < x, because no tour can be shorter  | 
         | 
   144 //    than 1  | 
         | 
   145 //   | 
         | 
   146   | 
         | 
   147 def jumps(xs: List[Int]) : List[List[Int]] = xs match { | 
         | 
   148   case Nil => Nil  | 
         | 
   149   case (x::xs) => { | 
         | 
   150     val children = moves(xs, x)  | 
         | 
   151     val results = children.map(cs => jumps(cs).map(x :: _)).flatten  | 
         | 
   152     if (xs.length < x) List(x)::results else results  | 
         | 
   153   }  | 
         | 
   154 }  | 
         | 
   155   | 
         | 
   156 jumps(List(5,3,2,5,1,1)).minBy(_.length)  | 
         | 
   157 jumps(List(3,5,1,2,1,2,1))  | 
         | 
   158 jumps(List(3,5,1,2,3,4,1))  | 
         | 
   159 jumps(List(3,5,1,0,0,0,1))  | 
         | 
   160 jumps(List(3,5,1))  | 
         | 
   161 jumps(List(5,1,1))  | 
         | 
   162 jumps(Nil)  | 
         | 
   163 jumps(List(1))  | 
         | 
   164 jumps(List(5,1,2))  | 
         | 
   165 moves(List(1,2), 5)  | 
         | 
   166 jumps(List(1,5,1,2))  | 
         | 
   167 jumps(List(3,5,1,0,0,0,0,0,0,0,0,1))  | 
         | 
   168   | 
         | 
   169 jumps(List(5,3,2,5,1,1)).minBy(_.length)  | 
         | 
   170 jumps(List(1,3,5,8,9,2,6,7,6,8,9)).minBy(_.length)  | 
         | 
   171 jumps(List(1,3,6,1,0,9)).minBy(_.length)  | 
         | 
   172 jumps(List(2,3,1,1,2,4,2,0,1,1)).minBy(_.length)  | 
         | 
   173   | 
         | 
   174   | 
         | 
   175   | 
         | 
   176   | 
    51   | 
   177   | 
    52   | 
   178   | 
    53 // User-defined Datatypes  | 
   179 // User-defined Datatypes  | 
    54 //========================  | 
   180 //========================  | 
    55   | 
   181   | 
   119 RomanNumeral2Int(List(I,X))             // 9  | 
   245 RomanNumeral2Int(List(I,X))             // 9  | 
   120 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979  | 
   246 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979  | 
   121 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017  | 
   247 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017  | 
   122   | 
   248   | 
   123   | 
   249   | 
   124 // another example  | 
         | 
   125 //=================  | 
         | 
   126   | 
         | 
   127 // Once upon a time, in a complete fictional   | 
         | 
   128 // country there were Persons...  | 
         | 
   129   | 
         | 
   130   | 
         | 
   131 abstract class Person  | 
         | 
   132 case object King extends Person  | 
         | 
   133 case class Peer(deg: String, terr: String, succ: Int) extends Person  | 
         | 
   134 case class Knight(name: String) extends Person  | 
         | 
   135 case class Peasant(name: String) extends Person  | 
         | 
   136   | 
         | 
   137   | 
         | 
   138 def title(p: Person): String = p match { | 
         | 
   139   case King => "His Majesty the King"  | 
         | 
   140   case Peer(deg, terr, _) => s"The ${deg} of ${terr}" | 
         | 
   141   case Knight(name) => s"Sir ${name}" | 
         | 
   142   case Peasant(name) => name  | 
         | 
   143 }  | 
         | 
   144   | 
         | 
   145 def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { | 
         | 
   146   case (King, _) => true  | 
         | 
   147   case (Peer(_,_,_), Knight(_)) => true  | 
         | 
   148   case (Peer(_,_,_), Peasant(_)) => true  | 
         | 
   149   case (Peer(_,_,_), Clown) => true  | 
         | 
   150   case (Knight(_), Peasant(_)) => true  | 
         | 
   151   case (Knight(_), Clown) => true  | 
         | 
   152   case (Clown, Peasant(_)) => true  | 
         | 
   153   case _ => false  | 
         | 
   154 }  | 
         | 
   155   | 
         | 
   156 val people = List(Knight("David"),  | 
         | 
   157                   Peer("Duke", "Norfolk", 84),  | 
         | 
   158                   Peasant("Christian"),  | 
         | 
   159                   King,   | 
         | 
   160                   Clown)  | 
         | 
   161   | 
         | 
   162 println(people.sortWith(superior).mkString("\n")) | 
         | 
   163   | 
         | 
   164   | 
         | 
   165 // String interpolations as patterns  | 
   250 // String interpolations as patterns  | 
   166   | 
   251   | 
   167 val date = "2000-01-01"  | 
   252 val date = "2019-11-26"  | 
   168 val s"$year-$month-$day" = date  | 
   253 val s"$year-$month-$day" = date  | 
   169   | 
   254   | 
   170 def parse_date(date: String) = date match { | 
   255 def parse_date(date: String) : Option[(Int, Int, Int)]= date match { | 
   171   case s"$year-$month-$day" => Some((year.toInt, month.toInt, day.toInt))  | 
   256   case s"$year-$month-$day" => Some((day.toInt, month.toInt, year.toInt))  | 
   172   case s"$day/$month/$year" => Some((year.toInt, month.toInt, day.toInt))  | 
   257   case s"$day/$month/$year" => Some((day.toInt, month.toInt, year.toInt))  | 
         | 
   258   case s"$day.$month.$year" => Some((day.toInt, month.toInt, year.toInt))  | 
   173   case _ => None  | 
   259   case _ => None  | 
   174 }   | 
   260 }   | 
   175   | 
   261   | 
   176   | 
   262 parse_date("2019-11-26") | 
         | 
   263 parse_date("26/11/2019") | 
         | 
   264 parse_date("26.11.2019") | 
   177   | 
   265   | 
   178   | 
   266   | 
   179 // User-defined Datatypes and Pattern Matching  | 
   267 // User-defined Datatypes and Pattern Matching  | 
   180 //=============================================  | 
   268 //=============================================  | 
   181   | 
   269   | 
   182   | 
   270 // trees  | 
   183   | 
   271   | 
   184 abstract class Exp  | 
   272 abstract class Exp  | 
   185 case class N(n: Int) extends Exp                  // for numbers  | 
   273 case class N(n: Int) extends Exp                  // for numbers  | 
   186 case class Plus(e1: Exp, e2: Exp) extends Exp  | 
   274 case class Plus(e1: Exp, e2: Exp) extends Exp  | 
   187 case class Times(e1: Exp, e2: Exp) extends Exp  | 
   275 case class Times(e1: Exp, e2: Exp) extends Exp  | 
   188   | 
   276   | 
   189 def string(e: Exp) : String = e match { | 
   277 def string(e: Exp) : String = e match { | 
   190   case N(n) => n.toString  | 
   278   case N(n) => s"$n"  | 
   191   case Plus(e1, e2) => "(" + string(e1) + " + " + string(e2) + ")"  | 
   279   case Plus(e1, e2) => s"(${string(e1)} + ${string(e2)})"  | 
   192   case Times(e1, e2) => "(" + string(e1) + " * " + string(e2) + ")"  | 
   280   case Times(e1, e2) => s"(${string(e1)} * ${string(e2)})" | 
   193 }  | 
   281 }  | 
   194   | 
   282   | 
   195 val e = Plus(N(9), Times(N(3), N(4)))  | 
   283 val e = Plus(N(9), Times(N(3), N(4)))  | 
   196 println(string(e))  | 
   284 println(string(e))  | 
   197   | 
   285   | 
   198 def eval(e: Exp) : Int = e match { | 
   286 def eval(e: Exp) : Int = e match { | 
   199   case N(n) => n  | 
   287   case N(n) => n  | 
   200   case Plus(e1, e2) => eval(e1) + eval(e2)   | 
   288   case Plus(e1, e2) => eval(e1) + eval(e2)   | 
   201   case Times(e1, e2) => eval(e1) * eval(e2)   | 
   289   case Times(e1, e2) => eval(e1) * eval(e2)   | 
   202 }  | 
   290 }  | 
         | 
   291   | 
         | 
   292 println(eval(e))  | 
   203   | 
   293   | 
   204 def simp(e: Exp) : Exp = e match { | 
   294 def simp(e: Exp) : Exp = e match { | 
   205   case N(n) => N(n)  | 
   295   case N(n) => N(n)  | 
   206   case Plus(e1, e2) => (simp(e1), simp(e2)) match { | 
   296   case Plus(e1, e2) => (simp(e1), simp(e2)) match { | 
   207     case (N(0), e2s) => e2s  | 
   297     case (N(0), e2s) => e2s  | 
   251   case  "*" => TI  | 
   341   case  "*" => TI  | 
   252   case  _ => T(s.toInt)   | 
   342   case  _ => T(s.toInt)   | 
   253 }  | 
   343 }  | 
   254   | 
   344   | 
   255 comp("1 2 + 4 * 5 + 3 +".split(" ").toList.map(proc), Nil) | 
   345 comp("1 2 + 4 * 5 + 3 +".split(" ").toList.map(proc), Nil) | 
   256   | 
         | 
   257   | 
         | 
   258   | 
         | 
   259   | 
         | 
   260 def string(e: Exp) : String = e match { | 
         | 
   261   case N(n) => n.toString  | 
         | 
   262   case Plus(e1, e2) => "(" + string(e1) + " + " + string(e2) + ")" | 
         | 
   263   case Times(e1, e2) => "(" + string(e1) + " * " + string(e2) + ")" | 
         | 
   264 }  | 
         | 
   265   | 
         | 
   266 val e = Plus(N(9), Times(N(3), N(4)))  | 
         | 
   267   | 
         | 
   268 println(string(e))  | 
         | 
   269   | 
         | 
   270 def eval(e: Exp) : Int = e match { | 
         | 
   271   case N(n) => n  | 
         | 
   272   case Plus(e1, e2) => eval(e1) + eval(e2)  | 
         | 
   273   case Times(e1, e2) => eval(e1) * eval(e2)  | 
         | 
   274 }  | 
         | 
   275   | 
         | 
   276 eval(e)  | 
         | 
   277   | 
         | 
   278 def simp(e: Exp) : Exp = e match { | 
         | 
   279   case N(n) => N(n)  | 
         | 
   280   case Plus(e1, e2) => (simp(e1), simp(e2)) match { | 
         | 
   281     case (N(0), e2s) => e2s  | 
         | 
   282     case (e1s, N(0)) => e1s  | 
         | 
   283     case (e1s, e2s) => Plus(e1s, e2s)   | 
         | 
   284   }  | 
         | 
   285   case Times(e1, e2) => (simp(e1), simp(e2)) match { | 
         | 
   286     case (N(0), e2s) => N(0)  | 
         | 
   287     case (e1s, N(0)) => N(0)  | 
         | 
   288     case (N(1), e2s) => e2s  | 
         | 
   289     case (e1s, N(1)) => e1s  | 
         | 
   290     case (e1s, e2s) => Times(e1s, e2s)   | 
         | 
   291   }  | 
         | 
   292 }  | 
         | 
   293   | 
         | 
   294   | 
         | 
   295 val e2 = Times(Plus(N(0), N(1)), Plus(N(0), N(9)))  | 
         | 
   296 println(string(e2))  | 
         | 
   297 println(string(simp(e2)))  | 
         | 
   298   | 
         | 
   299 // Token and Reverse Polish Notation  | 
         | 
   300 abstract class Token  | 
         | 
   301 case class T(n: Int) extends Token  | 
         | 
   302 case object PL extends Token  | 
         | 
   303 case object TI extends Token  | 
         | 
   304   | 
         | 
   305 def rp(e: Exp) : List[Token] = e match { | 
         | 
   306   case N(n) => List(T(n))  | 
         | 
   307   case Plus(e1, e2) => rp(e1) ::: rp(e2) ::: List(PL)  | 
         | 
   308   case Times(e1, e2) => rp(e1) ::: rp(e2) ::: List(TI)  | 
         | 
   309 }  | 
         | 
   310   | 
         | 
   311 def comp(ts: List[Token], stk: List[Int]) : Int = (ts, stk) match { | 
         | 
   312   case (Nil, st) => st.head  | 
         | 
   313   case (T(n)::rest, st) => comp(rest, n::st)  | 
         | 
   314   case (PL::rest, n1::n2::st) => comp(rest, n1 + n2::st)  | 
         | 
   315   case (TI::rest, n1::n2::st) => comp(rest, n1 * n2::st)  | 
         | 
   316 }  | 
         | 
   317   | 
         | 
   318 def exp(ts: List[Token], st: List[Exp]) : Exp = (ts, st) match { | 
         | 
   319   case (Nil, st) => st.head  | 
         | 
   320   case (T(n)::rest, st) => exp(rest, N(n)::st)  | 
         | 
   321   case (PL::rest, n1::n2::st) => exp(rest, Plus(n2, n1)::st)  | 
         | 
   322   case (TI::rest, n1::n2::st) => exp(rest, Times(n2, n1)::st)  | 
         | 
   323 }  | 
         | 
   324   | 
         | 
   325 exp(toks(e2), Nil)  | 
         | 
   326   | 
         | 
   327 def proc(s: String) = s match { | 
         | 
   328   case "+" => PL  | 
         | 
   329   case "*" => TI  | 
         | 
   330   case n => T(n.toInt)  | 
         | 
   331 }  | 
         | 
   332   | 
         | 
   333   | 
         | 
   334 string(exp("1 2 + 4 * 5 + 3 +".split(" ").toList.map(proc), Nil)) | 
         | 
   335   | 
         | 
   336   | 
         | 
   337   | 
         | 
   338 // Tail recursion  | 
         | 
   339 //================  | 
         | 
   340   | 
         | 
   341   | 
         | 
   342 def fact(n: Long): Long =   | 
         | 
   343   if (n == 0) 1 else n * fact(n - 1)  | 
         | 
   344   | 
         | 
   345 def factB(n: BigInt): BigInt =   | 
         | 
   346   if (n == 0) 1 else n * factB(n - 1)  | 
         | 
   347   | 
         | 
   348 factB(100000)  | 
         | 
   349   | 
         | 
   350 fact(10)              //ok  | 
         | 
   351 fact(10000)           // produces a stackoverflow  | 
         | 
   352   | 
         | 
   353 def factT(n: BigInt, acc: BigInt): BigInt =  | 
         | 
   354   if (n == 0) acc else factT(n - 1, n * acc)  | 
         | 
   355   | 
         | 
   356 factT(10, 1)  | 
         | 
   357 println(factT(100000, 1))  | 
         | 
   358   | 
         | 
   359 // there is a flag for ensuring a function is tail recursive  | 
         | 
   360 import scala.annotation.tailrec  | 
         | 
   361   | 
         | 
   362 @tailrec  | 
         | 
   363 def factT(n: BigInt, acc: BigInt): BigInt =  | 
         | 
   364   if (n == 0) acc else factT(n - 1, n * acc)  | 
         | 
   365   | 
         | 
   366   | 
         | 
   367   | 
         | 
   368 // for tail-recursive functions the Scala compiler  | 
         | 
   369 // generates loop-like code, which does not need  | 
         | 
   370 // to allocate stack-space in each recursive  | 
         | 
   371 // call; Scala can do this only for tail-recursive  | 
         | 
   372 // functions  | 
         | 
   373   | 
         | 
   374   | 
         | 
   375   | 
         | 
   376 // Jumping Towers  | 
         | 
   377 //================  | 
         | 
   378   | 
         | 
   379   | 
         | 
   380 // the first n prefixes of xs  | 
         | 
   381 // for 1 => include xs  | 
         | 
   382   | 
         | 
   383   | 
         | 
   384   | 
         | 
   385 def moves(xs: List[Int], n: Int) : List[List[Int]] = (xs, n) match { | 
         | 
   386   case (Nil, _) => Nil  | 
         | 
   387   case (xs, 0) => Nil  | 
         | 
   388   case (x::xs, n) => (x::xs) :: moves(xs, n - 1)  | 
         | 
   389 }  | 
         | 
   390   | 
         | 
   391   | 
         | 
   392 moves(List(5,1,0), 1)  | 
         | 
   393 moves(List(5,1,0), 2)  | 
         | 
   394 moves(List(5,1,0), 5)  | 
         | 
   395   | 
         | 
   396 // checks whether a jump tour exists at all  | 
         | 
   397   | 
         | 
   398 def search(xs: List[Int]) : Boolean = xs match { | 
         | 
   399   case Nil => true  | 
         | 
   400   case (x::xs) =>  | 
         | 
   401     if (xs.length < x) true else moves(xs, x).exists(search(_))  | 
         | 
   402 }  | 
         | 
   403   | 
         | 
   404   | 
         | 
   405 search(List(5,3,2,5,1,1))  | 
         | 
   406 search(List(3,5,1,0,0,0,1))  | 
         | 
   407 search(List(3,5,1,0,0,0,0,1))  | 
         | 
   408 search(List(3,5,1,0,0,0,1,1))  | 
         | 
   409 search(List(3,5,1))  | 
         | 
   410 search(List(5,1,1))  | 
         | 
   411 search(Nil)  | 
         | 
   412 search(List(1))  | 
         | 
   413 search(List(5,1,1))  | 
         | 
   414 search(List(3,5,1,0,0,0,0,0,0,0,0,1))  | 
         | 
   415   | 
         | 
   416 // generates *all* jump tours  | 
         | 
   417 //    if we are only interested in the shortes one, we could  | 
         | 
   418 //    shortcircut the calculation and only return List(x) in  | 
         | 
   419 //    case where xs.length < x, because no tour can be shorter  | 
         | 
   420 //    than 1  | 
         | 
   421 //   | 
         | 
   422   | 
         | 
   423 def jumps(xs: List[Int]) : List[List[Int]] = xs match { | 
         | 
   424   case Nil => Nil  | 
         | 
   425   case (x::xs) => { | 
         | 
   426     val children = moves(xs, x)  | 
         | 
   427     val results = children.map((cs) => jumps(cs).map(x :: _)).flatten  | 
         | 
   428     if (xs.length < x) List(x) :: results else results  | 
         | 
   429   }  | 
         | 
   430 }  | 
         | 
   431   | 
         | 
   432 println(jumps(List(5,3,2,5,1,1)).minBy(_.length))  | 
         | 
   433 jumps(List(3,5,1,2,1,2,1))  | 
         | 
   434 jumps(List(3,5,1,2,3,4,1))  | 
         | 
   435 jumps(List(3,5,1,0,0,0,1))  | 
         | 
   436 jumps(List(3,5,1))  | 
         | 
   437 jumps(List(5,1,1))  | 
         | 
   438 jumps(Nil)  | 
         | 
   439 jumps(List(1))  | 
         | 
   440 jumps(List(5,1,2))  | 
         | 
   441 moves(List(1,2), 5)  | 
         | 
   442 jumps(List(1,5,1,2))  | 
         | 
   443 jumps(List(3,5,1,0,0,0,0,0,0,0,0,1))  | 
         | 
   444   | 
         | 
   445 jumps(List(5,3,2,5,1,1)).minBy(_.length)  | 
         | 
   446 jumps(List(1,3,5,8,9,2,6,7,6,8,9)).minBy(_.length)  | 
         | 
   447 jumps(List(1,3,6,1,0,9)).minBy(_.length)  | 
         | 
   448 jumps(List(2,3,1,1,2,4,2,0,1,1)).minBy(_.length)  | 
         | 
   449   | 
         | 
   450   | 
         | 
   451   | 
         | 
   452 // Tail Recursion  | 
         | 
   453 //================  | 
         | 
   454   | 
         | 
   455   | 
         | 
   456 def fact(n: Long): Long =   | 
         | 
   457   if (n == 0) 1 else n * fact(n - 1)  | 
         | 
   458   | 
         | 
   459 fact(10)              //ok  | 
         | 
   460 fact(10000)           // produces a stackoverflow  | 
         | 
   461   | 
         | 
   462 def factT(n: BigInt, acc: BigInt): BigInt =  | 
         | 
   463   if (n == 0) acc else factT(n - 1, n * acc)  | 
         | 
   464   | 
         | 
   465 factT(10, 1)  | 
         | 
   466 factT(100000, 1)  | 
         | 
   467   | 
         | 
   468 // there is a flag for ensuring a function is tail recursive  | 
         | 
   469 import scala.annotation.tailrec  | 
         | 
   470   | 
         | 
   471 @tailrec  | 
         | 
   472 def factT(n: BigInt, acc: BigInt): BigInt =  | 
         | 
   473   if (n == 0) acc else factT(n - 1, n * acc)  | 
         | 
   474   | 
         | 
   475   | 
         | 
   476   | 
         | 
   477 // for tail-recursive functions the Scala compiler  | 
         | 
   478 // generates loop-like code, which does not need  | 
         | 
   479 // to allocate stack-space in each recursive  | 
         | 
   480 // call; Scala can do this only for tail-recursive  | 
         | 
   481 // functions  | 
         | 
   482   | 
         | 
   483   | 
   346   | 
   484   | 
   347   | 
   485   | 
   348   | 
   486   | 
   349   | 
   487 // Sudoku   | 
   350 // Sudoku   |