multi-puzzle-solver 0.9.24__tar.gz → 0.9.26__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 (107) hide show
  1. {multi_puzzle_solver-0.9.24/src/multi_puzzle_solver.egg-info → multi_puzzle_solver-0.9.26}/PKG-INFO +173 -3
  2. multi_puzzle_solver-0.9.24/PKG-INFO → multi_puzzle_solver-0.9.26/README.md +3959 -3815
  3. multi_puzzle_solver-0.9.24/README.md → multi_puzzle_solver-0.9.26/src/multi_puzzle_solver.egg-info/PKG-INFO +3985 -3789
  4. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/multi_puzzle_solver.egg-info/SOURCES.txt +5 -0
  5. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/__init__.py +3 -1
  6. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/core/utils.py +80 -58
  7. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/core/utils_ortools.py +6 -10
  8. multi_puzzle_solver-0.9.26/src/puzzle_solver/puzzles/flip/flip.py +77 -0
  9. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/lits/lits.py +2 -28
  10. multi_puzzle_solver-0.9.26/src/puzzle_solver/puzzles/palisade/palisade.py +104 -0
  11. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/slitherlink/slitherlink.py +8 -3
  12. multi_puzzle_solver-0.9.26/tests/test_flip.py +73 -0
  13. multi_puzzle_solver-0.9.26/tests/test_palisade.py +157 -0
  14. multi_puzzle_solver-0.9.26/tests/test_utils.py +11 -0
  15. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/pyproject.toml +0 -0
  16. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/setup.cfg +0 -0
  17. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/multi_puzzle_solver.egg-info/dependency_links.txt +0 -0
  18. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/multi_puzzle_solver.egg-info/requires.txt +0 -0
  19. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/multi_puzzle_solver.egg-info/top_level.txt +0 -0
  20. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/aquarium/aquarium.py +0 -0
  21. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/battleships/battleships.py +0 -0
  22. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/binairo/binairo.py +0 -0
  23. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/black_box/black_box.py +0 -0
  24. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/bridges/bridges.py +0 -0
  25. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/chess_range/chess_melee.py +0 -0
  26. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/chess_range/chess_range.py +0 -0
  27. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/chess_range/chess_solo.py +0 -0
  28. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/dominosa/dominosa.py +0 -0
  29. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/filling/filling.py +0 -0
  30. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/galaxies/galaxies.py +0 -0
  31. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/galaxies/parse_map/parse_map.py +0 -0
  32. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/guess/guess.py +0 -0
  33. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/inertia/inertia.py +0 -0
  34. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/inertia/parse_map/parse_map.py +0 -0
  35. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/inertia/tsp.py +0 -0
  36. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/kakurasu/kakurasu.py +0 -0
  37. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/keen/keen.py +0 -0
  38. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/light_up/light_up.py +0 -0
  39. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/magnets/magnets.py +0 -0
  40. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/map/map.py +0 -0
  41. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/minesweeper/minesweeper.py +0 -0
  42. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/mosaic/mosaic.py +0 -0
  43. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/nonograms/nonograms.py +0 -0
  44. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/norinori/norinori.py +0 -0
  45. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/pearl/pearl.py +0 -0
  46. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/range/range.py +0 -0
  47. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/rectangles/rectangles.py +0 -0
  48. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/signpost/signpost.py +0 -0
  49. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/singles/singles.py +0 -0
  50. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/slant/parse_map/parse_map.py +0 -0
  51. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/slant/slant.py +0 -0
  52. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/star_battle/star_battle.py +0 -0
  53. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/star_battle/star_battle_shapeless.py +0 -0
  54. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/stitches/parse_map/parse_map.py +0 -0
  55. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/stitches/stitches.py +0 -0
  56. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/sudoku/sudoku.py +0 -0
  57. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/tents/tents.py +0 -0
  58. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/thermometers/thermometers.py +0 -0
  59. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/towers/towers.py +0 -0
  60. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/tracks/tracks.py +0 -0
  61. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/undead/undead.py +0 -0
  62. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/unequal/unequal.py +0 -0
  63. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/unruly/unruly.py +0 -0
  64. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/yin_yang/parse_map/parse_map.py +0 -0
  65. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/puzzles/yin_yang/yin_yang.py +0 -0
  66. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/src/puzzle_solver/utils/visualizer.py +0 -0
  67. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_aquarium.py +0 -0
  68. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_battleships.py +0 -0
  69. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_binairo.py +0 -0
  70. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_black_box.py +0 -0
  71. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_bridges.py +0 -0
  72. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_chess_melee.py +0 -0
  73. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_chess_range.py +0 -0
  74. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_chess_solo.py +0 -0
  75. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_dominosa.py +0 -0
  76. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_filling.py +0 -0
  77. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_galaxies.py +0 -0
  78. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_guess.py +0 -0
  79. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_inertia.py +0 -0
  80. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_kakurasu.py +0 -0
  81. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_keen.py +0 -0
  82. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_light_up.py +0 -0
  83. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_lits.py +0 -0
  84. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_magnets.py +0 -0
  85. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_map.py +0 -0
  86. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_minesweeper.py +0 -0
  87. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_mosaic.py +0 -0
  88. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_nonograms.py +0 -0
  89. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_norinori.py +0 -0
  90. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_pearl.py +0 -0
  91. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_range.py +0 -0
  92. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_rectangles.py +0 -0
  93. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_signpost.py +0 -0
  94. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_singles.py +0 -0
  95. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_slant.py +0 -0
  96. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_slitherlink.py +0 -0
  97. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_star_battle.py +0 -0
  98. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_stitches.py +0 -0
  99. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_sudoku.py +0 -0
  100. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_tents.py +0 -0
  101. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_thermometers.py +0 -0
  102. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_towers.py +0 -0
  103. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_tracks.py +0 -0
  104. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_undead.py +0 -0
  105. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_unequal.py +0 -0
  106. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/tests/test_unruly.py +0 -0
  107. {multi_puzzle_solver-0.9.24 → multi_puzzle_solver-0.9.26}/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.24
