multi-puzzle-solver 0.9.25__tar.gz → 0.9.27__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of multi-puzzle-solver might be problematic. Click here for more details.

Files changed (112) hide show
  1. {multi_puzzle_solver-0.9.25/src/multi_puzzle_solver.egg-info → multi_puzzle_solver-0.9.27}/PKG-INFO +199 -3
  2. multi_puzzle_solver-0.9.25/PKG-INFO → multi_puzzle_solver-0.9.27/README.md +4085 -3915
  3. multi_puzzle_solver-0.9.25/README.md → multi_puzzle_solver-0.9.27/src/multi_puzzle_solver.egg-info/PKG-INFO +4111 -3889
  4. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/multi_puzzle_solver.egg-info/SOURCES.txt +3 -0
  5. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/__init__.py +3 -2
  6. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/core/utils.py +3 -154
  7. multi_puzzle_solver-0.9.27/src/puzzle_solver/core/utils_visualizer.py +310 -0
  8. multi_puzzle_solver-0.9.27/src/puzzle_solver/puzzles/flip/flip.py +77 -0
  9. multi_puzzle_solver-0.9.27/src/puzzle_solver/puzzles/nurikabe/nurikabe.py +126 -0
  10. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/palisade/palisade.py +3 -2
  11. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/rectangles/rectangles.py +2 -2
  12. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/slitherlink/slitherlink.py +2 -1
  13. multi_puzzle_solver-0.9.27/tests/test_flip.py +73 -0
  14. multi_puzzle_solver-0.9.27/tests/test_nurikabe.py +92 -0
  15. multi_puzzle_solver-0.9.25/src/puzzle_solver/puzzles/flip/flip.py +0 -48
  16. multi_puzzle_solver-0.9.25/tests/test_flip.py +0 -2
  17. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/pyproject.toml +0 -0
  18. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/setup.cfg +0 -0
  19. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/multi_puzzle_solver.egg-info/dependency_links.txt +0 -0
  20. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/multi_puzzle_solver.egg-info/requires.txt +0 -0
  21. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/multi_puzzle_solver.egg-info/top_level.txt +0 -0
  22. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/core/utils_ortools.py +0 -0
  23. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/aquarium/aquarium.py +0 -0
  24. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/battleships/battleships.py +0 -0
  25. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/binairo/binairo.py +0 -0
  26. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/black_box/black_box.py +0 -0
  27. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/bridges/bridges.py +0 -0
  28. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/chess_range/chess_melee.py +0 -0
  29. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/chess_range/chess_range.py +0 -0
  30. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/chess_range/chess_solo.py +0 -0
  31. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/dominosa/dominosa.py +0 -0
  32. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/filling/filling.py +0 -0
  33. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/galaxies/galaxies.py +0 -0
  34. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/galaxies/parse_map/parse_map.py +0 -0
  35. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/guess/guess.py +0 -0
  36. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/inertia/inertia.py +0 -0
  37. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/inertia/parse_map/parse_map.py +0 -0
  38. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/inertia/tsp.py +0 -0
  39. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/kakurasu/kakurasu.py +0 -0
  40. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/keen/keen.py +0 -0
  41. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/light_up/light_up.py +0 -0
  42. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/lits/lits.py +0 -0
  43. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/magnets/magnets.py +0 -0
  44. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/map/map.py +0 -0
  45. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/minesweeper/minesweeper.py +0 -0
  46. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/mosaic/mosaic.py +0 -0
  47. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/nonograms/nonograms.py +0 -0
  48. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/norinori/norinori.py +0 -0
  49. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/pearl/pearl.py +0 -0
  50. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/range/range.py +0 -0
  51. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/signpost/signpost.py +0 -0
  52. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/singles/singles.py +0 -0
  53. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/slant/parse_map/parse_map.py +0 -0
  54. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/slant/slant.py +0 -0
  55. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/star_battle/star_battle.py +0 -0
  56. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/star_battle/star_battle_shapeless.py +0 -0
  57. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/stitches/parse_map/parse_map.py +0 -0
  58. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/stitches/stitches.py +0 -0
  59. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/sudoku/sudoku.py +0 -0
  60. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/tents/tents.py +0 -0
  61. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/thermometers/thermometers.py +0 -0
  62. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/towers/towers.py +0 -0
  63. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/tracks/tracks.py +0 -0
  64. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/undead/undead.py +0 -0
  65. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/unequal/unequal.py +0 -0
  66. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/unruly/unruly.py +0 -0
  67. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/yin_yang/parse_map/parse_map.py +0 -0
  68. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/puzzles/yin_yang/yin_yang.py +0 -0
  69. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/src/puzzle_solver/utils/visualizer.py +0 -0
  70. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_aquarium.py +0 -0
  71. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_battleships.py +0 -0
  72. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_binairo.py +0 -0
  73. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_black_box.py +0 -0
  74. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_bridges.py +0 -0
  75. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_chess_melee.py +0 -0
  76. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_chess_range.py +0 -0
  77. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_chess_solo.py +0 -0
  78. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_dominosa.py +0 -0
  79. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_filling.py +0 -0
  80. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_galaxies.py +0 -0
  81. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_guess.py +0 -0
  82. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_inertia.py +0 -0
  83. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_kakurasu.py +0 -0
  84. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_keen.py +0 -0
  85. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_light_up.py +0 -0
  86. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_lits.py +0 -0
  87. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_magnets.py +0 -0
  88. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_map.py +0 -0
  89. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_minesweeper.py +0 -0
  90. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_mosaic.py +0 -0
  91. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_nonograms.py +0 -0
  92. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_norinori.py +0 -0
  93. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_palisade.py +0 -0
  94. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_pearl.py +0 -0
  95. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_range.py +0 -0
  96. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_rectangles.py +0 -0
  97. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_signpost.py +0 -0
  98. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_singles.py +0 -0
  99. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_slant.py +0 -0
  100. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_slitherlink.py +0 -0
  101. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_star_battle.py +0 -0
  102. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_stitches.py +0 -0
  103. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_sudoku.py +0 -0
  104. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_tents.py +0 -0
  105. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_thermometers.py +0 -0
  106. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_towers.py +0 -0
  107. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_tracks.py +0 -0
  108. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_undead.py +0 -0
  109. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_unequal.py +0 -0
  110. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_unruly.py +0 -0
  111. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_utils.py +0 -0
  112. {multi_puzzle_solver-0.9.25 → multi_puzzle_solver-0.9.27}/tests/test_yin_yang.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: multi-puzzle-solver
