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