1 // Scala Lecture 2  | 
     1 // Scala Lecture 2  | 
     2 //=================  | 
     2 //=================  | 
     3   | 
     3   | 
         | 
     4 // UNFINISHED BUSINESS from Lecture 1  | 
         | 
     5 //====================================  | 
         | 
     6   | 
         | 
     7   | 
         | 
     8 // for measuring time  | 
         | 
     9 def time_needed[T](n: Int, code: => T) = { | 
         | 
    10   val start = System.nanoTime()  | 
         | 
    11   for (i <- (0 to n)) code  | 
         | 
    12   val end = System.nanoTime()  | 
         | 
    13   (end - start) / 1.0e9  | 
         | 
    14 }  | 
         | 
    15   | 
         | 
    16   | 
         | 
    17 val list = (1 to 1000000).toList  | 
         | 
    18 time_needed(10, for (n <- list) yield n + 42)  | 
         | 
    19 time_needed(10, for (n <- list.par) yield n + 42)  | 
         | 
    20   | 
         | 
    21   | 
         | 
    22 // Just for "Fun": Mutable vs Immutable  | 
         | 
    23 //=======================================  | 
         | 
    24 //  | 
         | 
    25 // - no vars, no ++i, no +=  | 
         | 
    26 // - no mutable data-structures (no Arrays, no ListBuffers)  | 
         | 
    27   | 
         | 
    28   | 
         | 
    29 // Q: Count how many elements are in the intersections of two sets?  | 
         | 
    30   | 
         | 
    31 def count_intersection(A: Set[Int], B: Set[Int]) : Int = { | 
         | 
    32   var count = 0  | 
         | 
    33   for (x <- A; if B contains x) count += 1   | 
         | 
    34   count  | 
         | 
    35 }  | 
         | 
    36   | 
         | 
    37 val A = (1 to 1000).toSet  | 
         | 
    38 val B = (1 to 1000 by 4).toSet  | 
         | 
    39   | 
         | 
    40 count_intersection(A, B)  | 
         | 
    41   | 
         | 
    42 // but do not try to add .par to the for-loop above  | 
         | 
    43   | 
         | 
    44   | 
         | 
    45 //propper parallel version  | 
         | 
    46 def count_intersection2(A: Set[Int], B: Set[Int]) : Int =   | 
         | 
    47   A.par.count(x => B contains x)  | 
         | 
    48   | 
         | 
    49 count_intersection2(A, B)  | 
         | 
    50   | 
         | 
    51   | 
         | 
    52 val A = (1 to 1000000).toSet  | 
         | 
    53 val B = (1 to 1000000 by 4).toSet  | 
         | 
    54   | 
         | 
    55 time_needed(100, count_intersection(A, B))  | 
         | 
    56 time_needed(100, count_intersection2(A, B))  | 
         | 
    57   | 
         | 
    58   | 
         | 
    59   | 
         | 
    60 // For-Comprehensions Again  | 
         | 
    61 //==========================  | 
         | 
    62   | 
         | 
    63 // the first produces a result, while the second does not  | 
         | 
    64 for (n <- List(1, 2, 3, 4, 5)) yield n * n  | 
         | 
    65   | 
         | 
    66   | 
         | 
    67 for (n <- List(1, 2, 3, 4, 5)) println(n)  | 
         | 
    68   | 
         | 
    69   | 
         | 
    70   | 
         | 
    71 // Higher-Order Functions  | 
         | 
    72 //========================  | 
         | 
    73   | 
         | 
    74 // functions can take functions as arguments  | 
         | 
    75   | 
         | 
    76 def even(x: Int) : Boolean = x % 2 == 0  | 
         | 
    77 def odd(x: Int) : Boolean = x % 2 == 1  | 
         | 
    78   | 
         | 
    79 val lst = (1 to 10).toList  | 
         | 
    80   | 
         | 
    81 lst.filter(x => even(x))  | 
         | 
    82 lst.filter(even(_))  | 
         | 
    83 lst.filter(even)  | 
         | 
    84   | 
         | 
    85 lst.count(even)  | 
         | 
    86   | 
         | 
    87 lst.find(_ > 8)  | 
         | 
    88   | 
         | 
    89   | 
         | 
    90 val ps = List((3, 0), (3, 2), (4, 2), (2, 0), (1, 1), (1, 0))  | 
         | 
    91   | 
         | 
    92 ps.sortBy(_._1)  | 
         | 
    93 ps.sortBy(_._2)  | 
         | 
    94   | 
         | 
    95 ps.maxBy(_._1)  | 
         | 
    96 ps.maxBy(_._2)  | 
         | 
    97   | 
         | 
    98   | 
         | 
    99   | 
         | 
   100 // maps  | 
         | 
   101 //=====  | 
         | 
   102   | 
         | 
   103 def square(x: Int): Int = x * x  | 
         | 
   104   | 
         | 
   105 val lst = (1 to 10).toList  | 
         | 
   106   | 
         | 
   107 lst.map(square)  | 
         | 
   108   | 
         | 
   109 // this is actually what for is defined at in Scala  | 
         | 
   110   | 
         | 
   111 lst.map(n => square(n))  | 
         | 
   112 for (n <- lst) yield square(n)  | 
         | 
   113   | 
         | 
   114 // this can be iterated  | 
         | 
   115   | 
         | 
   116 lst.map(square).filter(_ > 4)  | 
         | 
   117   | 
         | 
   118 lst.map(square).filter(_ > 4).map(square)  | 
         | 
   119   | 
         | 
   120   | 
         | 
   121 // lets define our own functions  | 
         | 
   122 // type of functions, for example f: Int => Int  | 
         | 
   123   | 
         | 
   124 def my_map_int(lst: List[Int], f: Int => Int) : List[Int] = { | 
         | 
   125   if (lst == Nil) Nil  | 
         | 
   126   else f(lst.head) :: my_map_int(lst.tail, f)  | 
         | 
   127 }  | 
         | 
   128   | 
         | 
   129 my_map_int(lst, square)  | 
         | 
   130   | 
         | 
   131   | 
         | 
   132 // same function using pattern matching: a kind  | 
         | 
   133 // of switch statement on steroids (see more later on)  | 
         | 
   134   | 
         | 
   135 def my_map_int(lst: List[Int], f: Int => Int) : List[Int] = lst match { | 
         | 
   136   case Nil => Nil  | 
         | 
   137   case x::xs => f(x)::my_map_int(xs, f)  | 
         | 
   138 }  | 
         | 
   139   | 
         | 
   140   | 
         | 
   141 // other function types  | 
         | 
   142 //  | 
         | 
   143 // f1: (Int, Int) => Int  | 
         | 
   144 // f2: List[String] => Option[Int]  | 
         | 
   145 // ...   | 
         | 
   146   | 
         | 
   147   | 
         | 
   148 def sumOf(f: Int => Int, lst: List[Int]): Int = lst match { | 
         | 
   149   case Nil => 0  | 
         | 
   150   case x::xs => f(x) + sumOf(f, xs)  | 
         | 
   151 }  | 
         | 
   152   | 
         | 
   153 def sum_squares(lst: List[Int]) = sumOf(square, lst)  | 
         | 
   154 def sum_cubes(lst: List[Int])   = sumOf(x => x * x * x, lst)  | 
         | 
   155   | 
         | 
   156 sum_squares(lst)  | 
         | 
   157 sum_cubes(lst)  | 
         | 
   158   | 
         | 
   159 // lets try it factorial  | 
         | 
   160 def fact(n: Int) : Int = ...  | 
         | 
   161   | 
         | 
   162 def sum_fact(lst: List[Int]) = sumOf(fact, lst)  | 
         | 
   163 sum_fact(lst)  | 
         | 
   164   | 
         | 
   165   | 
         | 
   166   | 
         | 
   167   | 
         | 
   168   | 
         | 
   169 // Map type  | 
         | 
   170 //==========  | 
         | 
   171   | 
         | 
   172 // Note the difference between map and Map  | 
         | 
   173   | 
         | 
   174 def factors(n: Int) : List[Int] =  | 
         | 
   175   ((1 until n).filter { divisor => | 
         | 
   176       n % divisor == 0  | 
         | 
   177     }).toList  | 
         | 
   178   | 
         | 
   179   | 
         | 
   180 var ls = (1 to 10).toList  | 
         | 
   181   | 
         | 
   182 val facs = ls.map(n => (n, factors(n)))  | 
         | 
   183   | 
         | 
   184 facs.find(_._1 == 4)  | 
         | 
   185   | 
         | 
   186 // works for lists of pairs  | 
         | 
   187 facs.toMap  | 
         | 
   188   | 
         | 
   189   | 
         | 
   190 facs.toMap.get(4)  | 
         | 
   191 facs.toMap.getOrElse(4, Nil)  | 
         | 
   192   | 
         | 
   193 val facsMap = facs.toMap  | 
         | 
   194   | 
         | 
   195 val facsMap0 = facsMap + (0 -> List(1,2,3,4,5))  | 
         | 
   196 facsMap0.get(0)  | 
         | 
   197   | 
         | 
   198 val facsMap4 = facsMap + (1 -> List(1,2,3,4,5))  | 
         | 
   199 facsMap.get(1)  | 
         | 
   200 facsMap4.get(1)  | 
         | 
   201   | 
         | 
   202 val ls = List("one", "two", "three", "four", "five") | 
         | 
   203 ls.groupBy(_.length)  | 
         | 
   204   | 
         | 
   205 ls.groupBy(_.length).get(3)  | 
         | 
   206   | 
         | 
   207   | 
     4   | 
   208   | 
     5 // Option type  | 
   209 // Option type  | 
     6 //=============  | 
   210 //=============  | 
     7   | 
   211   | 
     8 //in Java if something unusually happens, you return null;  | 
   212 //in Java if something unusually happens, you return null;  | 
         | 
   213 //  | 
     9 //in Scala you use Option  | 
   214 //in Scala you use Option  | 
    10 //   - if the value is present, you use Some(value)  | 
   215 //   - if the value is present, you use Some(value)  | 
    11 //   - if no value is present, you use None  | 
   216 //   - if no value is present, you use None  | 
    12   | 
   217   | 
    13   | 
   218   | 
    14 List(7,2,3,4,5,6).find(_ < 4)  | 
   219 List(7,2,3,4,5,6).find(_ < 4)  | 
    15 List(5,6,7,8,9).find(_ < 4)  | 
   220 List(5,6,7,8,9).find(_ < 4)  | 
    16   | 
   221   | 
    17   | 
   222 // operations on options  | 
    18 // Values in types  | 
         | 
    19 //  | 
         | 
    20 // Boolean:   | 
         | 
    21 // Int:   | 
         | 
    22 // String:   | 
         | 
    23 //  | 
         | 
    24 // Option[String]:  | 
         | 
    25 //     | 
         | 
    26   | 
         | 
    27   | 
   223   | 
    28 val lst = List(None, Some(1), Some(2), None, Some(3))  | 
   224 val lst = List(None, Some(1), Some(2), None, Some(3))  | 
    29   | 
   225   | 
    30 lst.flatten  | 
   226 lst.flatten  | 
    31   | 
   227   | 
   222   | 
   372   | 
   223   | 
   373   | 
   224 // User-defined Datatypes  | 
   374 // User-defined Datatypes  | 
   225 //========================  | 
   375 //========================  | 
   226   | 
   376   | 
   227 abstract class Tree  | 
   377   | 
   228 case class Node(elem: Int, left: Tree, right: Tree) extends Tree  | 
   378 abstract class Colour  | 
   229 case class Leaf() extends Tree  | 
   379 case object Red extends Colour   | 
   230   | 
   380 case object Green extends Colour   | 
   231   | 
   381 case object Blue extends Colour  | 
   232 def insert(tr: Tree, n: Int): Tree = tr match { | 
   382   | 
   233   case Leaf() => Node(n, Leaf(), Leaf())  | 
   383 def fav_colour(c: Colour) : Boolean = c match { | 
   234   case Node(m, left, right) =>   | 
   384   case Red   => false  | 
   235     if (n == m) Node(m, left, right)   | 
   385   case Green => true  | 
   236     else if (n < m) Node(m, insert(left, n), right)  | 
   386   case Blue  => false   | 
   237     else Node(m, left, insert(right, n))  | 
   387 }  | 
   238 }  | 
   388   | 
   239   | 
   389 fav_colour(Green)  | 
   240   | 
   390   | 
   241 val t1 = Node(4, Node(2, Leaf(), Leaf()), Node(7, Leaf(), Leaf()))  | 
   391   | 
   242 insert(t1, 3)  | 
   392 // ... a bit more useful: Roman Numerals  | 
   243   | 
   393   | 
   244 def depth(tr: Tree): Int = tr match { | 
   394 abstract class RomanDigit   | 
   245   case Leaf() => 0  | 
   395 case object I extends RomanDigit   | 
   246   case Node(_, left, right) => 1 + List(depth(left), depth(right)).max  | 
   396 case object V extends RomanDigit   | 
   247 }  | 
   397 case object X extends RomanDigit   | 
   248   | 
   398 case object L extends RomanDigit   | 
   249   | 
   399 case object C extends RomanDigit   | 
   250 def balance(tr: Tree): Int = tr match { | 
   400 case object D extends RomanDigit   | 
   251   case Leaf() => 0  | 
   401 case object M extends RomanDigit   | 
   252   case Node(_, left, right) => depth(left) - depth(right)  | 
   402   | 
   253 }  | 
   403 type RomanNumeral = List[RomanDigit]   | 
   254   | 
   404   | 
   255 balance(insert(t1, 3))  | 
   405 def RomanNumeral2Int(rs: RomanNumeral): Int = rs match {  | 
         | 
   406   case Nil => 0  | 
         | 
   407   case M::r    => 1000 + RomanNumeral2Int(r)    | 
         | 
   408   case C::M::r => 900 + RomanNumeral2Int(r)  | 
         | 
   409   case D::r    => 500 + RomanNumeral2Int(r)  | 
         | 
   410   case C::D::r => 400 + RomanNumeral2Int(r)  | 
         | 
   411   case C::r    => 100 + RomanNumeral2Int(r)  | 
         | 
   412   case X::C::r => 90 + RomanNumeral2Int(r)  | 
         | 
   413   case L::r    => 50 + RomanNumeral2Int(r)  | 
         | 
   414   case X::L::r => 40 + RomanNumeral2Int(r)  | 
         | 
   415   case X::r    => 10 + RomanNumeral2Int(r)  | 
         | 
   416   case I::X::r => 9 + RomanNumeral2Int(r)  | 
         | 
   417   case V::r    => 5 + RomanNumeral2Int(r)  | 
         | 
   418   case I::V::r => 4 + RomanNumeral2Int(r)  | 
         | 
   419   case I::r    => 1 + RomanNumeral2Int(r)  | 
         | 
   420 }  | 
         | 
   421   | 
         | 
   422 RomanNumeral2Int(List(I,V))             // 4  | 
         | 
   423 RomanNumeral2Int(List(I,I,I,I))         // 4 (invalid Roman number)  | 
         | 
   424 RomanNumeral2Int(List(V,I))             // 6  | 
         | 
   425 RomanNumeral2Int(List(I,X))             // 9  | 
         | 
   426 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979  | 
         | 
   427 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017  | 
         | 
   428   | 
   256   | 
   429   | 
   257 // another example  | 
   430 // another example  | 
         | 
   431 //=================  | 
         | 
   432   | 
         | 
   433 // Once upon a time, in a complete fictional country there were Persons...  | 
         | 
   434   | 
   258   | 
   435   | 
   259 abstract class Person  | 
   436 abstract class Person  | 
   260 case class King() extends Person  | 
   437 case object King extends Person  | 
   261 case class Peer(deg: String, terr: String, succ: Int) extends Person  | 
   438 case class Peer(deg: String, terr: String, succ: Int) extends Person  | 
   262 case class Knight(name: String) extends Person  | 
   439 case class Knight(name: String) extends Person  | 
   263 case class Peasant(name: String) extends Person  | 
   440 case class Peasant(name: String) extends Person  | 
   264 case class Clown() extends Person  | 
   441 case object Clown extends Person  | 
   265   | 
   442   | 
   266 def title(p: Person): String = p match { | 
   443 def title(p: Person): String = p match { | 
   267   case King() => "His Majesty the King"  | 
   444   case King => "His Majesty the King"  | 
   268   case Peer(deg, terr, _) => s"The ${deg} of ${terr}" | 
   445   case Peer(deg, terr, _) => s"The ${deg} of ${terr}" | 
   269   case Knight(name) => s"Sir ${name}" | 
   446   case Knight(name) => s"Sir ${name}" | 
   270   case Peasant(name) => name  | 
   447   case Peasant(name) => name  | 
   271 }  | 
   448 }  | 
   272   | 
   449   | 
   273 def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { | 
   450 def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { | 
   274   case (King(), _) => true  | 
   451   case (King, _) => true  | 
   275   case (Peer(_,_,_), Knight(_)) => true  | 
   452   case (Peer(_,_,_), Knight(_)) => true  | 
   276   case (Peer(_,_,_), Peasant(_)) => true  | 
   453   case (Peer(_,_,_), Peasant(_)) => true  | 
   277   case (Peer(_,_,_), Clown()) => true  | 
   454   case (Peer(_,_,_), Clown) => true  | 
   278   case (Knight(_), Peasant(_)) => true  | 
   455   case (Knight(_), Peasant(_)) => true  | 
   279   case (Knight(_), Clown()) => true  | 
   456   case (Knight(_), Clown) => true  | 
   280   case (Clown(), Peasant(_)) => true  | 
   457   case (Clown, Peasant(_)) => true  | 
   281   case _ => false  | 
   458   case _ => false  | 
   282 }  | 
   459 }  | 
   283   | 
   460   | 
   284 val people = List(Knight("David"),  | 
   461 val people = List(Knight("David"),  | 
   285                   Peer("Duke", "Norfolk", 84),  | 
   462                   Peer("Duke", "Norfolk", 84),  | 
   286                   Peasant("Christian"),  | 
   463                   Peasant("Christian"),  | 
   287                   King(),   | 
   464                   King,   | 
   288                   Clown())  | 
   465                   Clown)  | 
   289   | 
   466   | 
   290 println(people.sortWith(superior(_, _)).mkString(", ")) | 
   467 println(people.sortWith(superior(_, _)).mkString(", ")) | 
   291   | 
   468   | 
   292   | 
   469   | 
   293   | 
   470 // Tail recursion  | 
   294 // Higher-Order Functions  | 
   471 //================  | 
   295 //========================  | 
   472   | 
   296   | 
   473   | 
   297 // functions can take functions as arguments  | 
   474 def fact(n: Long): Long =   | 
   298   | 
   475   if (n == 0) 1 else n * fact(n - 1)  | 
   299 val lst = (1 to 10).toList  | 
   476   | 
   300   | 
   477 fact(10)              //ok  | 
   301 def even(x: Int): Boolean = x % 2 == 0  | 
   478 fact(10000)           // produces a stackoverflow  | 
   302 def odd(x: Int): Boolean = x % 2 == 1  | 
   479   | 
   303   | 
   480 def factT(n: BigInt, acc: BigInt): BigInt =  | 
   304 lst.filter(x => even(x))  | 
   481   if (n == 0) acc else factT(n - 1, n * acc)  | 
   305 lst.filter(even(_))  | 
   482   | 
   306 lst.filter(even)  | 
   483 factT(10, 1)  | 
   307   | 
   484 factT(100000, 1)  | 
   308 lst.find(_ > 8)  | 
   485   | 
   309   | 
   486 // there is a flag for ensuring a function is tail recursive  | 
   310 def square(x: Int): Int = x * x  | 
   487 import scala.annotation.tailrec  | 
   311   | 
   488   | 
   312 lst.map(square)  | 
   489 @tailrec  | 
   313   | 
   490 def factT(n: BigInt, acc: BigInt): BigInt =  | 
   314 lst.map(square).filter(_ > 4)  | 
   491   if (n == 0) acc else factT(n - 1, n * acc)  | 
   315   | 
   492   | 
   316 lst.map(square).filter(_ > 4).map(square)  | 
   493   | 
   317   | 
   494   | 
   318 // in my collatz.scala  | 
   495 // for tail-recursive functions the Scala compiler  | 
   319 //(1 to bnd).map(i => (collatz(i), i)).maxBy(_._1)  | 
   496 // generates loop-like code, which does not need  | 
   320   | 
   497 // to allocate stack-space in each recursive  | 
   321   | 
   498 // call; Scala can do this only for tail-recursive  | 
   322 // type of functions, for example f: Int => Int  | 
   499 // functions  | 
   323   | 
   500   | 
   324 def my_map_int(lst: List[Int], f: Int => Int): List[Int] = lst match { | 
   501   | 
   325   case Nil => Nil  | 
   502 // A Web Crawler   | 
   326   case x::xs => f(x)::my_map_int(xs, f)  | 
   503 //===============  | 
   327 }  | 
   504 //  | 
   328   | 
   505 // the idea is to look for dead links using the  | 
   329 my_map_int(lst, square)  | 
   506 // regular expression "https?://[^"]*"  | 
   330   | 
   507   | 
   331 // other function types  | 
   508 import io.Source  | 
   332 //  | 
   509 import scala.util._  | 
   333 // f1: (Int, Int) => Int  | 
   510   | 
   334 // f2: List[String] => Option[Int]  | 
   511 // gets the first 10K of a web-page  | 
   335 // ...   | 
   512 def get_page(url: String) : String = { | 
   336   | 
   513   Try(Source.fromURL(url)("ISO-8859-1").take(10000).mkString). | 
   337   | 
   514     getOrElse { println(s"  Problem with: $url"); ""} | 
   338 def sumOf(f: Int => Int, lst: List[Int]): Int = lst match { | 
   515 }  | 
   339   case Nil => 0  | 
   516   | 
   340   case x::xs => f(x) + sumOf(f, xs)  | 
   517 // regex for URLs and emails  | 
   341 }  | 
   518 val http_pattern = """"https?://[^"]*"""".r  | 
   342   | 
   519 val email_pattern = """([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})""".r | 
   343 def sum_squares(lst: List[Int]) = sumOf(square, lst)  | 
   520   | 
   344 def sum_cubes(lst: List[Int])   = sumOf(x => x * x * x, lst)  | 
   521   | 
   345   | 
   522 // drops the first and last character from a string  | 
   346 sum_squares(lst)  | 
   523 def unquote(s: String) = s.drop(1).dropRight(1)  | 
   347 sum_cubes(lst)  | 
   524   | 
   348   | 
   525 def get_all_URLs(page: String): Set[String] =   | 
   349 // lets try it factorial  | 
   526   http_pattern.findAllIn(page).map(unquote).toSet  | 
   350 def fact(n: Int): Int = ...  | 
   527   | 
   351   | 
   528 // naive version of crawl - searches until a given depth,  | 
   352 def sum_fact(lst: List[Int]) = sumOf(fact, lst)  | 
   529 // visits pages potentially more than once  | 
   353 sum_fact(lst)  | 
   530 def crawl(url: String, n: Int) : Set[String] = { | 
   354   | 
   531   if (n == 0) Set()  | 
   355 // Avoid being mutable  | 
   532   else { | 
   356 //=====================  | 
   533     println(s"  Visiting: $n $url")  | 
   357   | 
   534     val page = get_page(url)  | 
   358 // a student showed me...  | 
   535     val new_emails = email_pattern.findAllIn(page).toSet  | 
   359 import scala.collection.mutable.ListBuffer  | 
   536     new_emails ++ (for (u <- get_all_URLs(page).par) yield crawl(u, n - 1)).flatten  | 
   360   | 
   537   }  | 
   361   | 
   538 }  | 
   362   | 
   539   | 
   363 def collatz_max(bnd: Long): (Long, Long) = { | 
   540 // some starting URLs for the crawler  | 
   364   val colNos = ListBuffer[(Long, Long)]()  | 
   541 val startURL = """https://nms.kcl.ac.uk/christian.urban/"""  | 
   365   for (i <- (1L to bnd).toList) colNos += ((collatz(i), i))  | 
   542   | 
   366   colNos.max  | 
   543 crawl(startURL, 2)  | 
   367 }  | 
   544   | 
   368   | 
   545   | 
   369 def collatz_max(bnd: Long): (Long, Long) = { | 
   546   | 
   370   (1L to bnd).map((i) => (collatz(i), i)).maxBy(_._1)  | 
   547   | 
   371 }  | 
         | 
   372   | 
         | 
   373 //views -> lazy collection  | 
         | 
   374 def collatz_max(bnd: Long): (Long, Long) = { | 
         | 
   375   (1L to bnd).view.map((i) => (collatz(i), i)).maxBy(_._1)  | 
         | 
   376 }  | 
         | 
   377   | 
         | 
   378 // raises a GC exception  | 
         | 
   379 (1 to 1000000000).filter(_ % 2 == 0).take(10).toList  | 
         | 
   380 // ==> java.lang.OutOfMemoryError: GC overhead limit exceeded  | 
         | 
   381   | 
         | 
   382 (1 to 1000000000).view.filter(_ % 2 == 0).take(10).toList  | 
         | 
   383   | 
   548   | 
   384   | 
   549   | 
   385   | 
   550   | 
   386 // Sudoku  | 
   551 // Sudoku  | 
   387 //========  | 
   552 //========  |