|    269               |5....9.6. |    269               |5....9.6. | 
|    270               |..6.2..3. |    270               |..6.2..3. | 
|    271               |1..5...92 |    271               |1..5...92 | 
|    272               |..7.9.41.""".stripMargin.replaceAll("\\n", "") |    272               |..7.9.41.""".stripMargin.replaceAll("\\n", "") | 
|    273  |    273  | 
|    274 candidates(game0, (0, 0)) |    274  | 
|    275  |    275  | 
|    276 type Pos = (Int, Int) |    276 type Pos = (Int, Int) | 
|    277 val EmptyValue = '.' |    277 val EmptyValue = '.' | 
|    278 val MaxValue = 9 |    278 val MaxValue = 9 | 
|    279  |    279  | 
|         |    280 def pretty(game: String): String =  | 
|         |    281   "\n" + (game.grouped(MaxValue).mkString("\n")) | 
|         |    282  | 
|         |    283 pretty(game0) | 
|         |    284  | 
|         |    285  | 
|    280 val allValues = "123456789".toList |    286 val allValues = "123456789".toList | 
|    281 val indexes = (0 to 8).toList |    287 val indexes = (0 to 8).toList | 
|    282  |    288  | 
|    283  |         | 
|    284 def empty(game: String) = game.indexOf(EmptyValue) |    289 def empty(game: String) = game.indexOf(EmptyValue) | 
|    285 def isDone(game: String) = empty(game) == -1  |    290 def isDone(game: String) = empty(game) == -1  | 
|    286 def emptyPosition(game: String) =  |    291 def emptyPosition(game: String) = { | 
|    287   (empty(game) % MaxValue, empty(game) / MaxValue) |    292   val e = empty(game) | 
|    288  |    293   (e % MaxValue, e / MaxValue) | 
|         |    294 } | 
|    289  |    295  | 
|    290 def get_row(game: String, y: Int) =  |    296 def get_row(game: String, y: Int) =  | 
|    291   indexes.map(col => game(y * MaxValue + col)) |    297   indexes.map(col => game(y * MaxValue + col)) | 
|    292 def get_col(game: String, x: Int) =  |    298 def get_col(game: String, x: Int) =  | 
|    293   indexes.map(row => game(x + row * MaxValue)) |    299   indexes.map(row => game(x + row * MaxValue)) | 
|    294  |    300  | 
|    295 get_row(game0, 0) |    301 //get_row(game0, 0) | 
|         |    302 //get_row(game0, 1) | 
|         |    303 //get_col(game0, 0) | 
|    296  |    304  | 
|    297 def get_box(game: String, pos: Pos): List[Char] = { |    305 def get_box(game: String, pos: Pos): List[Char] = { | 
|    298     def base(p: Int): Int = (p / 3) * 3 |    306     def base(p: Int): Int = (p / 3) * 3 | 
|    299     val x0 = base(pos._1) |    307     val x0 = base(pos._1) | 
|    300     val y0 = base(pos._2) |    308     val y0 = base(pos._2) | 
|    301     val ys = (y0 until y0 + 3).toList |    309     val ys = (y0 until y0 + 3).toList | 
|    302     (x0 until x0 + 3).toList.flatMap(x => ys.map(y => game(x + y * MaxValue))) |    310     (x0 until x0 + 3).toList | 
|    303 } |    311       .flatMap(x => ys.map(y => game(x + y * MaxValue))) | 
|    304  |    312 } | 
|    305 //get_row(game0, 0) |    313  | 
|    306 //get_row(game0, 1) |    314  | 
|    307 //get_col(game0, 0) |         | 
|    308 //get_box(game0, (3, 1)) |    315 //get_box(game0, (3, 1)) | 
|    309  |    316  | 
|    310  |    317  | 
|    311 // this is not mutable!! |    318 // this is not mutable!! | 
|    312 def update(game: String, pos: Int, value: Char): String =  |    319 def update(game: String, pos: Int, value: Char): String =  | 
|    313   game.updated(pos, value) |    320   game.updated(pos, value) | 
|    314  |    321  | 
|    315 def toAvoid(game: String, pos: Pos): List[Char] =  |    322 def toAvoid(game: String, pos: Pos): List[Char] =  | 
|    316   (get_col(game, pos._1) ++ get_row(game, pos._2) ++ get_box(game, pos)) |    323   (get_col(game, pos._1) ++  | 
|         |    324    get_row(game, pos._2) ++  | 
|         |    325    get_box(game, pos)) | 
|    317  |    326  | 
|    318 def candidates(game: String, pos: Pos): List[Char] =  |    327 def candidates(game: String, pos: Pos): List[Char] =  | 
|    319   allValues.diff(toAvoid(game, pos)) |    328   allValues.diff(toAvoid(game, pos)) | 
|    320  |    329  | 
|    321 //candidates(game0, (0,0)) |    330 //candidates(game0, (0,0)) | 
|    322  |    331  | 
|    323 def pretty(game: String): String =  |         | 
|    324   "\n" + (game.sliding(MaxValue, MaxValue).mkString("\n")) |         | 
|    325  |    332  | 
|    326 def search(game: String): List[String] = { |    333 def search(game: String): List[String] = { | 
|    327   if (isDone(game)) List(game) |    334   if (isDone(game)) List(game) | 
|    328   else { |    335   else { | 
|    329     val cs = candidates(game, emptyPosition(game)) |    336     val cs = candidates(game, emptyPosition(game)) | 
|    330     cs.map(c => search(update(game, empty(game), c))).toList.flatten |    337     cs.map(c => search(update(game, empty(game), c))).flatten | 
|    331   } |    338   } | 
|    332 } |    339 } | 
|    333  |    340  | 
|    334 List(List("sol1"), List("sol2", "sol3")).flatten |    341 pretty(game0) | 
|    335  |         | 
|    336 search(game0).map(pretty) |    342 search(game0).map(pretty) | 
|    337  |    343  | 
|    338 val game1 = """23.915... |    344 val game1 = """23.915... | 
|    339               |...2..54. |    345               |...2..54. | 
|    340               |6.7...... |    346               |6.7...... |