3
- Version: 0.9.25
3
+ Version: 0.9.27
4
4
  Summary: Efficient solvers for numerous popular and esoteric logic puzzles using CP-SAT
5
5
  Author: Ar-Kareem
6
6
  Project-URL: Homepage, https://github.com/Ar-Kareem/puzzle_solver
@@ -331,6 +331,16 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
331
331
  <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/palisade_solved.png" alt="Palisade" width="140">
332
332
  </a>
333
333
  </td>
334
+ <td align="center">
335
+ <a href="#flip-puzzle-type-44"><b>Flip</b><br><br>
336
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/flip_unsolved.png" alt="Flip" width="140">
337
+ </a>
338
+ </td>
339
+ <td align="center">
340
+ <a href="#nurikabe-puzzle-type-45"><b>Nurikabe</b><br><br>
341
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/nurikabe_unsolved.png" alt="Nurikabe" width="140">
342
+ </a>
343
+ </td>
334
344
  </tr>
335
345
  </table>
336
346
 
@@ -389,6 +399,8 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
389
399
  - [Binairo (Puzzle Type #41)](#binairo-puzzle-type-41)
390
400
  - [Rectangles (Puzzle Type #42)](#rectangles-puzzle-type-42)
391
401
  - [Palisade (Puzzle Type #43)](#palisade-puzzle-type-43)
402
+ - [Flip (Puzzle Type #44)](#flip-puzzle-type-44)
403
+ - [Nurikabe (Puzzle Type #45)](#nurikabe-puzzle-type-45)
392
404
  - [Why SAT / CP-SAT?](#why-sat--cp-sat)
393
405
  - [Testing](#testing)
394
406
  - [Contributing](#contributing)
@@ -3730,14 +3742,13 @@ Applying the solution to the puzzle visually:
3730
3742
 
3731
3743
  ---
3732
3744
 
3733
-
3734
3745
  ## Palisade (Puzzle Type #43)
3735
3746
 
3736
3747
  * [**Play online**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/js/palisade.html)
3737
3748
 
3738
3749
  * [**Instructions**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/doc/palisade.html#palisade)
3739
3750
 
3740
- * [**Solver Code**][42]
3751
+ * [**Solver Code**][43]
3741
3752
 
3742
3753
  <details>
3743
3754
  <summary><strong>Rules</strong></summary>
@@ -3819,6 +3830,189 @@ Applying the solution to the puzzle visually:
3819
3830
 
3820
3831
  ---
3821
3832
 
3833
+ ## Flip (Puzzle Type #44)
3834
+
3835
+ * [**Play online**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/js/flip.html)
3836
+
3837
+ * [**Instructions**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/doc/flip.html#flip)
3838
+
3839
+ * [**Solver Code**][44]
3840
+
3841
+ <details>
3842
+ <summary><strong>Rules</strong></summary>
3843
+
3844
+ You have a grid of squares, some light and some dark. Your aim is to light all the squares up at the same time. You can choose any square and flip its state from light to dark or dark to light, but when you do so, other squares around it change state as well.
3845
+
3846
+ </details>
3847
+
3848
+ **Unsolved puzzle**
3849
+
3850
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/flip_unsolved.png" alt="Flip unsolved" width="500">
3851
+
3852
+ Code to utilize this package and solve the puzzle:
3853
+
3854
+ (Note: the solver also supports random mapping of squares to the neighbors they flip, see the test cases in `tests/test_flip.py` for usage examples)
3855
+
3856
+ ```python
3857
+ import numpy as np
3858
+ from puzzle_solver import flip_solver as solver
3859
+ board = np.array([
3860
+ ['B', 'W', 'W', 'W', 'W', 'W', 'W'],
3861
+ ['B', 'B', 'W', 'W', 'W', 'B', 'B'],
3862
+ ['W', 'B', 'W', 'W', 'B', 'B', 'W'],
3863
+ ['B', 'B', 'B', 'W', 'W', 'B', 'W'],
3864
+ ['W', 'W', 'B', 'B', 'W', 'B', 'W'],
3865
+ ['B', 'W', 'B', 'B', 'W', 'W', 'W'],
3866
+ ['B', 'W', 'B', 'W', 'W', 'B', 'B'],
3867
+ ])
3868
+ binst = solver.Board(board=board)
3869
+ solutions = binst.solve_and_print()
3870
+ ```
3871
+
3872
+ **Script Output**
3873
+
3874
+ The output tells you which squares to tap to solve the puzzle.
3875
+
3876
+ ```python
3877
+ Solution found
3878
+ [['T' ' ' 'T' 'T' 'T' ' ' ' ']
3879
+ [' ' ' ' ' ' 'T' ' ' 'T' ' ']
3880
+ [' ' 'T' ' ' ' ' 'T' ' ' ' ']
3881
+ ['T' ' ' 'T' ' ' ' ' 'T' ' ']
3882
+ [' ' ' ' ' ' 'T' ' ' ' ' 'T']
3883
+ ['T' ' ' 'T' ' ' 'T' 'T' 'T']
3884
+ [' ' ' ' ' ' ' ' ' ' 'T' 'T']]
3885
+ Solutions found: 1
3886
+ status: OPTIMAL
3887
+ ```
3888
+
3889
+ **Solved puzzle**
3890
+
3891
+ This picture won't mean much as the game is about the sequence of moves not the final frame as shown here.
3892
+
3893
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/flip_solved.png" alt="Flip solved" width="500">
3894
+
3895
+ ---
3896
+ ## Nurikabe (Puzzle Type #45)
3897
+
3898
+ * [**Play online**](https://www.puzzle-nurikabe.com/)
3899
+
3900
+ * [**Instructions**](https://www.logicgamesonline.com/nurikabe/)
3901
+
3902
+ * [**Solver Code**][45]
3903
+
3904
+ <details>
3905
+ <summary><strong>Rules</strong></summary>
3906
+
3907
+ Nurikabe is a binary determination puzzle. You must decide for each cell if it is white or black according to the following rules:
3908
+
3909
+ - All of the black cells must be connected.
3910
+ - Each numbered cell must be part of a white island of connected white cells.
3911
+ - Each island must have the same number of white cells as the number it contains (including the numbered cell).
3912
+ - Two islands may not be connected.
3913
+ - There cannot be any 2x2 blocks of black cells.
3914
+
3915
+ Read more about the history and methods behind nurikabe in the [Wikipedia nurikabe article](https://en.wikipedia.org/wiki/Nurikabe).
3916
+
3917
+ </details>
3918
+
3919
+ **Unsolved puzzle**
3920
+
3921
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/nurikabe_unsolved.png" alt="Nurikabe unsolved" width="500">
3922
+
3923
+ Code to utilize this package and solve the puzzle:
3924
+
3925
+ (Note: the solver also supports random mapping of squares to the neighbors they flip, see the test cases in `tests/test_flip.py` for usage examples)
3926
+
3927
+ ```python
3928
+ import numpy as np
3929
+ from puzzle_solver import nurikabe_solver as solver
3930
+ board = np.array([
3931
+ ['2', ' ', '3', ' ', '3', ' ', ' ', ' ', '3', ' ', ' ', '3', ' ', ' ', ' ', '2', ' ', '2', ' ', ' '],
3932
+ [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
3933
+ [' ', ' ', ' ', ' ', '2', ' ', ' ', '1', ' ', ' ', '1', ' ', '3', ' ', ' ', ' ', '3', ' ', ' ', ' '],
3934
+ ['2', ' ', ' ', '1', ' ', ' ', '3', ' ', ' ', '2', ' ', '2', ' ', ' ', ' ', '1', ' ', ' ', ' ', ' '],
3935
+ [' ', ' ', '2', ' ', '2', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '3', ' ', ' ', ' '],
3936
+ [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '2', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
3937
+ ['1', ' ', ' ', ' ', ' ', '1', ' ', '2', ' ', ' ', '3', ' ', ' ', ' ', ' ', ' ', ' ', '1', ' ', '2'],
3938
+ [' ', '2', ' ', '2', ' ', ' ', '1', ' ', ' ', ' ', ' ', ' ', ' ', '6', ' ', ' ', '2', ' ', ' ', ' '],
3939
+ [' ', ' ', ' ', ' ', ' ', '2', ' ', '7', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '3', ' '],
3940
+ [' ', ' ', '3', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '2', ' ', '2', ' ', '2', ' ', ' ', ' ', ' ', ' '],
3941
+ ['4', ' ', ' ', ' ', ' ', ' ', '7', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
3942
+ [' ', ' ', ' ', ' ', '7', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '3', ' ', ' ', ' ', ' '],
3943
+ [' ', ' ', '2', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '1', ' ', '1', ' ', ' ', ' ', ' ', ' ', '3'],
3944
+ [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '2', ' ', '4', ' ', ' ', '7', ' ', ' ', ' ', ' '],
3945
+ [' ', '1', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
3946
+ [' ', ' ', '2', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '1', ' ', ' '],
3947
+ ['2', ' ', ' ', ' ', ' ', ' ', ' ', '1', ' ', '3', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '2', ' '],
3948
+ [' ', ' ', ' ', '4', ' ', ' ', ' ', ' ', '1', ' ', ' ', ' ', '2', ' ', '1', ' ', '3', ' ', ' ', ' '],
3949
+ [' ', '1', ' ', ' ', ' ', ' ', ' ', '3', ' ', ' ', '1', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '2'],
3950
+ [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '1', ' ', ' ', ' ', ' ', ' '],
3951
+ ])
3952
+ binst = solver.Board(board=board)
3953
+ solutions = binst.solve_and_print()
3954
+ ```
3955
+
3956
+ **Script Output**
3957
+
3958
+ The output tells you which squares to tap to solve the puzzle.
3959
+
3960
+ ```python
3961
+ Solution found
3962
+ 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1
3963
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
3964
+ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
3965
+ 0│ 2 │▒▒▒│ 3 │▒▒▒│ 3 │ │ │▒▒▒│ 3 │ │▒▒▒│ 3 │ │ │▒▒▒│ 2 │▒▒▒│ 2 │ │▒▒▒│
3966
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3967
+ 1│ │▒▒▒│ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│
3968
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3969
+ 2│▒▒▒│▒▒▒│ │▒▒▒│ 2 │ │▒▒▒│ 1 │▒▒▒│▒▒▒│ 1 │▒▒▒│ 3 │ │▒▒▒│▒▒▒│ 3 │ │ │▒▒▒│
3970
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3971
+ 3│ 2 │▒▒▒│▒▒▒│ 1 │▒▒▒│▒▒▒│ 3 │▒▒▒│▒▒▒│ 2 │▒▒▒│ 2 │▒▒▒│ │▒▒▒│ 1 │▒▒▒│▒▒▒│▒▒▒│▒▒▒│
3972
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3973
+ 4│ │▒▒▒│ 2 │▒▒▒│ 2 │▒▒▒│ │ │▒▒▒│ │▒▒▒│ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│ 3 │ │ │▒▒▒│
3974
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3975
+ 5│▒▒▒│▒▒▒│ │▒▒▒│ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│ 2 │▒▒▒│ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│
3976
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3977
+ 6│ 1 │▒▒▒│▒▒▒│▒▒▒│▒▒▒│ 1 │▒▒▒│ 2 │ │▒▒▒│ 3 │▒▒▒│ │▒▒▒│ │ │▒▒▒│ 1 │▒▒▒│ 2 │
3978
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3979
+ 7│▒▒▒│ 2 │▒▒▒│ 2 │▒▒▒│▒▒▒│ 1 │▒▒▒│▒▒▒│▒▒▒│ │ │▒▒▒│ 6 │ │▒▒▒│ 2 │▒▒▒│▒▒▒│ │
3980
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3981
+ 8│▒▒▒│ │▒▒▒│ │▒▒▒│ 2 │▒▒▒│ 7 │ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│ │▒▒▒│▒▒▒│ │▒▒▒│ 3 │▒▒▒│
3982
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3983
+ 9│▒▒▒│▒▒▒│ 3 │▒▒▒│▒▒▒│ │▒▒▒│▒▒▒│ │▒▒▒│ 2 │▒▒▒│ 2 │▒▒▒│ 2 │▒▒▒│▒▒▒│▒▒▒│ │▒▒▒│
3984
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3985
+ 10│ 4 │▒▒▒│ │ │▒▒▒│▒▒▒│ 7 │▒▒▒│ │▒▒▒│ │▒▒▒│ │▒▒▒│ │▒▒▒│ │▒▒▒│ │▒▒▒│
3986
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3987
+ 11│ │▒▒▒│▒▒▒│▒▒▒│ 7 │▒▒▒│ │▒▒▒│ │ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│ 3 │ │▒▒▒│▒▒▒│▒▒▒│
3988
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3989
+ 12│ │▒▒▒│ 2 │▒▒▒│ │▒▒▒│ │▒▒▒│▒▒▒│ │▒▒▒│ 1 │▒▒▒│ 1 │▒▒▒│▒▒▒│▒▒▒│ │▒▒▒│ 3 │
3990
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3991
+ 13│ │▒▒▒│ │▒▒▒│ │▒▒▒│ │ │▒▒▒│▒▒▒│ 2 │▒▒▒│ 4 │▒▒▒│▒▒▒│ 7 │ │ │▒▒▒│ │
3992
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3993
+ 14│▒▒▒│ 1 │▒▒▒│▒▒▒│ │▒▒▒│▒▒▒│ │ │▒▒▒│ │▒▒▒│ │ │▒▒▒│ │▒▒▒│▒▒▒│▒▒▒│ │
3994
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3995
+ 15│▒▒▒│▒▒▒│ 2 │▒▒▒│ │ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│ │▒▒▒│ │▒▒▒│ 1 │▒▒▒│▒▒▒│
3996
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3997
+ 16│ 2 │▒▒▒│ │▒▒▒│▒▒▒│ │▒▒▒│ 1 │▒▒▒│ 3 │ │ │▒▒▒│▒▒▒│▒▒▒│ │▒▒▒│▒▒▒│ 2 │ │
3998
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
3999
+ 17│ │▒▒▒│▒▒▒│ 4 │▒▒▒│▒▒▒│▒▒▒│▒▒▒│ 1 │▒▒▒│▒▒▒│▒▒▒│ 2 │▒▒▒│ 1 │▒▒▒│ 3 │▒▒▒│▒▒▒│▒▒▒│
4000
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
4001
+ 18│▒▒▒│ 1 │▒▒▒│ │ │ │▒▒▒│ 3 │▒▒▒│▒▒▒│ 1 │▒▒▒│ │▒▒▒│▒▒▒│▒▒▒│ │ │▒▒▒│ 2 │
4002
+ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤
4003
+ 19│▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│ │ │▒▒▒│▒▒▒│▒▒▒│▒▒▒│▒▒▒│ 1 │▒▒▒│▒▒▒│▒▒▒│▒▒▒│ │
4004
+ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
4005
+ Solutions found: 1
4006
+ status: OPTIMAL
4007
+ Time taken: 1.62 seconds
4008
+ ```
4009
+
4010
+ **Solved puzzle**
4011
+
4012
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/nurikabe_solved.png" alt="Nurikabe solved" width="500">
4013
+
4014
+ ---
4015
+
3822
4016
  ---
3823
4017
 
3824
4018
  ## Why SAT / CP-SAT?
@@ -3913,3 +4107,5 @@ Issues and PRs welcome!
3913
4107
  [41]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/binairo "puzzle_solver/src/puzzle_solver/puzzles/binairo at master · Ar-Kareem/puzzle_solver · GitHub"
3914
4108
  [42]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/rectangles "puzzle_solver/src/puzzle_solver/puzzles/rectangles at master · Ar-Kareem/puzzle_solver · GitHub"
3915
4109
  [43]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/palisade "puzzle_solver/src/puzzle_solver/puzzles/palisade at master · Ar-Kareem/puzzle_solver · GitHub"
4110
+ [44]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/flip "puzzle_solver/src/puzzle_solver/puzzles/flip at master · Ar-Kareem/puzzle_solver · GitHub"
4111
+ [45]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/nurikabe "puzzle_solver/src/puzzle_solver/puzzles/nurikabe at master · Ar-Kareem/puzzle_solver · GitHub"