3
+ Version: 0.9.26
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
@@ -326,6 +326,16 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
326
326
  <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/rectangles_solved.png" alt="Rectangles" width="140">
327
327
  </a>
328
328
  </td>
329
+ <td align="center">
330
+ <a href="#palisade-puzzle-type-43"><b>Palisade</b><br><br>
331
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/palisade_solved.png" alt="Palisade" width="140">
332
+ </a>
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>
329
339
  </tr>
330
340
  </table>
331
341
 
@@ -383,6 +393,8 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
383
393
  - [Yin-Yang (Puzzle Type #40)](#yin-yang-puzzle-type-40)
384
394
  - [Binairo (Puzzle Type #41)](#binairo-puzzle-type-41)
385
395
  - [Rectangles (Puzzle Type #42)](#rectangles-puzzle-type-42)
396
+ - [Palisade (Puzzle Type #43)](#palisade-puzzle-type-43)
397
+ - [Flip (Puzzle Type #44)](#flip-puzzle-type-44)
386
398
  - [Why SAT / CP-SAT?](#why-sat--cp-sat)
387
399
  - [Testing](#testing)
388
400
  - [Contributing](#contributing)
@@ -3317,9 +3329,13 @@ Applying the solution to the puzzle visually:
3317
3329
 
3318
3330
  ## Slitherlink (Puzzle Type #39)
3319
3331
 
3320
- Also known as Fences and Loop the Loop
3332
+ Also known as Fences, Loop the Loop, and Loopy
3321
3333
 
3322
- * [**Play online**](https://www.puzzle-loop.com)
3334
+ * [**Play online 1**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/js/loopy.html)
3335
+
3336
+ * [**Play online 2**](https://www.puzzle-loop.com)
3337
+
3338
+ * [**Instructions**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/doc/loopy.html#loopy)
3323
3339
 
3324
3340
  * [**Solver Code**][39]
3325
3341
 
@@ -3720,6 +3736,158 @@ Applying the solution to the puzzle visually:
3720
3736
 
3721
3737
  ---
3722
3738
 
3739
+ ## Palisade (Puzzle Type #43)
3740
+
3741
+ * [**Play online**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/js/palisade.html)
3742
+
3743
+ * [**Instructions**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/doc/palisade.html#palisade)
3744
+
3745
+ * [**Solver Code**][43]
3746
+
3747
+ <details>
3748
+ <summary><strong>Rules</strong></summary>
3749
+
3750
+ You're given a grid of N squares and a region size M, some of which contain numbers. Your goal is to subdivide the grid into (N/M) contiguous regions, where every region is of size M, such that each square containing a number is adjacent to exactly that many edges (including those between the inside and the outside of the grid).
3751
+
3752
+ </details>
3753
+
3754
+ **Unsolved puzzle**
3755
+
3756
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/palisade_unsolved.png" alt="Palisade unsolved" width="500">
3757
+
3758
+ Code to utilize this package and solve the puzzle:
3759
+
3760
+ (Note: it takes a few seconds for the model to be built if the region size is larger than 8 and around 10 seconds for a region size of 10)
3761
+
3762
+ ```python
3763
+ import numpy as np
3764
+ from puzzle_solver import palisade_solver as solver
3765
+ board = np.array([
3766
+ ['2', ' ', ' ', ' ', ' ', '3', ' ', ' ', '1', '1', '3', ' ', ' ', ' ', ' '],
3767
+ ['3', '2', '1', ' ', '2', '3', ' ', ' ', ' ', ' ', ' ', '2', ' ', '0', ' '],
3768
+ [' ', ' ', ' ', '1', '1', ' ', ' ', '1', ' ', ' ', ' ', '1', ' ', ' ', ' '],
3769
+ [' ', '3', '2', ' ', ' ', ' ', ' ', '2', '3', ' ', ' ', ' ', '1', ' ', ' '],
3770
+ [' ', '0', '1', ' ', '2', ' ', ' ', '0', ' ', ' ', ' ', '1', ' ', '3', '2'],
3771
+ ['1', '0', ' ', ' ', ' ', '2', '2', ' ', '2', ' ', '3', ' ', '0', '2', ' '],
3772
+ [' ', ' ', ' ', ' ', ' ', '3', ' ', ' ', ' ', '2', ' ', ' ', ' ', ' ', ' '],
3773
+ [' ', '1', ' ', ' ', ' ', '3', '1', ' ', '1', ' ', ' ', ' ', ' ', '1', ' '],
3774
+ [' ', ' ', ' ', '0', ' ', ' ', '0', ' ', ' ', '1', '2', ' ', ' ', ' ', '3'],
3775
+ [' ', ' ', ' ', ' ', ' ', ' ', '1', ' ', ' ', '2', ' ', ' ', '1', '2', '1'],
3776
+ [' ', ' ', ' ', ' ', '1', ' ', '2', '3', '1', ' ', ' ', ' ', '2', ' ', '1'],
3777
+ ['2', ' ', '1', ' ', '2', '2', '1', ' ', ' ', '2', ' ', ' ', ' ', ' ', ' '],
3778
+ ])
3779
+ binst = solver.Board(board, region_size=10)
3780
+ solutions = binst.solve_and_print()
3781
+ ```
3782
+
3783
+ **Script Output**
3784
+
3785
+ ```python
3786
+ Solution found
3787
+ 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
3788
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
3789
+ ┌───────────────────┬───────────────────────┬───────────────┐
3790
+ 0│ 2 · · · · │ 3 · · 1 1 3 │ · · · · │
3791
+ │ ┌───────────┐ ├───────┬───┐ ┌───┴───┐ │
3792
+ 1│ 3 │ 2 1 · │ 2 │ 3 · │ · │ · · │ · 2 │ · 0 · │
3793
+ ├───┘ │ └───┐ │ └───┐ └───┐ └───┐ │
3794
+ 2│ · · · 1 │ 1 · │ · │ 1 · │ · · │ 1 · │ · · │
3795
+ │ ┌───┐ │ ┌───┘ │ ┌───┴───────┘ └───┐ │
3796
+ 3│ · │ 3 │ 2 · │ · │ · · │ 2 │ 3 · · · 1 · │ · │
3797
+ ├───┘ └───────┼───┘ ┌───┘ └───┬───────────────┬───┴───┤
3798
+ 4│ · 0 1 · │ 2 · │ · 0 · │ · · 1 · │ 3 2 │
3799
+ │ ┌───┘ │ │ ┌───┐ └───┐ │
3800
+ 5│ 1 0 · │ · · 2 │ 2 · 2 │ · │ 3 │ · 0 2 │ · │
3801
+ │ ┌───┴───────────┼───┬───────┴───┤ ├───┐ │ │
3802
+ 6│ · · │ · · · 3 │ · │ · · 2 │ · │ · │ · · │ · │
3803
+ ├───────┘ ┌───────────┤ └───┐ │ │ └───────┘ │
3804
+ 7│ · 1 · │ · · 3 │ 1 · │ 1 · │ · │ · · 1 · │
3805
+ │ ┌───┘ ┌───┘ │ │ └───────┐ ┌───┤
3806
+ 8│ · · │ · 0 · │ · 0 · │ · 1 │ 2 · · │ · │ 3 │
3807
+ │ ┌───┘ ┌───┤ ├───┐ └───┐ ├───┘ │
3808
+ 9│ · │ · · · │ · │ · 1 · │ · │ 2 · │ · 1 │ 2 1 │
3809
+ ├───┤ ┌───────┘ ├───────┐ │ └───┐ │ │ │
3810
+ 10│ · │ · │ · · 1 │ · 2 │ 3 │ 1 · │ · │ · 2 │ · 1 │
3811
+ │ └───┘ │ └───┘ ├───┴───────┘ │
3812
+ 11│ 2 · 1 · 2 │ 2 1 · · 2 │ · · · · · │
3813
+ └───────────────────┴───────────────────┴───────────────────┘
3814
+ Solutions found: 1
3815
+ status: OPTIMAL
3816
+ Time taken: 11.94 seconds
3817
+ ```
3818
+
3819
+ **Solved puzzle**
3820
+
3821
+ Applying the solution to the puzzle visually:
3822
+
3823
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/palisade_solved.png" alt="Palisade solved" width="500">
3824
+
3825
+ ---
3826
+
3827
+ ## Flip (Puzzle Type #44)
3828
+
3829
+ * [**Play online**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/js/flip.html)
3830
+
3831
+ * [**Instructions**](https://www.chiark.greenend.org.uk/~sgtatham/puzzles/doc/flip.html#flip)
3832
+
3833
+ * [**Solver Code**][44]
3834
+
3835
+ <details>
3836
+ <summary><strong>Rules</strong></summary>
3837
+
3838
+ 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.
3839
+
3840
+ </details>
3841
+
3842
+ **Unsolved puzzle**
3843
+
3844
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/flip_unsolved.png" alt="Flip unsolved" width="500">
3845
+
3846
+ Code to utilize this package and solve the puzzle:
3847
+
3848
+ (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)
3849
+
3850
+ ```python
3851
+ import numpy as np
3852
+ from puzzle_solver import flip_solver as solver
3853
+ board = np.array([
3854
+ ['B', 'W', 'W', 'W', 'W', 'W', 'W'],
3855
+ ['B', 'B', 'W', 'W', 'W', 'B', 'B'],
3856
+ ['W', 'B', 'W', 'W', 'B', 'B', 'W'],
3857
+ ['B', 'B', 'B', 'W', 'W', 'B', 'W'],
3858
+ ['W', 'W', 'B', 'B', 'W', 'B', 'W'],
3859
+ ['B', 'W', 'B', 'B', 'W', 'W', 'W'],
3860
+ ['B', 'W', 'B', 'W', 'W', 'B', 'B'],
3861
+ ])
3862
+ binst = solver.Board(board=board)
3863
+ solutions = binst.solve_and_print()
3864
+ ```
3865
+
3866
+ **Script Output**
3867
+
3868
+ The output tells you which squares to tap to solve the puzzle.
3869
+
3870
+ ```python
3871
+ Solution found
3872
+ [['T' ' ' 'T' 'T' 'T' ' ' ' ']
3873
+ [' ' ' ' ' ' 'T' ' ' 'T' ' ']
3874
+ [' ' 'T' ' ' ' ' 'T' ' ' ' ']
3875
+ ['T' ' ' 'T' ' ' ' ' 'T' ' ']
3876
+ [' ' ' ' ' ' 'T' ' ' ' ' 'T']
3877
+ ['T' ' ' 'T' ' ' 'T' 'T' 'T']
3878
+ [' ' ' ' ' ' ' ' ' ' 'T' 'T']]
3879
+ Solutions found: 1
3880
+ status: OPTIMAL
3881
+ ```
3882
+
3883
+ **Solved puzzle**
3884
+
3885
+ This picture won't mean much as the game is about the sequence of moves not the final frame as shown here.
3886
+
3887
+ <img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/flip_solved.png" alt="Flip solved" width="500">
3888
+
3889
+ ---
3890
+
3723
3891
  ---
3724
3892
 
3725
3893
  ## Why SAT / CP-SAT?
@@ -3813,3 +3981,5 @@ Issues and PRs welcome!
3813
3981
  [40]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/yin_yang "puzzle_solver/src/puzzle_solver/puzzles/yin_yang at master · Ar-Kareem/puzzle_solver · GitHub"
3814
3982
  [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"
3815
3983
  [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"
3984
+ [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"
3985
+ [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"