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