119 val lst = List(None, Some(1), Some(2), None, Some(3))  | 
   122 val lst = List(None, Some(1), Some(2), None, Some(3))  | 
   120   | 
   123   | 
   121 for (x <- lst) yield x.getOrElse(0)  | 
   124 for (x <- lst) yield x.getOrElse(0)  | 
   122   | 
   125   | 
   123   | 
   126   | 
         | 
   127 // a function that turns strings into numbers (similar to .toInt)  | 
         | 
   128 Integer.parseInt("1234") | 
         | 
   129   | 
         | 
   130   | 
         | 
   131 def get_me_an_int(s: String) : Option[Int] =   | 
         | 
   132  Try(Some(Integer.parseInt(s))).getOrElse(None)  | 
   124   | 
   133   | 
   125   | 
   134   | 
   126 // This may not look any better than working with null in Java, but to  | 
   135 // This may not look any better than working with null in Java, but to  | 
   127 // see the value, you have to put yourself in the shoes of the  | 
   136 // see the value, you have to put yourself in the shoes of the  | 
   128 // consumer of the get_me_an_int function, and imagine you didn't  | 
   137 // consumer of the get_me_an_int function, and imagine you didn't  | 
   129 // write that function.  | 
   138 // write that function.  | 
   130 //  | 
   139 //  | 
   131 // In Java, if you didn't write this function, you'd have to depend on  | 
   140 // In Java, if you didn't write this function, you'd have to depend on  | 
   132 // the Javadoc of the get_me_an_int. If you didn't look at the Javadoc,   | 
   141 // the Javadoc of the get_me_an_int. If you didn't look at the Javadoc,   | 
   133 // you might not know that get_me_an_int could return a null, and your   | 
   142 // you might not know that get_me_an_int could return null, and your   | 
   134 // code could potentially throw a NullPointerException.  | 
   143 // code could potentially throw a NullPointerException.  | 
   135   | 
         | 
   136   | 
   144   | 
   137   | 
   145   | 
   138 // even Scala is not immune to problems like this:  | 
   146 // even Scala is not immune to problems like this:  | 
   139   | 
   147   | 
   140 List(5,6,7,8,9).indexOf(7)  | 
   148 List(5,6,7,8,9).indexOf(7)  | 
   152 def even(x: Int) : Boolean = x % 2 == 0  | 
   160 def even(x: Int) : Boolean = x % 2 == 0  | 
   153 def odd(x: Int) : Boolean = x % 2 == 1  | 
   161 def odd(x: Int) : Boolean = x % 2 == 1  | 
   154   | 
   162   | 
   155 val lst = (1 to 10).toList  | 
   163 val lst = (1 to 10).toList  | 
   156   | 
   164   | 
   157 lst.filter(x => even(x))  | 
         | 
   158 lst.filter(even(_))  | 
         | 
   159 lst.filter(even)  | 
   165 lst.filter(even)  | 
   160   | 
         | 
   161 lst.count(even)  | 
   166 lst.count(even)  | 
   162   | 
         | 
   163   | 
         | 
   164 lst.find(even)  | 
   167 lst.find(even)  | 
   165   | 
   168   | 
   166 val ps = List((3, 0), (3, 2), (4, 2), (2, 2), (2, 0), (1, 1), (1, 0))  | 
   169 lst.filter(x => x % 2 == 0)  | 
         | 
   170 lst.filter(_ % 2 == 0)  | 
   167   | 
   171   | 
   168 lst.sortWith(_ > _)  | 
   172 lst.sortWith(_ > _)  | 
   169 lst.sortWith(_ < _)  | 
   173 lst.sortWith(_ < _)  | 
   170   | 
   174   | 
         | 
   175 // but this only works when the arguments are clear, but   | 
         | 
   176 // not with multiple occurences  | 
         | 
   177 lst.find(n => odd(n) && n > 2)  | 
         | 
   178   | 
         | 
   179   | 
         | 
   180 val ps = List((3, 0), (3, 2), (4, 2), (2, 2), (2, 0), (1, 1), (1, 0))  | 
         | 
   181   | 
   171 def lex(x: (Int, Int), y: (Int, Int)) : Boolean =   | 
   182 def lex(x: (Int, Int), y: (Int, Int)) : Boolean =   | 
   172   if (x._1 == y._1) x._2 < y._2 else x._1 < y._1  | 
   183   if (x._1 == y._1) x._2 < y._2 else x._1 < y._1  | 
   173   | 
   184   | 
   174 ps.sortWith(lex)  | 
   185 ps.sortWith(lex)  | 
   175   | 
   186   | 
   245 def sum_cubes(lst: List[Int])   = sumOf(x => x * x * x, lst)  | 
   254 def sum_cubes(lst: List[Int])   = sumOf(x => x * x * x, lst)  | 
   246   | 
   255   | 
   247 sum_squares(lst)  | 
   256 sum_squares(lst)  | 
   248 sum_cubes(lst)  | 
   257 sum_cubes(lst)  | 
   249   | 
   258   | 
   250 // lets try it factorial  | 
   259 // lets try a factorial  | 
   251 def fact(n: Int) : Int =   | 
   260 def fact(n: Int) : Int =   | 
   252   if (n == 0) 1 else n * fact(n - 1)  | 
   261   if (n == 0) 1 else n * fact(n - 1)  | 
   253   | 
   262   | 
   254 def sum_fact(lst: List[Int]) = sumOf(fact, lst)  | 
   263 def sum_fact(lst: List[Int]) = sumOf(fact, lst)  | 
   255 sum_fact(lst)  | 
   264 sum_fact(lst)  | 
   256   | 
   265   | 
   257   | 
   266   | 
   258   | 
   267   | 
   259 // if you like verbosity, you can full-specify the literal.   | 
   268 // sometimes it is needed that you specify the type.   | 
   260 // Don't go telling that to people, though  | 
         | 
   261 (1 to 100).filter((x: Int) => x % 2 == 0).sum   | 
   269 (1 to 100).filter((x: Int) => x % 2 == 0).sum   | 
   262   | 
   270   | 
   263 // As x is known to be an Int anyway, you can omit that part  | 
   271 // in this case it is clear that x mist be an Int  | 
   264 (1 to 100).filter(x => x % 2 == 0).sum  | 
   272 (1 to 100).filter(x => x % 2 == 0).sum  | 
   265   | 
   273   | 
   266 // As each parameter (only x in this case) is passed only once  | 
   274 // As each parameter (only x in this case) is passed only once  | 
   267 // you can use the wizardy placeholder syntax  | 
   275 // you can use the wizardy placeholder syntax  | 
   268 (1 to 100).filter(_ % 2 == 0).sum  | 
   276 (1 to 100).filter(_ % 2 == 0).sum  | 
   269   | 
   277   | 
   270 // But if you want to re-use your literal, you can also put it in a value  | 
   278   | 
   271 // In this case, explicit types are required because there's nothing to infer from  | 
   279   | 
   272 val isEven = (x: Int) => x % 2 == 0  | 
   280 // Option Type and maps  | 
   273 (1 to 100).filter(isEven).sum  | 
   281 //======================  | 
   274   | 
         | 
   275   | 
         | 
   276   | 
         | 
   277 // Option Type again  | 
         | 
   278 //===================  | 
         | 
   279   | 
   282   | 
   280 // a function that turns strings into numbers (similar to .toInt)  | 
   283 // a function that turns strings into numbers (similar to .toInt)  | 
   281 Integer.parseInt("12u34") | 
   284 Integer.parseInt("12u34") | 
   282   | 
   285   | 
         | 
   286 import scala.util._  | 
   283   | 
   287   | 
   284 def get_me_an_int(s: String) : Option[Int] =   | 
   288 def get_me_an_int(s: String) : Option[Int] =   | 
   285  Try(Some(Integer.parseInt(s))).getOrElse(None)  | 
   289  Try(Some(Integer.parseInt(s))).getOrElse(None)  | 
   286   | 
   290   | 
   287 val lst = List("12345", "foo", "5432", "bar", "x21", "456") | 
   291 val lst = List("12345", "foo", "5432", "bar", "x21", "456") | 
   413   | 
   415   | 
   414 for (n <- 0 to 20)   | 
   416 for (n <- 0 to 20)   | 
   415  println(fizz_buzz(n))  | 
   417  println(fizz_buzz(n))  | 
   416   | 
   418   | 
   417   | 
   419   | 
   418 // User-defined Datatypes  | 
         | 
   419 //========================  | 
         | 
   420   | 
         | 
   421   | 
         | 
   422 abstract class Colour  | 
         | 
   423 case object Red extends Colour   | 
         | 
   424 case object Green extends Colour   | 
         | 
   425 case object Blue extends Colour  | 
         | 
   426   | 
         | 
   427 def fav_colour(c: Colour) : Boolean = c match { | 
         | 
   428   case Red   => false  | 
         | 
   429   case Green => true  | 
         | 
   430   case Blue  => false   | 
         | 
   431 }  | 
         | 
   432   | 
         | 
   433 fav_colour(Green)  | 
         | 
   434   | 
         | 
   435   | 
         | 
   436 // ... a tiny bit more useful: Roman Numerals  | 
         | 
   437   | 
         | 
   438 abstract class RomanDigit   | 
         | 
   439 case object I extends RomanDigit   | 
         | 
   440 case object V extends RomanDigit   | 
         | 
   441 case object X extends RomanDigit   | 
         | 
   442 case object L extends RomanDigit   | 
         | 
   443 case object C extends RomanDigit   | 
         | 
   444 case object D extends RomanDigit   | 
         | 
   445 case object M extends RomanDigit   | 
         | 
   446   | 
         | 
   447 type RomanNumeral = List[RomanDigit]   | 
         | 
   448   | 
         | 
   449 List(X,I)  | 
         | 
   450   | 
         | 
   451 /*  | 
         | 
   452 I -> 1  | 
         | 
   453 II -> 2  | 
         | 
   454 III  -> 3  | 
         | 
   455 IV -> 4  | 
         | 
   456 V -> 5  | 
         | 
   457 VI -> 6  | 
         | 
   458 VII -> 7  | 
         | 
   459 VIII -> 8  | 
         | 
   460 IX -> 9  | 
         | 
   461 X -> X  | 
         | 
   462 */  | 
         | 
   463   | 
         | 
   464 def RomanNumeral2Int(rs: RomanNumeral): Int = rs match {  | 
         | 
   465   case Nil => 0  | 
         | 
   466   case M::r    => 1000 + RomanNumeral2Int(r)    | 
         | 
   467   case C::M::r => 900 + RomanNumeral2Int(r)  | 
         | 
   468   case D::r    => 500 + RomanNumeral2Int(r)  | 
         | 
   469   case C::D::r => 400 + RomanNumeral2Int(r)  | 
         | 
   470   case C::r    => 100 + RomanNumeral2Int(r)  | 
         | 
   471   case X::C::r => 90 + RomanNumeral2Int(r)  | 
         | 
   472   case L::r    => 50 + RomanNumeral2Int(r)  | 
         | 
   473   case X::L::r => 40 + RomanNumeral2Int(r)  | 
         | 
   474   case X::r    => 10 + RomanNumeral2Int(r)  | 
         | 
   475   case I::X::r => 9 + RomanNumeral2Int(r)  | 
         | 
   476   case V::r    => 5 + RomanNumeral2Int(r)  | 
         | 
   477   case I::V::r => 4 + RomanNumeral2Int(r)  | 
         | 
   478   case I::r    => 1 + RomanNumeral2Int(r)  | 
         | 
   479 }  | 
         | 
   480   | 
         | 
   481 RomanNumeral2Int(List(I,V))             // 4  | 
         | 
   482 RomanNumeral2Int(List(I,I,I,I))         // 4 (invalid Roman number)  | 
         | 
   483 RomanNumeral2Int(List(V,I))             // 6  | 
         | 
   484 RomanNumeral2Int(List(I,X))             // 9  | 
         | 
   485 RomanNumeral2Int(List(M,C,M,L,X,X,I,X)) // 1979  | 
         | 
   486 RomanNumeral2Int(List(M,M,X,V,I,I))     // 2017  | 
         | 
   487   | 
         | 
   488   | 
         | 
   489 // another example  | 
         | 
   490 //=================  | 
         | 
   491   | 
         | 
   492 // Once upon a time, in a complete fictional   | 
         | 
   493 // country there were Persons...  | 
         | 
   494   | 
         | 
   495   | 
         | 
   496 abstract class Person  | 
         | 
   497 case object King extends Person  | 
         | 
   498 case class Peer(deg: String, terr: String, succ: Int) extends Person  | 
         | 
   499 case class Knight(name: String) extends Person  | 
         | 
   500 case class Peasant(name: String) extends Person  | 
         | 
   501   | 
         | 
   502   | 
         | 
   503 def title(p: Person): String = p match { | 
         | 
   504   case King => "His Majesty the King"  | 
         | 
   505   case Peer(deg, terr, _) => s"The ${deg} of ${terr}" | 
         | 
   506   case Knight(name) => s"Sir ${name}" | 
         | 
   507   case Peasant(name) => name  | 
         | 
   508 }  | 
         | 
   509   | 
         | 
   510 def superior(p1: Person, p2: Person): Boolean = (p1, p2) match { | 
         | 
   511   case (King, _) => true  | 
         | 
   512   case (Peer(_,_,_), Knight(_)) => true  | 
         | 
   513   case (Peer(_,_,_), Peasant(_)) => true  | 
         | 
   514   case (Peer(_,_,_), Clown) => true  | 
         | 
   515   case (Knight(_), Peasant(_)) => true  | 
         | 
   516   case (Knight(_), Clown) => true  | 
         | 
   517   case (Clown, Peasant(_)) => true  | 
         | 
   518   case _ => false  | 
         | 
   519 }  | 
         | 
   520   | 
         | 
   521 val people = List(Knight("David"),  | 
         | 
   522                   Peer("Duke", "Norfolk", 84),  | 
         | 
   523                   Peasant("Christian"),  | 
         | 
   524                   King,   | 
         | 
   525                   Clown)  | 
         | 
   526   | 
         | 
   527 println(people.sortWith(superior).mkString("\n")) | 
         | 
   528   | 
         | 
   529   | 
         | 
   530 // String interpolations as patterns  | 
         | 
   531   | 
         | 
   532 val date = "2000-01-01"  | 
         | 
   533 val s"$year-$month-$day" = date  | 
         | 
   534   | 
         | 
   535 def parse_date(date: String) = date match { | 
         | 
   536   case s"$year-$month-$day" => Some((year.toInt, month.toInt, day.toInt))  | 
         | 
   537   case s"$day/$month/$year" => Some((year.toInt, month.toInt, day.toInt))  | 
         | 
   538   case _ => None  | 
         | 
   539 }   | 
         | 
   540   | 
   420   | 
   541   | 
   421   | 
   542 // Recursion  | 
   422 // Recursion  | 
   543 //===========  | 
   423 //===========  | 
   544   | 
   424   | 
   545 /* a, b, c  | 
   425 // well-known example  | 
   546   | 
   426   | 
   547 aa         aaa  | 
   427 def fib(n: Int) : Int = {  | 
   548 ab         baa   | 
   428   if (n == 0 || n == 1) 1  | 
   549 ac         caa   | 
   429    else fib(n - 1) + fib(n - 2)  | 
   550 ba  =>     ......  | 
   430 }  | 
   551 bb  | 
   431   | 
   552 bc  | 
   432   | 
   553 ca  | 
   433 /* Say you have characters a, b, c.  | 
   554 cb  | 
   434    What are all the combinations of a certain length?  | 
   555 cc  | 
   435   | 
   556   | 
   436    All combinations of length 2:  | 
         | 
   437     | 
         | 
   438      aa, ab, ac, ba, bb, bc, ca, cb, cc  | 
         | 
   439   | 
         | 
   440    Combinations of length 3:  | 
         | 
   441      | 
         | 
   442      aaa, baa, caa, and so on......  | 
   557 */  | 
   443 */  | 
   558   | 
   444   | 
   559 def perms(cs: List[Char], l: Int) : List[String] = { | 
   445 def combs(cs: List[Char], l: Int) : List[String] = { | 
   560   if (l == 0) List("") | 
   446   if (l == 0) List("") | 
   561   else for (c <- cs; s <- perms(cs, l - 1)) yield s"$c$s"  | 
   447   else for (c <- cs; s <- combs(cs, l - 1)) yield s"$c$s"  | 
   562 }  | 
   448 }  | 
   563   | 
   449   | 
   564 perms("abc".toList, 2) | 
   450 combs("abc".toList, 2) | 
         | 
   451   | 
         | 
   452   | 
         | 
   453 // another well-known example  | 
   565   | 
   454   | 
   566 def move(from: Char, to: Char) =  | 
   455 def move(from: Char, to: Char) =  | 
   567   println(s"Move disc from $from to $to!")  | 
   456   println(s"Move disc from $from to $to!")  | 
   568   | 
   457   | 
   569 def hanoi(n: Int, from: Char, via: Char, to: Char) : Unit = { | 
   458 def hanoi(n: Int, from: Char, via: Char, to: Char) : Unit = { | 
   573     move(from, to)  | 
   462     move(from, to)  | 
   574     hanoi(n - 1, via, from, to)  | 
   463     hanoi(n - 1, via, from, to)  | 
   575   }  | 
   464   }  | 
   576 }   | 
   465 }   | 
   577   | 
   466   | 
   578 hanoi(40, 'A', 'B', 'C')  | 
   467 hanoi(4, 'A', 'B', 'C')  | 
   579   | 
   468   | 
   580   | 
   469   | 
   581 // Tail Recursion  | 
   470 // A Recursive Web Crawler / Email Harvester  | 
   582 //================  | 
   471 //===========================================  | 
   583   | 
         | 
   584   | 
         | 
   585 def fact(n: Long): Long =   | 
         | 
   586   if (n == 0) 1 else n * fact(n - 1)  | 
         | 
   587   | 
         | 
   588 fact(10)              //ok  | 
         | 
   589 fact(10000)           // produces a stackoverflow  | 
         | 
   590   | 
         | 
   591 def factT(n: BigInt, acc: BigInt): BigInt =  | 
         | 
   592   if (n == 0) acc else factT(n - 1, n * acc)  | 
         | 
   593   | 
         | 
   594 factT(10, 1)  | 
         | 
   595 factT(100000, 1)  | 
         | 
   596   | 
         | 
   597 // there is a flag for ensuring a function is tail recursive  | 
         | 
   598 import scala.annotation.tailrec  | 
         | 
   599   | 
         | 
   600 @tailrec  | 
         | 
   601 def factT(n: BigInt, acc: BigInt): BigInt =  | 
         | 
   602   if (n == 0) acc else factT(n - 1, n * acc)  | 
         | 
   603   | 
         | 
   604   | 
         | 
   605   | 
         | 
   606 // for tail-recursive functions the Scala compiler  | 
         | 
   607 // generates loop-like code, which does not need  | 
         | 
   608 // to allocate stack-space in each recursive  | 
         | 
   609 // call; Scala can do this only for tail-recursive  | 
         | 
   610 // functions  | 
         | 
   611   | 
         | 
   612   | 
         | 
   613 // A Web Crawler / Email Harvester  | 
         | 
   614 //=================================  | 
         | 
   615 //  | 
   472 //  | 
   616 // the idea is to look for links using the  | 
   473 // the idea is to look for links using the  | 
   617 // regular expression "https?://[^"]*" and for  | 
   474 // regular expression "https?://[^"]*" and for  | 
   618 // email addresses using another regex.  | 
   475 // email addresses using another regex.  | 
   619   | 
   476   | 
   641 def get_all_URLs(page: String): Set[String] =   | 
   498 def get_all_URLs(page: String): Set[String] =   | 
   642   http_pattern.findAllIn(page).map(unquote).toSet  | 
   499   http_pattern.findAllIn(page).map(unquote).toSet  | 
   643   | 
   500   | 
   644 // naive version of crawl - searches until a given depth,  | 
   501 // naive version of crawl - searches until a given depth,  | 
   645 // visits pages potentially more than once  | 
   502 // visits pages potentially more than once  | 
   646 def crawl(url: String, n: Int) : Set[String] = { | 
   503 def crawl(url: String, n: Int) : Unit = { | 
         | 
   504   if (n == 0) ()  | 
         | 
   505   else { | 
         | 
   506     println(s"  Visiting: $n $url")  | 
         | 
   507     for (u <- get_all_URLs(get_page(url))) crawl(u, n - 1)  | 
         | 
   508   }  | 
         | 
   509 }  | 
         | 
   510   | 
         | 
   511 // some starting URLs for the crawler  | 
         | 
   512 val startURL = """https://nms.kcl.ac.uk/christian.urban/"""  | 
         | 
   513   | 
         | 
   514 crawl(startURL, 2)  | 
         | 
   515   | 
         | 
   516   | 
         | 
   517 // a primitive email harvester  | 
         | 
   518 def emails(url: String, n: Int) : Set[String] = { | 
   647   if (n == 0) Set()  | 
   519   if (n == 0) Set()  | 
   648   else { | 
   520   else { | 
   649     println(s"  Visiting: $n $url")  | 
   521     println(s"  Visiting: $n $url")  | 
   650     val page = get_page(url)  | 
   522     val page = get_page(url)  | 
   651     val new_emails = email_pattern.findAllIn(page).toSet  | 
   523     val new_emails = email_pattern.findAllIn(page).toSet  | 
   652     new_emails ++ (for (u <- get_all_URLs(page)) yield crawl(u, n - 1)).flatten  | 
   524     new_emails ++ (for (u <- get_all_URLs(page)) yield emails(u, n - 1)).flatten  | 
   653   }  | 
   525   }  | 
   654 }  | 
   526 }  | 
   655   | 
   527   | 
   656 // some starting URLs for the crawler  | 
   528 emails(startURL, 3)  | 
   657 val startURL = """https://nms.kcl.ac.uk/christian.urban/"""  | 
   529   | 
   658   | 
   530   | 
   659 crawl(startURL, 2)  | 
   531 // if we want to explore the internet "deeper", then we  | 
   660   | 
   532 // first have to parallelise the request of webpages:  | 
   661   | 
   533 //  | 
   662   | 
   534 // scala -cp scala-parallel-collections_2.13-0.2.0.jar   | 
   663   | 
   535 // import scala.collection.parallel.CollectionConverters._  | 
   664   | 
   536   | 
   665   | 
   537   | 
   666   | 
   538   | 
   667 // Sudoku  | 
   539   | 
   668 //========  | 
   540   | 
   669   | 
   541   | 
   670 // THE POINT OF THIS CODE IS NOT TO BE SUPER  | 
         | 
   671 // EFFICIENT AND FAST, just explaining exhaustive  | 
         | 
   672 // depth-first search  | 
         | 
   673   | 
         | 
   674   | 
         | 
   675 val game0 = """.14.6.3..  | 
         | 
   676               |62...4..9  | 
         | 
   677               |.8..5.6..  | 
         | 
   678               |.6.2....3  | 
         | 
   679               |.7..1..5.  | 
         | 
   680               |5....9.6.  | 
         | 
   681               |..6.2..3.  | 
         | 
   682               |1..5...92  | 
         | 
   683               |..7.9.41.""".stripMargin.replaceAll("\\n", "") | 
         | 
   684   | 
         | 
   685 type Pos = (Int, Int)  | 
         | 
   686 val emptyValue = '.'  | 
         | 
   687 val maxValue = 9  | 
         | 
   688   | 
         | 
   689 val allValues = "123456789".toList  | 
         | 
   690 val indexes = (0 to 8).toList  | 
         | 
   691   | 
         | 
   692   | 
         | 
   693 def empty(game: String) = game.indexOf(emptyValue)  | 
         | 
   694 def isDone(game: String) = empty(game) == -1   | 
         | 
   695 def emptyPosition(game: String) : Pos =   | 
         | 
   696   (empty(game) % maxValue, empty(game) / maxValue)  | 
         | 
   697   | 
         | 
   698   | 
         | 
   699 def get_row(game: String, y: Int) = indexes.map(col => game(y * maxValue + col))  | 
         | 
   700 def get_col(game: String, x: Int) = indexes.map(row => game(x + row * maxValue))  | 
         | 
   701   | 
         | 
   702 def get_box(game: String, pos: Pos): List[Char] = { | 
         | 
   703     def base(p: Int): Int = (p / 3) * 3  | 
         | 
   704     val x0 = base(pos._1)  | 
         | 
   705     val y0 = base(pos._2)  | 
         | 
   706     for (x <- (x0 until x0 + 3).toList;  | 
         | 
   707          y <- (y0 until y0 + 3).toList) yield game(x + y * maxValue)  | 
         | 
   708 }           | 
         | 
   709   | 
         | 
   710   | 
         | 
   711 //get_row(game0, 0)  | 
         | 
   712 //get_row(game0, 1)  | 
         | 
   713 //get_box(game0, (3,1))  | 
         | 
   714   | 
         | 
   715 def update(game: String, pos: Int, value: Char): String =   | 
         | 
   716   game.updated(pos, value)  | 
         | 
   717   | 
         | 
   718 def toAvoid(game: String, pos: Pos): List[Char] =   | 
         | 
   719   (get_col(game, pos._1) ++ get_row(game, pos._2) ++ get_box(game, pos))  | 
         | 
   720   | 
         | 
   721 def candidates(game: String, pos: Pos): List[Char] =   | 
         | 
   722   allValues.diff(toAvoid(game, pos))  | 
         | 
   723   | 
         | 
   724 //candidates(game0, (0, 0))  | 
         | 
   725   | 
         | 
   726 def pretty(game: String): String =   | 
         | 
   727   "\n" ++ (game.sliding(maxValue, maxValue).mkString("\n")) | 
         | 
   728   | 
         | 
   729 def search(game: String): List[String] = { | 
         | 
   730   if (isDone(game)) List(game)  | 
         | 
   731   else   | 
         | 
   732     candidates(game, emptyPosition(game)).  | 
         | 
   733       map(c => search(update(game, empty(game), c))).flatten  | 
         | 
   734 }  | 
         | 
   735   | 
         | 
   736 // an easy game  | 
         | 
   737 val game1 = """23.915...  | 
         | 
   738               |...2..54.  | 
         | 
   739               |6.7......  | 
         | 
   740               |..1.....9  | 
         | 
   741               |89.5.3.17  | 
         | 
   742               |5.....6..  | 
         | 
   743               |......9.5  | 
         | 
   744               |.16..7...  | 
         | 
   745               |...329..1""".stripMargin.replaceAll("\\n", "") | 
         | 
   746   | 
         | 
   747   | 
         | 
   748 // a game that is in the sligtly harder category  | 
         | 
   749 val game2 = """8........  | 
         | 
   750               |..36.....  | 
         | 
   751               |.7..9.2..  | 
         | 
   752               |.5...7...  | 
         | 
   753               |....457..  | 
         | 
   754               |...1...3.  | 
         | 
   755               |..1....68  | 
         | 
   756               |..85...1.  | 
         | 
   757               |.9....4..""".stripMargin.replaceAll("\\n", "") | 
         | 
   758   | 
         | 
   759 // a game with multiple solutions  | 
         | 
   760 val game3 = """.8...9743  | 
         | 
   761               |.5...8.1.  | 
         | 
   762               |.1.......  | 
         | 
   763               |8....5...  | 
         | 
   764               |...8.4...  | 
         | 
   765               |...3....6  | 
         | 
   766               |.......7.  | 
         | 
   767               |.3.5...8.  | 
         | 
   768               |9724...5.""".stripMargin.replaceAll("\\n", "") | 
         | 
   769   | 
         | 
   770   | 
         | 
   771 search(game0).map(pretty)  | 
         | 
   772 search(game1).map(pretty)  | 
         | 
   773   | 
         | 
   774 // for measuring time  | 
         | 
   775 def time_needed[T](i: Int, code: => T) = { | 
         | 
   776   val start = System.nanoTime()  | 
         | 
   777   for (j <- 1 to i) code  | 
         | 
   778   val end = System.nanoTime()  | 
         | 
   779   s"${(end - start) / i / 1.0e9} secs" | 
         | 
   780 }  | 
         | 
   781   | 
         | 
   782 search(game2).map(pretty)  | 
         | 
   783 search(game3).distinct.length  | 
         | 
   784 time_needed(3, search(game2))  | 
         | 
   785 time_needed(3, search(game3))  | 
         | 
   786   | 
         | 
   787   | 
         | 
   788   | 
         | 
   789   | 
         | 
   790   | 
         | 
   791   | 
         |