|     37 for (i <- (0 until lst.length).toList) yield square(lst(i)) |     37 for (i <- (0 until lst.length).toList) yield square(lst(i)) | 
|     38  |     38  | 
|     39 // this is just so prone to off-by-one errors; |     39 // this is just so prone to off-by-one errors; | 
|     40 // write instead |     40 // write instead | 
|     41  |     41  | 
|     42 for (e <- lst) yield square(e) |     42 for (e <- lst; if (e % 2) == 0; if (e != 4)) yield square(e) | 
|     43  |     43  | 
|     44  |     44  | 
|     45 //this works for sets as well |     45 //this works for sets as well | 
|     46 val st = Set(1, 2, 3, 4, 5, 6, 7, 8, 9) |     46 val st = Set(1, 2, 3, 4, 5, 6, 7, 8, 9) | 
|     47  |     47  | 
|     69  |     69  | 
|     70  |     70  | 
|     71  |     71  | 
|     72 // know when to use yield and when not: |     72 // know when to use yield and when not: | 
|     73  |     73  | 
|     74 for (e <- Set(1, 2, 3, 4, 5, 6, 7, 8, 9); if e < 5) yield square(e) |     74 val test =  | 
|         |     75  for (e <- Set(1, 2, 3, 4, 5, 6, 7, 8, 9); if e < 5) yield square(e) | 
|         |     76  | 
|     75  |     77  | 
|     76  |     78  | 
|     77 // Option type |     79 // Option type | 
|     78 //============= |     80 //============= | 
|     79  |     81  | 
|     81 //in Scala you use Option |     83 //in Scala you use Option | 
|     82 //   - if the value is present, you use Some(value) |     84 //   - if the value is present, you use Some(value) | 
|     83 //   - if no value is present, you use None |     85 //   - if no value is present, you use None | 
|     84  |     86  | 
|     85  |     87  | 
|     86 List(7,2,3,4,5,6).find(_ < 4) |     88 List(7,24,3,4,5,6).find(_ < 4) | 
|     87 List(5,6,7,8,9).find(_ < 4) |     89 List(5,6,7,8,9).find(_ < 4) | 
|     88  |     90  | 
|         |     91 List(7,2,3,4,5,6).filter(_ < 4) | 
|     89  |     92  | 
|     90 // some operations on Option's |     93 // some operations on Option's | 
|     91  |     94  | 
|     92 val lst = List(None, Some(1), Some(2), None, Some(3)) |     95 val lst = List(None, Some(1), Some(2), None, Some(3)) | 
|     93  |     96  | 
|     94 lst.flatten |     97 lst.flatten | 
|     95  |     98  | 
|     96 Some(1).get |     99 Some(10).get | 
|         |    100 None.get | 
|     97  |    101  | 
|     98 Some(1).isDefined |    102 Some(1).isDefined | 
|     99 None.isDefined |    103 None.isDefined | 
|    100  |    104  | 
|    101 val ps = List((3, 0), (3, 2), (4, 2), (2, 0), (1, 0), (1, 1)) |    105 val ps = List((3, 0), (3, 2), (4, 2), (2, 0), (1, 0), (1, 1)) | 
|    165 // code could potentially throw a NullPointerException. |    170 // code could potentially throw a NullPointerException. | 
|    166  |    171  | 
|    167  |    172  | 
|    168 // even Scala is not immune to problems like this: |    173 // even Scala is not immune to problems like this: | 
|    169  |    174  | 
|    170 List(5,6,7,8,9).indexOf(7) |    175 List(5,6,7,8,9).indexOf(42) | 
|    171  |    176  | 
|    172  |    177  | 
|         |    178 // ... how are we supposed to know that this returns -1 | 
|    173  |    179  | 
|    174  |    180  | 
|    175 // Higher-Order Functions |    181 // Higher-Order Functions | 
|    176 //======================== |    182 //======================== | 
|    177  |    183  | 
|    180 val lst = (1 to 10).toList |    186 val lst = (1 to 10).toList | 
|    181  |    187  | 
|    182 def even(x: Int) : Boolean = x % 2 == 0 |    188 def even(x: Int) : Boolean = x % 2 == 0 | 
|    183 def odd(x: Int) : Boolean = x % 2 == 1 |    189 def odd(x: Int) : Boolean = x % 2 == 1 | 
|    184  |    190  | 
|    185 lst.filter(x => even(x)) |    191 lst.filter(x => even(x) && odd(x)) | 
|    186 lst.filter(even(_)) |    192 lst.filter(even(_)) | 
|    187 lst.filter(even) |    193 lst.filter(odd && even) | 
|    188  |    194  | 
|    189 lst.find(_ > 8) |    195 lst.find(_ > 8) | 
|    190  |    196  | 
|    191 // map applies a function to each element of a list |    197 // map applies a function to each element of a list | 
|    192  |    198  | 
|    193 def square(x: Int): Int = x * x |    199 def square(x: Int): Int = x * x | 
|    194  |    200  | 
|         |    201 val lst = (1 to 10).toList | 
|    195 lst.map(square) |    202 lst.map(square) | 
|    196  |    203  | 
|    197 lst.map(square).filter(_ > 4) |    204 lst.map(square).filter(_ > 4) | 
|    198  |    205  | 
|    199 lst.map(square).filter(_ > 4).map(square) |    206 lst.map(square).filter(_ > 4).map(square) | 
|    200  |    207  | 
|    201 // map works for most collection types, including sets |    208 // map works for most collection types, including sets | 
|    202 Set(1, 3, 6).map(square) |    209 Set(1, 3, 6).map(square).filter(_ > 4) | 
|    203  |    210  | 
|    204  |    211  | 
|    205 // Why could functions as arguments be useful? |    212 val l = List((1, 3),(2, 4),(4, 1),(6, 2)) | 
|         |    213  | 
|         |    214 l.map(square(_._1)) | 
|         |    215  | 
|         |    216  | 
|         |    217 // Why are functions as arguments useful? | 
|    206 // |    218 // | 
|    207 // Consider the sum between a and b: |    219 // Consider the sum between a and b: | 
|    208  |    220  | 
|    209 def sumInts(a: Int, b: Int) : Int =  |    221 def sumInts(a: Int, b: Int) : Int =  | 
|    210   if (a > b) 0 else a + sumInts(a + 1, b) |    222   if (a > b) 0 else a + sumInts(a + 1, b) | 
|    211  |    223  | 
|    212  |    224  | 
|    213 sumInt(10, 16) |    225 sumInts(10, 16) | 
|    214  |    226  | 
|    215 // sum squares |    227 // sum squares | 
|    216 def square(n: Int) : Int = n * n |    228 def square(n: Int) : Int = n * n | 
|    217  |    229  | 
|    218 def sumSquares(a: Int, b: Int) : Int =  |    230 def sumSquares(a: Int, b: Int) : Int =  | 
|    230  |    242  | 
|    231 sumFacts(2, 6) |    243 sumFacts(2, 6) | 
|    232  |    244  | 
|    233  |    245  | 
|    234  |    246  | 
|    235 // You can see the pattern....can we simplify out work? |    247 // You can see the pattern....can we simplify our work? | 
|    236 // The type of functions from ints to ints: Int => Int |    248 // The type of functions from ints to ints: Int => Int | 
|    237  |    249  | 
|    238 def sum(f: Int => Int, a: Int, b: Int) : Int = { |    250 def sum(f: Int => Int, a: Int, b: Int) : Int = { | 
|    239   if (a > b) 0  |    251   if (a > b) 0  | 
|    240   else f(a) + sum(f, a + 1, b) |    252   else f(a) + sum(f, a + 1, b) | 
|    247 // What should we do for sumInts? |    259 // What should we do for sumInts? | 
|    248  |    260  | 
|    249 def id(n: Int) : Int = n |    261 def id(n: Int) : Int = n | 
|    250 def sumInts(a: Int, b: Int) : Int = sum(id, a, b) |    262 def sumInts(a: Int, b: Int) : Int = sum(id, a, b) | 
|    251  |    263  | 
|         |    264 sumInts(10, 12) | 
|    252  |    265  | 
|    253  |    266  | 
|    254 // Anonymous Functions: You can also write: |    267 // Anonymous Functions: You can also write: | 
|    255  |    268  | 
|    256 def sumCubes(a: Int, b: Int) : Int =   sum(x => x * x * x, a, b) |    269 def sumCubes(a: Int, b: Int) : Int =   sum(x => x * x * x, a, b) | 
|    266  |    279  | 
|    267  |    280  | 
|    268 // an aside: partial application |    281 // an aside: partial application | 
|    269  |    282  | 
|    270 def add(a: Int)(b: Int) : Int = a + b |    283 def add(a: Int)(b: Int) : Int = a + b | 
|         |    284 def add_abc(a: Int)(b: Int)(c: Int) : Int = a + b + c | 
|         |    285  | 
|         |    286 val add2 : Int => Int = add(2) | 
|         |    287 add2(5) | 
|         |    288  | 
|         |    289 val add2_bc : Int => Int => Int = add_abc(2)  | 
|         |    290 val add2_9_c : Int => Int = add2_bc(9)  | 
|         |    291  | 
|         |    292 add2_9_c(10) | 
|    271  |    293  | 
|    272 sum(add(2), 0, 2) |    294 sum(add(2), 0, 2) | 
|    273 sum(add(10), 0, 2) |    295 sum(add(10), 0, 2) | 
|    274  |    296  | 
|    275 def add2(a: Int, b: Int) : Int = a + b |         | 
|    276 sum(x => add2(2, x), 0, 2) |         | 
|    277 sum(x => add2(10, x), 0, 2) |         | 
|    278  |    297  | 
|    279 // Function Composition |    298 // Function Composition | 
|    280 //====================== |    299 //====================== | 
|    281  |    300  | 
|    282 // How could Higher-Order Functions and Options be helpful? |    301 // How can be Higher-Order Functions and Options be helpful? | 
|    283  |    302  | 
|    284 def add_footer(msg: String) : String = msg ++ " - Sent from iOS" |    303 def add_footer(msg: String) : String = msg ++ " - Sent from iOS" | 
|    285  |    304  | 
|    286 def valid_msg(msg: String) : Boolean = msg.size <= 140 |    305 def valid_msg(msg: String) : Boolean = msg.size <= 140 | 
|    287  |    306  | 
|    288 def duplicate(s: String) : String = s ++ s |    307 def duplicate(s: String) : String = s ++ s | 
|    289  |    308  | 
|    290 // they compose nicely |    309 // they compose very nicely, e.g | 
|         |    310  | 
|    291 valid_msg(add_footer("Hello World")) |    311 valid_msg(add_footer("Hello World")) | 
|    292 valid_msg(duplicate(add_footer("Hello World"))) |    312 valid_msg(duplicate(duplicate(add_footer("Helloooooooooooooooooo World")))) | 
|    293  |    313  | 
|    294  |    314 // but not all functions do | 
|    295 // first_word: let's first do it the ugly Java way using null: |    315 // first_word: let's first do it the ugly Java way using null: | 
|    296  |    316  | 
|    297 def first_word(msg: String) : String = { |    317 def first_word(msg: String) : String = { | 
|    298   val words = msg.split(" ") |    318   val words = msg.split(" ") | 
|    299   if (words(0) != "") words(0) else null |    319   if (words(0) != "") words(0) else null | 
|    304  |    324  | 
|    305 def extended_duplicate(s: String) : String =  |    325 def extended_duplicate(s: String) : String =  | 
|    306   if (s != null) s ++ s else null |    326   if (s != null) s ++ s else null | 
|    307  |    327  | 
|    308 extended_duplicate(first_word("")) |    328 extended_duplicate(first_word("")) | 
|         |    329  | 
|         |    330 // but this is against the rules of the game: we do not want | 
|         |    331 // to change duplicate, because first_word might return null | 
|    309  |    332  | 
|    310  |    333  | 
|    311 // Avoid always null! |    334 // Avoid always null! | 
|    312 def better_first_word(msg: String) : Option[String] = { |    335 def better_first_word(msg: String) : Option[String] = { | 
|    313   val words = msg.split(" ") |    336   val words = msg.split(" ") | 
|    314   if (words(0) != "") Some(words(0)) else None |    337   if (words(0) != "") Some(words(0)) else None | 
|    315 } |    338 } | 
|    316  |    339  | 
|    317 better_first_word("Hello World").map(duplicate) |    340 better_first_word("Hello World").map(duplicate) | 
|    318 better_first_word("Hello World").map(duplicate).map(duplicate).map(valid_msg) |    341  | 
|         |    342 better_first_word("Hello World").map(duplicate) | 
|         |    343 better_first_word("").map(duplicate).map(duplicate).map(valid_msg) | 
|    319  |    344  | 
|    320 better_first_word("").map(duplicate) |    345 better_first_word("").map(duplicate) | 
|    321 better_first_word("").map(duplicate).map(valid_msg) |    346 better_first_word("").map(duplicate).map(valid_msg) | 
|    322  |         | 
|    323  |         | 
|    324  |         | 
|    325  |         | 
|    326  |         | 
|    327  |         | 
|    328 // Implicits (Cool Feature) |         | 
|    329 //========================= |         | 
|    330 // |         | 
|    331 // For example adding your own methods to Strings: |         | 
|    332 // Imagine you want to increment strings, like |         | 
|    333 // |         | 
|    334 //     "HAL".increment |         | 
|    335 // |         | 
|    336 // you can avoid ugly fudges, like a MyString, by |         | 
|    337 // using implicit conversions. |         | 
|    338  |         | 
|    339  |         | 
|    340 implicit class MyString(s: String) { |         | 
|    341   def increment = for (c <- s) yield (c + 1).toChar  |         | 
|    342 } |         | 
|    343  |         | 
|    344 "HAL".increment |         | 
|    345  |         | 
|    346  |         | 
|    347  |         | 
|    348 // No returns in Scala |         | 
|    349 //==================== |         | 
|    350  |         | 
|    351 // You should not use "return" in Scala: |         | 
|    352 // |         | 
|    353 // A return expression, when evaluated, abandons the  |         | 
|    354 // current computation and returns to the caller of the  |         | 
|    355 // function in which return appears." |         | 
|    356  |         | 
|    357 def sq1(x: Int): Int = x * x |         | 
|    358 def sq2(x: Int): Int = return x * x |         | 
|    359  |         | 
|    360 def sumq(ls: List[Int]): Int = { |         | 
|    361   ls.map(sq1).sum[Int] |         | 
|    362 } |         | 
|    363  |         | 
|    364 sumq(List(1, 2, 3, 4)) |         | 
|    365  |         | 
|    366  |         | 
|    367  |         | 
|    368 def sumq(ls: List[Int]): Int = { |         | 
|    369   val sqs : List[Int] = for (x <- ls) yield (return x * x) |         | 
|    370   sqs.sum |         | 
|    371 } |         | 
|    372  |         | 
|    373  |         | 
|    374  |    347  | 
|    375  |    348  | 
|    376 // Pattern Matching |    349 // Pattern Matching | 
|    377 //================== |    350 //================== | 
|    378  |    351  | 
|    447   case Green() => true |    420   case Green() => true | 
|    448   case Blue()  => false  |    421   case Blue()  => false  | 
|    449 } |    422 } | 
|    450  |    423  | 
|    451  |    424  | 
|    452 // actually this can be written with "object" |    425 // actually colors can be written with "object", | 
|         |    426 // because they do not take any arguments | 
|    453  |    427  | 
|    454  |    428  | 
|    455 // another example |    429 // another example | 
|    456 //================= |    430 //================= | 
|         |    431  | 
|         |    432 // Once upon a time, in a complete fictional country there were persons... | 
|    457  |    433  | 
|    458 abstract class Person |    434 abstract class Person | 
|    459 case class King() extends Person |    435 case class King() extends Person | 
|    460 case class Peer(deg: String, terr: String, succ: Int) extends Person |    436 case class Peer(deg: String, terr: String, succ: Int) extends Person | 
|    461 case class Knight(name: String) extends Person |    437 case class Knight(name: String) extends Person | 
|    506 val A = (1 to 1000).toSet |    481 val A = (1 to 1000).toSet | 
|    507 val B = (1 to 1000 by 4).toSet |    482 val B = (1 to 1000 by 4).toSet | 
|    508  |    483  | 
|    509 count_intersection(A, B) |    484 count_intersection(A, B) | 
|    510  |    485  | 
|    511 // but do not try to add .par to the for-loop above |    486 // but do not try to add .par to the for-loop above, | 
|         |    487 // otherwise you will be caught in race-condition hell. | 
|    512  |    488  | 
|    513  |    489  | 
|    514 //propper parallel version |    490 //propper parallel version | 
|    515 def count_intersection2(A: Set[Int], B: Set[Int]) : Int =  |    491 def count_intersection2(A: Set[Int], B: Set[Int]) : Int =  | 
|    516   A.par.count(x => B contains x) |    492   A.par.count(x => B contains x) | 
|    531  |    507  | 
|    532 time_needed(10, count_intersection(A, B)) |    508 time_needed(10, count_intersection(A, B)) | 
|    533 time_needed(10, count_intersection2(A, B)) |    509 time_needed(10, count_intersection2(A, B)) | 
|    534  |    510  | 
|    535  |    511  | 
|         |    512 // Implicits (Cool Feature) | 
|         |    513 //========================= | 
|         |    514 // | 
|         |    515 // For example adding your own methods to Strings: | 
|         |    516 // Imagine you want to increment strings, like | 
|         |    517 // | 
|         |    518 //     "HAL".increment | 
|         |    519 // | 
|         |    520 // you can avoid ugly fudges, like a MyString, by | 
|         |    521 // using implicit conversions. | 
|         |    522  | 
|         |    523  | 
|         |    524 implicit class MyString(s: String) { | 
|         |    525   def increment = for (c <- s) yield (c + 1).toChar  | 
|         |    526 } | 
|         |    527  | 
|         |    528 "HAL".increment | 
|         |    529  | 
|         |    530  | 
|         |    531  | 
|         |    532 // No returns in Scala | 
|         |    533 //==================== | 
|         |    534  | 
|         |    535 // You should not use "return" in Scala: | 
|         |    536 // | 
|         |    537 // A return expression, when evaluated, abandons the  | 
|         |    538 // current computation and returns to the caller of the  | 
|         |    539 // function in which return appears." | 
|         |    540  | 
|         |    541 def sq1(x: Int): Int = x * x | 
|         |    542 def sq2(x: Int): Int = return x * x | 
|         |    543  | 
|         |    544 def sumq(ls: List[Int]): Int = { | 
|         |    545   ls.map(sq1).sum[Int] | 
|         |    546 } | 
|         |    547  | 
|         |    548 sumq(List(1, 2, 3, 4)) | 
|         |    549  | 
|         |    550  | 
|         |    551  | 
|         |    552 def sumq(ls: List[Int]): Int = { | 
|         |    553   val sqs : List[Int] = for (x <- ls) yield (return x * x) | 
|         |    554   sqs.sum | 
|         |    555 } | 
|         |    556  | 
|         |    557  | 
|         |    558  | 
|         |    559  | 
|    536 // Type abbreviations |    560 // Type abbreviations | 
|    537 //==================== |    561 //==================== | 
|    538  |    562  | 
|    539 // some syntactic convenience |    563 // some syntactic convenience | 
|    540  |    564  | 
|    570 val indexes = (0 to 8).toList |    594 val indexes = (0 to 8).toList | 
|    571  |    595  | 
|    572  |    596  | 
|    573 def empty(game: String) = game.indexOf(EmptyValue) |    597 def empty(game: String) = game.indexOf(EmptyValue) | 
|    574 def isDone(game: String) = empty(game) == -1  |    598 def isDone(game: String) = empty(game) == -1  | 
|    575 def emptyPosition(game: String) = (empty(game) % MaxValue, empty(game) / MaxValue) |    599 def emptyPosition(game: String) =  | 
|    576  |    600   (empty(game) % MaxValue, empty(game) / MaxValue) | 
|    577  |    601  | 
|    578 def get_row(game: String, y: Int) = indexes.map(col => game(y * MaxValue + col)) |    602  | 
|    579 def get_col(game: String, x: Int) = indexes.map(row => game(x + row * MaxValue)) |    603 def get_row(game: String, y: Int) =  | 
|         |    604   indexes.map(col => game(y * MaxValue + col)) | 
|         |    605 def get_col(game: String, x: Int) =  | 
|         |    606   indexes.map(row => game(x + row * MaxValue)) | 
|    580  |    607  | 
|    581 get_row(game0, 3) |    608 get_row(game0, 3) | 
|    582 get_col(game0, 0) |    609 get_col(game0, 0) | 
|    583  |    610  | 
|    584 def get_box(game: String, pos: Pos): List[Char] = { |    611 def get_box(game: String, pos: Pos): List[Char] = { | 
|    592 get_box(game0, (0, 0)) |    619 get_box(game0, (0, 0)) | 
|    593 get_box(game0, (1, 1)) |    620 get_box(game0, (1, 1)) | 
|    594 get_box(game0, (2, 1)) |    621 get_box(game0, (2, 1)) | 
|    595  |    622  | 
|    596 // this is not mutable!! |    623 // this is not mutable!! | 
|    597 def update(game: String, pos: Int, value: Char): String = game.updated(pos, value) |    624 def update(game: String, pos: Int, value: Char): String =  | 
|         |    625   game.updated(pos, value) | 
|    598  |    626  | 
|    599 def toAvoid(game: String, pos: Pos): List[Char] =  |    627 def toAvoid(game: String, pos: Pos): List[Char] =  | 
|    600   (get_col(game, pos._1) ++ get_row(game, pos._2) ++ get_box(game, pos)) |    628   (get_col(game, pos._1) ++ get_row(game, pos._2) ++ get_box(game, pos)) | 
|    601  |    629  | 
|    602 def candidates(game: String, pos: Pos): List[Char] = allValues.diff(toAvoid(game,pos)) |    630 def candidates(game: String, pos: Pos): List[Char] =  | 
|         |    631   allValues.diff(toAvoid(game,pos)) | 
|    603  |    632  | 
|    604 //candidates(game0, (0,0)) |    633 //candidates(game0, (0,0)) | 
|    605  |    634  | 
|    606 def pretty(game: String): String =  |    635 def pretty(game: String): String =  | 
|    607   "\n" + (game sliding (MaxValue, MaxValue) mkString "\n") |    636   "\n" + (game sliding (MaxValue, MaxValue) mkString "\n") | 
|    608  |    637  | 
|    609 def search(game: String): List[String] = { |    638 def search(game: String): List[String] = { | 
|    610   if (isDone(game)) List(game) |    639   if (isDone(game)) List(game) | 
|    611   else { |    640   else { | 
|    612     val cs = candidates(game, emptyPosition(game)) |    641     val cs = candidates(game, emptyPosition(game)) | 
|    613     cs.map(c => search(update(game, empty(game), c))).toList.flatten |    642     cs.par.map(c => search(update(game, empty(game), c))).toList.flatten | 
|    614   } |    643   } | 
|    615 } |    644 } | 
|    616  |    645  | 
|    617 search(game0).map(pretty) |    646 search(game0).map(pretty) | 
|    618  |    647  |