multi-puzzle-solver 0.9.8__tar.gz → 0.9.9__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.
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/PKG-INFO +107 -31
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/README.md +106 -30
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/multi_puzzle_solver.egg-info/PKG-INFO +107 -31
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/multi_puzzle_solver.egg-info/SOURCES.txt +1 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/__init__.py +2 -1
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/star_battle/star_battle.py +16 -8
- multi_puzzle_solver-0.9.9/src/puzzle_solver/puzzles/star_battle/star_battle_shapeless.py +7 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_star_battle.py +21 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/pyproject.toml +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/setup.cfg +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/multi_puzzle_solver.egg-info/dependency_links.txt +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/multi_puzzle_solver.egg-info/requires.txt +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/multi_puzzle_solver.egg-info/top_level.txt +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/core/utils.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/core/utils_ortools.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/aquarium/aquarium.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/battleships/battleships.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/bridges/bridges.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/chess_range/chess_melee.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/chess_range/chess_range.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/chess_range/chess_solo.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/dominosa/dominosa.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/filling/filling.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/guess/guess.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/inertia/inertia.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/inertia/parse_map/parse_map.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/inertia/tsp.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/kakurasu/kakurasu.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/keen/keen.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/light_up/light_up.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/magnets/magnets.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/map/map.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/minesweeper/minesweeper.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/mosaic/mosaic.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/nonograms/nonograms.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/pearl/pearl.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/range/range.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/signpost/signpost.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/singles/singles.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/stitches/parse_map/parse_map.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/stitches/stitches.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/sudoku/sudoku.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/tents/tents.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/thermometers/thermometers.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/towers/towers.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/tracks/tracks.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/undead/undead.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/unruly/unruly.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/utils/visualizer.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_aquarium.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_battleships.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_bridges.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_chess_melee.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_chess_range.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_chess_solo.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_dominosa.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_filling.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_guess.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_inertia.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_kakurasu.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_keen.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_light_up.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_magnets.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_map.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_minesweeper.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_mosaic.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_nonograms.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_pearl.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_range.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_signpost.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_singles.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_stitches.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_sudoku.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_tents.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_thermometers.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_towers.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_tracks.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_undead.py +0 -0
- {multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/tests/test_unruly.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: multi-puzzle-solver
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.9
|
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
|
@@ -254,6 +254,11 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
|
|
254
254
|
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_solved.png" alt="Star Battle" width="140">
|
255
255
|
</a>
|
256
256
|
</td>
|
257
|
+
<td align="center">
|
258
|
+
<a href="#star-battle-shapeless-puzzle-type-32"><b>Star Battle Shapeless</b><br><br>
|
259
|
+
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_shapeless_solved.png" alt="Star Battle Shapeless" width="140">
|
260
|
+
</a>
|
261
|
+
</td>
|
257
262
|
</tr>
|
258
263
|
</table>
|
259
264
|
|
@@ -300,6 +305,7 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
|
|
300
305
|
- [Battleships (Puzzle Type #29)](#battleships-puzzle-type-29)
|
301
306
|
- [Kakurasu (Puzzle Type #30)](#kakurasu-puzzle-type-30)
|
302
307
|
- [Star Battle (Puzzle Type #31)](#star-battle-puzzle-type-31)
|
308
|
+
- [Star Battle Shapeless (Puzzle Type #32)](#star-battle-shapeless-puzzle-type-32)
|
303
309
|
- [Why SAT / CP-SAT?](#why-sat--cp-sat)
|
304
310
|
- [Testing](#testing)
|
305
311
|
- [Contributing](#contributing)
|
@@ -2536,39 +2542,39 @@ Time taken: 0.00 seconds
|
|
2536
2542
|
|
2537
2543
|
Code to utilize this package and solve the puzzle:
|
2538
2544
|
|
2539
|
-
Note that as usual the board is an id of the shape (id is meaningless, just used to identify one shape), and the star_count parameter depenends on the puzzle type.
|
2545
|
+
Note that as usual the board is an id of the shape (id is meaningless, just used to identify one shape), and the `star_count` parameter depenends on the puzzle type.
|
2540
2546
|
|
2541
2547
|
```python
|
2542
2548
|
from puzzle_solver import star_battle_solver as solver
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
|
2554
|
-
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
2560
|
-
|
2561
|
-
|
2562
|
-
|
2563
|
-
|
2564
|
-
|
2565
|
-
|
2566
|
-
|
2567
|
-
|
2568
|
-
|
2569
|
-
|
2570
|
-
|
2571
|
-
|
2549
|
+
board = np.array([
|
2550
|
+
['00', '00', '00', '00', '00', '01', '01', '01', '01', '01', '01', '01', '01', '01', '02', '02', '02', '03', '03', '03', '03', '03', '03', '03', '03'],
|
2551
|
+
['00', '01', '00', '01', '01', '01', '01', '01', '01', '01', '04', '04', '01', '02', '02', '02', '02', '05', '05', '05', '05', '05', '05', '03', '03'],
|
2552
|
+
['00', '01', '01', '01', '01', '01', '01', '01', '01', '04', '04', '04', '04', '04', '02', '02', '05', '05', '05', '05', '05', '05', '03', '03', '03'],
|
2553
|
+
['00', '01', '06', '04', '04', '04', '04', '04', '04', '04', '04', '04', '04', '04', '02', '05', '05', '05', '05', '05', '05', '05', '03', '07', '03'],
|
2554
|
+
['00', '01', '06', '06', '06', '06', '06', '06', '06', '04', '04', '04', '04', '02', '02', '02', '02', '02', '05', '05', '05', '05', '05', '07', '03'],
|
2555
|
+
['00', '00', '08', '06', '09', '09', '09', '09', '06', '04', '04', '04', '04', '02', '02', '02', '02', '02', '05', '05', '05', '05', '07', '07', '07'],
|
2556
|
+
['00', '08', '08', '08', '08', '09', '09', '06', '06', '06', '04', '04', '04', '04', '02', '02', '02', '05', '05', '05', '07', '07', '07', '07', '07'],
|
2557
|
+
['00', '00', '08', '08', '08', '09', '09', '09', '09', '06', '10', '10', '10', '10', '02', '02', '02', '05', '11', '11', '11', '11', '07', '07', '07'],
|
2558
|
+
['08', '08', '08', '08', '09', '09', '09', '09', '09', '09', '10', '10', '10', '02', '02', '02', '02', '11', '11', '11', '11', '11', '11', '07', '11'],
|
2559
|
+
['08', '08', '08', '08', '09', '09', '09', '09', '09', '10', '10', '10', '10', '02', '02', '02', '11', '11', '11', '11', '11', '11', '11', '07', '11'],
|
2560
|
+
['08', '08', '08', '09', '09', '09', '09', '09', '10', '10', '10', '10', '10', '12', '12', '12', '12', '11', '11', '11', '11', '11', '11', '11', '11'],
|
2561
|
+
['08', '08', '09', '09', '09', '09', '09', '08', '10', '10', '10', '10', '10', '10', '10', '10', '12', '11', '11', '11', '11', '13', '11', '13', '11'],
|
2562
|
+
['14', '08', '08', '08', '08', '08', '08', '08', '10', '10', '10', '10', '10', '12', '12', '12', '12', '12', '11', '11', '11', '13', '11', '13', '15'],
|
2563
|
+
['14', '14', '14', '14', '16', '08', '16', '16', '17', '10', '10', '10', '10', '10', '10', '10', '10', '12', '13', '13', '13', '13', '13', '13', '15'],
|
2564
|
+
['14', '14', '14', '14', '16', '16', '16', '16', '17', '10', '10', '18', '18', '10', '19', '10', '12', '12', '13', '15', '15', '15', '15', '15', '15'],
|
2565
|
+
['14', '14', '14', '14', '14', '16', '16', '17', '17', '18', '18', '18', '19', '19', '19', '10', '10', '10', '13', '15', '15', '15', '15', '15', '15'],
|
2566
|
+
['14', '14', '14', '16', '16', '16', '16', '17', '18', '18', '20', '20', '19', '21', '19', '19', '19', '19', '13', '15', '15', '15', '15', '15', '15'],
|
2567
|
+
['14', '16', '16', '16', '16', '16', '16', '17', '18', '18', '20', '21', '21', '21', '21', '19', '21', '19', '15', '15', '21', '15', '15', '15', '15'],
|
2568
|
+
['14', '14', '14', '16', '16', '17', '17', '17', '18', '20', '20', '21', '20', '21', '21', '19', '21', '19', '15', '21', '21', '15', '15', '15', '15'],
|
2569
|
+
['14', '14', '14', '16', '16', '16', '17', '17', '18', '18', '20', '20', '20', '20', '21', '21', '21', '21', '21', '21', '15', '15', '22', '22', '15'],
|
2570
|
+
['14', '14', '14', '14', '23', '16', '17', '20', '18', '20', '20', '20', '20', '20', '20', '21', '24', '24', '24', '21', '15', '15', '22', '15', '15'],
|
2571
|
+
['14', '14', '14', '14', '23', '20', '17', '20', '18', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '21', '15', '22', '22', '22', '15'],
|
2572
|
+
['14', '23', '23', '14', '23', '20', '20', '20', '18', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24', '22', '15'],
|
2573
|
+
['14', '23', '14', '14', '23', '20', '23', '20', '18', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '24', '22', '22', '22', '22', '22'],
|
2574
|
+
['14', '23', '23', '23', '23', '23', '23', '20', '20', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24']
|
2575
|
+
])
|
2576
|
+
binst = solver.Board(board=board, star_count=6)
|
2577
|
+
solutions = binst.solve_and_print()
|
2572
2578
|
```
|
2573
2579
|
|
2574
2580
|
|
@@ -2612,6 +2618,75 @@ Time taken: 0.38 seconds
|
|
2612
2618
|
|
2613
2619
|
---
|
2614
2620
|
|
2621
|
+
## Star Battle Shapeless (Puzzle Type #32)
|
2622
|
+
|
2623
|
+
* [**Play online**](https://www.puzzle-star-battle.com/?size=14)
|
2624
|
+
|
2625
|
+
* [**Solver Code**][32]
|
2626
|
+
|
2627
|
+
<details>
|
2628
|
+
<summary><strong>Rules</strong></summary>
|
2629
|
+
|
2630
|
+
You have to place stars on the grid according to the rules:
|
2631
|
+
- 2 stars cannot be adjacent horizontally, vertically or diagonally.
|
2632
|
+
- For 1★ puzzles, you have to place 1 star on each row and column.
|
2633
|
+
- For 2★ puzzles, the stars per row and column must be 2 etc.
|
2634
|
+
- Some places begin with a black square and cannot have stars placed on them.
|
2635
|
+
|
2636
|
+
</details>
|
2637
|
+
|
2638
|
+
**Unsolved puzzle**
|
2639
|
+
|
2640
|
+
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_shapeless_unsolved.png" alt="Star Battle Shapeless unsolved" width="500">
|
2641
|
+
|
2642
|
+
Code to utilize this package and solve the puzzle:
|
2643
|
+
|
2644
|
+
The `star_count` parameter depenends on the puzzle type.
|
2645
|
+
|
2646
|
+
```python
|
2647
|
+
from puzzle_solver import star_battle_shapeless_solver as shapeless_solver
|
2648
|
+
board = np.array([
|
2649
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
2650
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
2651
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'B', ' '],
|
2652
|
+
['B', 'B', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
2653
|
+
['B', 'B', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
2654
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
2655
|
+
[' ', ' ', ' ', ' ', 'B', ' ', ' ', ' ', 'B', ' '],
|
2656
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', 'B', 'B', ' '],
|
2657
|
+
['B', 'B', ' ', ' ', ' ', ' ', 'B', 'B', 'B', ' '],
|
2658
|
+
['B', ' ', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
2659
|
+
])
|
2660
|
+
binst = shapeless_solver.Board(board=board, star_count=2)
|
2661
|
+
solutions = binst.solve_and_print()
|
2662
|
+
```
|
2663
|
+
|
2664
|
+
|
2665
|
+
**Script Output**
|
2666
|
+
|
2667
|
+
```python
|
2668
|
+
Solution found
|
2669
|
+
['*', ' ', ' ', ' ', '*', ' ', ' ', ' ', ' ', ' '],
|
2670
|
+
[' ', ' ', ' ', ' ', ' ', ' ', '*', ' ', '*', ' '],
|
2671
|
+
[' ', ' ', '*', ' ', '*', ' ', ' ', ' ', ' ', ' '],
|
2672
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', '*', ' ', '*'],
|
2673
|
+
[' ', ' ', '*', ' ', ' ', '*', ' ', ' ', ' ', ' '],
|
2674
|
+
['*', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '*', ' '],
|
2675
|
+
[' ', ' ', ' ', '*', ' ', ' ', '*', ' ', ' ', ' '],
|
2676
|
+
[' ', '*', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '*'],
|
2677
|
+
[' ', ' ', ' ', '*', ' ', '*', ' ', ' ', ' ', ' '],
|
2678
|
+
[' ', '*', ' ', ' ', ' ', ' ', ' ', '*', ' ', ' ']
|
2679
|
+
Solutions found: 1
|
2680
|
+
status: OPTIMAL
|
2681
|
+
Time taken: 0.02 seconds
|
2682
|
+
```
|
2683
|
+
|
2684
|
+
**Solved puzzle**
|
2685
|
+
|
2686
|
+
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_shapeless_solved.png" alt="Star Battle Shapeless solved" width="500">
|
2687
|
+
|
2688
|
+
---
|
2689
|
+
|
2615
2690
|
---
|
2616
2691
|
|
2617
2692
|
## Why SAT / CP-SAT?
|
@@ -2694,3 +2769,4 @@ Issues and PRs welcome!
|
|
2694
2769
|
[29]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/battleships "puzzle_solver/src/puzzle_solver/puzzles/battleships at master · Ar-Kareem/puzzle_solver · GitHub"
|
2695
2770
|
[30]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/kakurasu "puzzle_solver/src/puzzle_solver/puzzles/kakurasu at master · Ar-Kareem/puzzle_solver · GitHub"
|
2696
2771
|
[31]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/star_battle "puzzle_solver/src/puzzle_solver/puzzles/star_battle at master · Ar-Kareem/puzzle_solver · GitHub"
|
2772
|
+
[32]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/star_battle_shapeless "puzzle_solver/src/puzzle_solver/puzzles/star_battle_shapeless at master · Ar-Kareem/puzzle_solver · GitHub"
|
@@ -228,6 +228,11 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
|
|
228
228
|
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_solved.png" alt="Star Battle" width="140">
|
229
229
|
</a>
|
230
230
|
</td>
|
231
|
+
<td align="center">
|
232
|
+
<a href="#star-battle-shapeless-puzzle-type-32"><b>Star Battle Shapeless</b><br><br>
|
233
|
+
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_shapeless_solved.png" alt="Star Battle Shapeless" width="140">
|
234
|
+
</a>
|
235
|
+
</td>
|
231
236
|
</tr>
|
232
237
|
</table>
|
233
238
|
|
@@ -274,6 +279,7 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
|
|
274
279
|
- [Battleships (Puzzle Type #29)](#battleships-puzzle-type-29)
|
275
280
|
- [Kakurasu (Puzzle Type #30)](#kakurasu-puzzle-type-30)
|
276
281
|
- [Star Battle (Puzzle Type #31)](#star-battle-puzzle-type-31)
|
282
|
+
- [Star Battle Shapeless (Puzzle Type #32)](#star-battle-shapeless-puzzle-type-32)
|
277
283
|
- [Why SAT / CP-SAT?](#why-sat--cp-sat)
|
278
284
|
- [Testing](#testing)
|
279
285
|
- [Contributing](#contributing)
|
@@ -2510,39 +2516,39 @@ Time taken: 0.00 seconds
|
|
2510
2516
|
|
2511
2517
|
Code to utilize this package and solve the puzzle:
|
2512
2518
|
|
2513
|
-
Note that as usual the board is an id of the shape (id is meaningless, just used to identify one shape), and the star_count parameter depenends on the puzzle type.
|
2519
|
+
Note that as usual the board is an id of the shape (id is meaningless, just used to identify one shape), and the `star_count` parameter depenends on the puzzle type.
|
2514
2520
|
|
2515
2521
|
```python
|
2516
2522
|
from puzzle_solver import star_battle_solver as solver
|
2517
|
-
|
2518
|
-
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
2522
|
-
|
2523
|
-
|
2524
|
-
|
2525
|
-
|
2526
|
-
|
2527
|
-
|
2528
|
-
|
2529
|
-
|
2530
|
-
|
2531
|
-
|
2532
|
-
|
2533
|
-
|
2534
|
-
|
2535
|
-
|
2536
|
-
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2542
|
-
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2523
|
+
board = np.array([
|
2524
|
+
['00', '00', '00', '00', '00', '01', '01', '01', '01', '01', '01', '01', '01', '01', '02', '02', '02', '03', '03', '03', '03', '03', '03', '03', '03'],
|
2525
|
+
['00', '01', '00', '01', '01', '01', '01', '01', '01', '01', '04', '04', '01', '02', '02', '02', '02', '05', '05', '05', '05', '05', '05', '03', '03'],
|
2526
|
+
['00', '01', '01', '01', '01', '01', '01', '01', '01', '04', '04', '04', '04', '04', '02', '02', '05', '05', '05', '05', '05', '05', '03', '03', '03'],
|
2527
|
+
['00', '01', '06', '04', '04', '04', '04', '04', '04', '04', '04', '04', '04', '04', '02', '05', '05', '05', '05', '05', '05', '05', '03', '07', '03'],
|
2528
|
+
['00', '01', '06', '06', '06', '06', '06', '06', '06', '04', '04', '04', '04', '02', '02', '02', '02', '02', '05', '05', '05', '05', '05', '07', '03'],
|
2529
|
+
['00', '00', '08', '06', '09', '09', '09', '09', '06', '04', '04', '04', '04', '02', '02', '02', '02', '02', '05', '05', '05', '05', '07', '07', '07'],
|
2530
|
+
['00', '08', '08', '08', '08', '09', '09', '06', '06', '06', '04', '04', '04', '04', '02', '02', '02', '05', '05', '05', '07', '07', '07', '07', '07'],
|
2531
|
+
['00', '00', '08', '08', '08', '09', '09', '09', '09', '06', '10', '10', '10', '10', '02', '02', '02', '05', '11', '11', '11', '11', '07', '07', '07'],
|
2532
|
+
['08', '08', '08', '08', '09', '09', '09', '09', '09', '09', '10', '10', '10', '02', '02', '02', '02', '11', '11', '11', '11', '11', '11', '07', '11'],
|
2533
|
+
['08', '08', '08', '08', '09', '09', '09', '09', '09', '10', '10', '10', '10', '02', '02', '02', '11', '11', '11', '11', '11', '11', '11', '07', '11'],
|
2534
|
+
['08', '08', '08', '09', '09', '09', '09', '09', '10', '10', '10', '10', '10', '12', '12', '12', '12', '11', '11', '11', '11', '11', '11', '11', '11'],
|
2535
|
+
['08', '08', '09', '09', '09', '09', '09', '08', '10', '10', '10', '10', '10', '10', '10', '10', '12', '11', '11', '11', '11', '13', '11', '13', '11'],
|
2536
|
+
['14', '08', '08', '08', '08', '08', '08', '08', '10', '10', '10', '10', '10', '12', '12', '12', '12', '12', '11', '11', '11', '13', '11', '13', '15'],
|
2537
|
+
['14', '14', '14', '14', '16', '08', '16', '16', '17', '10', '10', '10', '10', '10', '10', '10', '10', '12', '13', '13', '13', '13', '13', '13', '15'],
|
2538
|
+
['14', '14', '14', '14', '16', '16', '16', '16', '17', '10', '10', '18', '18', '10', '19', '10', '12', '12', '13', '15', '15', '15', '15', '15', '15'],
|
2539
|
+
['14', '14', '14', '14', '14', '16', '16', '17', '17', '18', '18', '18', '19', '19', '19', '10', '10', '10', '13', '15', '15', '15', '15', '15', '15'],
|
2540
|
+
['14', '14', '14', '16', '16', '16', '16', '17', '18', '18', '20', '20', '19', '21', '19', '19', '19', '19', '13', '15', '15', '15', '15', '15', '15'],
|
2541
|
+
['14', '16', '16', '16', '16', '16', '16', '17', '18', '18', '20', '21', '21', '21', '21', '19', '21', '19', '15', '15', '21', '15', '15', '15', '15'],
|
2542
|
+
['14', '14', '14', '16', '16', '17', '17', '17', '18', '20', '20', '21', '20', '21', '21', '19', '21', '19', '15', '21', '21', '15', '15', '15', '15'],
|
2543
|
+
['14', '14', '14', '16', '16', '16', '17', '17', '18', '18', '20', '20', '20', '20', '21', '21', '21', '21', '21', '21', '15', '15', '22', '22', '15'],
|
2544
|
+
['14', '14', '14', '14', '23', '16', '17', '20', '18', '20', '20', '20', '20', '20', '20', '21', '24', '24', '24', '21', '15', '15', '22', '15', '15'],
|
2545
|
+
['14', '14', '14', '14', '23', '20', '17', '20', '18', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '21', '15', '22', '22', '22', '15'],
|
2546
|
+
['14', '23', '23', '14', '23', '20', '20', '20', '18', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24', '22', '15'],
|
2547
|
+
['14', '23', '14', '14', '23', '20', '23', '20', '18', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '24', '22', '22', '22', '22', '22'],
|
2548
|
+
['14', '23', '23', '23', '23', '23', '23', '20', '20', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24']
|
2549
|
+
])
|
2550
|
+
binst = solver.Board(board=board, star_count=6)
|
2551
|
+
solutions = binst.solve_and_print()
|
2546
2552
|
```
|
2547
2553
|
|
2548
2554
|
|
@@ -2586,6 +2592,75 @@ Time taken: 0.38 seconds
|
|
2586
2592
|
|
2587
2593
|
---
|
2588
2594
|
|
2595
|
+
## Star Battle Shapeless (Puzzle Type #32)
|
2596
|
+
|
2597
|
+
* [**Play online**](https://www.puzzle-star-battle.com/?size=14)
|
2598
|
+
|
2599
|
+
* [**Solver Code**][32]
|
2600
|
+
|
2601
|
+
<details>
|
2602
|
+
<summary><strong>Rules</strong></summary>
|
2603
|
+
|
2604
|
+
You have to place stars on the grid according to the rules:
|
2605
|
+
- 2 stars cannot be adjacent horizontally, vertically or diagonally.
|
2606
|
+
- For 1★ puzzles, you have to place 1 star on each row and column.
|
2607
|
+
- For 2★ puzzles, the stars per row and column must be 2 etc.
|
2608
|
+
- Some places begin with a black square and cannot have stars placed on them.
|
2609
|
+
|
2610
|
+
</details>
|
2611
|
+
|
2612
|
+
**Unsolved puzzle**
|
2613
|
+
|
2614
|
+
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_shapeless_unsolved.png" alt="Star Battle Shapeless unsolved" width="500">
|
2615
|
+
|
2616
|
+
Code to utilize this package and solve the puzzle:
|
2617
|
+
|
2618
|
+
The `star_count` parameter depenends on the puzzle type.
|
2619
|
+
|
2620
|
+
```python
|
2621
|
+
from puzzle_solver import star_battle_shapeless_solver as shapeless_solver
|
2622
|
+
board = np.array([
|
2623
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
2624
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
2625
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'B', ' '],
|
2626
|
+
['B', 'B', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
2627
|
+
['B', 'B', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
2628
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
2629
|
+
[' ', ' ', ' ', ' ', 'B', ' ', ' ', ' ', 'B', ' '],
|
2630
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', 'B', 'B', ' '],
|
2631
|
+
['B', 'B', ' ', ' ', ' ', ' ', 'B', 'B', 'B', ' '],
|
2632
|
+
['B', ' ', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
2633
|
+
])
|
2634
|
+
binst = shapeless_solver.Board(board=board, star_count=2)
|
2635
|
+
solutions = binst.solve_and_print()
|
2636
|
+
```
|
2637
|
+
|
2638
|
+
|
2639
|
+
**Script Output**
|
2640
|
+
|
2641
|
+
```python
|
2642
|
+
Solution found
|
2643
|
+
['*', ' ', ' ', ' ', '*', ' ', ' ', ' ', ' ', ' '],
|
2644
|
+
[' ', ' ', ' ', ' ', ' ', ' ', '*', ' ', '*', ' '],
|
2645
|
+
[' ', ' ', '*', ' ', '*', ' ', ' ', ' ', ' ', ' '],
|
2646
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', '*', ' ', '*'],
|
2647
|
+
[' ', ' ', '*', ' ', ' ', '*', ' ', ' ', ' ', ' '],
|
2648
|
+
['*', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '*', ' '],
|
2649
|
+
[' ', ' ', ' ', '*', ' ', ' ', '*', ' ', ' ', ' '],
|
2650
|
+
[' ', '*', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '*'],
|
2651
|
+
[' ', ' ', ' ', '*', ' ', '*', ' ', ' ', ' ', ' '],
|
2652
|
+
[' ', '*', ' ', ' ', ' ', ' ', ' ', '*', ' ', ' ']
|
2653
|
+
Solutions found: 1
|
2654
|
+
status: OPTIMAL
|
2655
|
+
Time taken: 0.02 seconds
|
2656
|
+
```
|
2657
|
+
|
2658
|
+
**Solved puzzle**
|
2659
|
+
|
2660
|
+
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_shapeless_solved.png" alt="Star Battle Shapeless solved" width="500">
|
2661
|
+
|
2662
|
+
---
|
2663
|
+
|
2589
2664
|
---
|
2590
2665
|
|
2591
2666
|
## Why SAT / CP-SAT?
|
@@ -2668,3 +2743,4 @@ Issues and PRs welcome!
|
|
2668
2743
|
[29]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/battleships "puzzle_solver/src/puzzle_solver/puzzles/battleships at master · Ar-Kareem/puzzle_solver · GitHub"
|
2669
2744
|
[30]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/kakurasu "puzzle_solver/src/puzzle_solver/puzzles/kakurasu at master · Ar-Kareem/puzzle_solver · GitHub"
|
2670
2745
|
[31]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/star_battle "puzzle_solver/src/puzzle_solver/puzzles/star_battle at master · Ar-Kareem/puzzle_solver · GitHub"
|
2746
|
+
[32]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/star_battle_shapeless "puzzle_solver/src/puzzle_solver/puzzles/star_battle_shapeless at master · Ar-Kareem/puzzle_solver · GitHub"
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/multi_puzzle_solver.egg-info/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: multi-puzzle-solver
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.9
|
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
|
@@ -254,6 +254,11 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
|
|
254
254
|
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_solved.png" alt="Star Battle" width="140">
|
255
255
|
</a>
|
256
256
|
</td>
|
257
|
+
<td align="center">
|
258
|
+
<a href="#star-battle-shapeless-puzzle-type-32"><b>Star Battle Shapeless</b><br><br>
|
259
|
+
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_shapeless_solved.png" alt="Star Battle Shapeless" width="140">
|
260
|
+
</a>
|
261
|
+
</td>
|
257
262
|
</tr>
|
258
263
|
</table>
|
259
264
|
|
@@ -300,6 +305,7 @@ These are all the puzzles that are implemented in this repo. <br> Click on any o
|
|
300
305
|
- [Battleships (Puzzle Type #29)](#battleships-puzzle-type-29)
|
301
306
|
- [Kakurasu (Puzzle Type #30)](#kakurasu-puzzle-type-30)
|
302
307
|
- [Star Battle (Puzzle Type #31)](#star-battle-puzzle-type-31)
|
308
|
+
- [Star Battle Shapeless (Puzzle Type #32)](#star-battle-shapeless-puzzle-type-32)
|
303
309
|
- [Why SAT / CP-SAT?](#why-sat--cp-sat)
|
304
310
|
- [Testing](#testing)
|
305
311
|
- [Contributing](#contributing)
|
@@ -2536,39 +2542,39 @@ Time taken: 0.00 seconds
|
|
2536
2542
|
|
2537
2543
|
Code to utilize this package and solve the puzzle:
|
2538
2544
|
|
2539
|
-
Note that as usual the board is an id of the shape (id is meaningless, just used to identify one shape), and the star_count parameter depenends on the puzzle type.
|
2545
|
+
Note that as usual the board is an id of the shape (id is meaningless, just used to identify one shape), and the `star_count` parameter depenends on the puzzle type.
|
2540
2546
|
|
2541
2547
|
```python
|
2542
2548
|
from puzzle_solver import star_battle_solver as solver
|
2543
|
-
|
2544
|
-
|
2545
|
-
|
2546
|
-
|
2547
|
-
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
|
2553
|
-
|
2554
|
-
|
2555
|
-
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
|
2560
|
-
|
2561
|
-
|
2562
|
-
|
2563
|
-
|
2564
|
-
|
2565
|
-
|
2566
|
-
|
2567
|
-
|
2568
|
-
|
2569
|
-
|
2570
|
-
|
2571
|
-
|
2549
|
+
board = np.array([
|
2550
|
+
['00', '00', '00', '00', '00', '01', '01', '01', '01', '01', '01', '01', '01', '01', '02', '02', '02', '03', '03', '03', '03', '03', '03', '03', '03'],
|
2551
|
+
['00', '01', '00', '01', '01', '01', '01', '01', '01', '01', '04', '04', '01', '02', '02', '02', '02', '05', '05', '05', '05', '05', '05', '03', '03'],
|
2552
|
+
['00', '01', '01', '01', '01', '01', '01', '01', '01', '04', '04', '04', '04', '04', '02', '02', '05', '05', '05', '05', '05', '05', '03', '03', '03'],
|
2553
|
+
['00', '01', '06', '04', '04', '04', '04', '04', '04', '04', '04', '04', '04', '04', '02', '05', '05', '05', '05', '05', '05', '05', '03', '07', '03'],
|
2554
|
+
['00', '01', '06', '06', '06', '06', '06', '06', '06', '04', '04', '04', '04', '02', '02', '02', '02', '02', '05', '05', '05', '05', '05', '07', '03'],
|
2555
|
+
['00', '00', '08', '06', '09', '09', '09', '09', '06', '04', '04', '04', '04', '02', '02', '02', '02', '02', '05', '05', '05', '05', '07', '07', '07'],
|
2556
|
+
['00', '08', '08', '08', '08', '09', '09', '06', '06', '06', '04', '04', '04', '04', '02', '02', '02', '05', '05', '05', '07', '07', '07', '07', '07'],
|
2557
|
+
['00', '00', '08', '08', '08', '09', '09', '09', '09', '06', '10', '10', '10', '10', '02', '02', '02', '05', '11', '11', '11', '11', '07', '07', '07'],
|
2558
|
+
['08', '08', '08', '08', '09', '09', '09', '09', '09', '09', '10', '10', '10', '02', '02', '02', '02', '11', '11', '11', '11', '11', '11', '07', '11'],
|
2559
|
+
['08', '08', '08', '08', '09', '09', '09', '09', '09', '10', '10', '10', '10', '02', '02', '02', '11', '11', '11', '11', '11', '11', '11', '07', '11'],
|
2560
|
+
['08', '08', '08', '09', '09', '09', '09', '09', '10', '10', '10', '10', '10', '12', '12', '12', '12', '11', '11', '11', '11', '11', '11', '11', '11'],
|
2561
|
+
['08', '08', '09', '09', '09', '09', '09', '08', '10', '10', '10', '10', '10', '10', '10', '10', '12', '11', '11', '11', '11', '13', '11', '13', '11'],
|
2562
|
+
['14', '08', '08', '08', '08', '08', '08', '08', '10', '10', '10', '10', '10', '12', '12', '12', '12', '12', '11', '11', '11', '13', '11', '13', '15'],
|
2563
|
+
['14', '14', '14', '14', '16', '08', '16', '16', '17', '10', '10', '10', '10', '10', '10', '10', '10', '12', '13', '13', '13', '13', '13', '13', '15'],
|
2564
|
+
['14', '14', '14', '14', '16', '16', '16', '16', '17', '10', '10', '18', '18', '10', '19', '10', '12', '12', '13', '15', '15', '15', '15', '15', '15'],
|
2565
|
+
['14', '14', '14', '14', '14', '16', '16', '17', '17', '18', '18', '18', '19', '19', '19', '10', '10', '10', '13', '15', '15', '15', '15', '15', '15'],
|
2566
|
+
['14', '14', '14', '16', '16', '16', '16', '17', '18', '18', '20', '20', '19', '21', '19', '19', '19', '19', '13', '15', '15', '15', '15', '15', '15'],
|
2567
|
+
['14', '16', '16', '16', '16', '16', '16', '17', '18', '18', '20', '21', '21', '21', '21', '19', '21', '19', '15', '15', '21', '15', '15', '15', '15'],
|
2568
|
+
['14', '14', '14', '16', '16', '17', '17', '17', '18', '20', '20', '21', '20', '21', '21', '19', '21', '19', '15', '21', '21', '15', '15', '15', '15'],
|
2569
|
+
['14', '14', '14', '16', '16', '16', '17', '17', '18', '18', '20', '20', '20', '20', '21', '21', '21', '21', '21', '21', '15', '15', '22', '22', '15'],
|
2570
|
+
['14', '14', '14', '14', '23', '16', '17', '20', '18', '20', '20', '20', '20', '20', '20', '21', '24', '24', '24', '21', '15', '15', '22', '15', '15'],
|
2571
|
+
['14', '14', '14', '14', '23', '20', '17', '20', '18', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '21', '15', '22', '22', '22', '15'],
|
2572
|
+
['14', '23', '23', '14', '23', '20', '20', '20', '18', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24', '22', '15'],
|
2573
|
+
['14', '23', '14', '14', '23', '20', '23', '20', '18', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '24', '22', '22', '22', '22', '22'],
|
2574
|
+
['14', '23', '23', '23', '23', '23', '23', '20', '20', '20', '20', '20', '20', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24', '24']
|
2575
|
+
])
|
2576
|
+
binst = solver.Board(board=board, star_count=6)
|
2577
|
+
solutions = binst.solve_and_print()
|
2572
2578
|
```
|
2573
2579
|
|
2574
2580
|
|
@@ -2612,6 +2618,75 @@ Time taken: 0.38 seconds
|
|
2612
2618
|
|
2613
2619
|
---
|
2614
2620
|
|
2621
|
+
## Star Battle Shapeless (Puzzle Type #32)
|
2622
|
+
|
2623
|
+
* [**Play online**](https://www.puzzle-star-battle.com/?size=14)
|
2624
|
+
|
2625
|
+
* [**Solver Code**][32]
|
2626
|
+
|
2627
|
+
<details>
|
2628
|
+
<summary><strong>Rules</strong></summary>
|
2629
|
+
|
2630
|
+
You have to place stars on the grid according to the rules:
|
2631
|
+
- 2 stars cannot be adjacent horizontally, vertically or diagonally.
|
2632
|
+
- For 1★ puzzles, you have to place 1 star on each row and column.
|
2633
|
+
- For 2★ puzzles, the stars per row and column must be 2 etc.
|
2634
|
+
- Some places begin with a black square and cannot have stars placed on them.
|
2635
|
+
|
2636
|
+
</details>
|
2637
|
+
|
2638
|
+
**Unsolved puzzle**
|
2639
|
+
|
2640
|
+
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_shapeless_unsolved.png" alt="Star Battle Shapeless unsolved" width="500">
|
2641
|
+
|
2642
|
+
Code to utilize this package and solve the puzzle:
|
2643
|
+
|
2644
|
+
The `star_count` parameter depenends on the puzzle type.
|
2645
|
+
|
2646
|
+
```python
|
2647
|
+
from puzzle_solver import star_battle_shapeless_solver as shapeless_solver
|
2648
|
+
board = np.array([
|
2649
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
2650
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
2651
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'B', ' '],
|
2652
|
+
['B', 'B', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
2653
|
+
['B', 'B', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
2654
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
2655
|
+
[' ', ' ', ' ', ' ', 'B', ' ', ' ', ' ', 'B', ' '],
|
2656
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', 'B', 'B', ' '],
|
2657
|
+
['B', 'B', ' ', ' ', ' ', ' ', 'B', 'B', 'B', ' '],
|
2658
|
+
['B', ' ', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
2659
|
+
])
|
2660
|
+
binst = shapeless_solver.Board(board=board, star_count=2)
|
2661
|
+
solutions = binst.solve_and_print()
|
2662
|
+
```
|
2663
|
+
|
2664
|
+
|
2665
|
+
**Script Output**
|
2666
|
+
|
2667
|
+
```python
|
2668
|
+
Solution found
|
2669
|
+
['*', ' ', ' ', ' ', '*', ' ', ' ', ' ', ' ', ' '],
|
2670
|
+
[' ', ' ', ' ', ' ', ' ', ' ', '*', ' ', '*', ' '],
|
2671
|
+
[' ', ' ', '*', ' ', '*', ' ', ' ', ' ', ' ', ' '],
|
2672
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', '*', ' ', '*'],
|
2673
|
+
[' ', ' ', '*', ' ', ' ', '*', ' ', ' ', ' ', ' '],
|
2674
|
+
['*', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '*', ' '],
|
2675
|
+
[' ', ' ', ' ', '*', ' ', ' ', '*', ' ', ' ', ' '],
|
2676
|
+
[' ', '*', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '*'],
|
2677
|
+
[' ', ' ', ' ', '*', ' ', '*', ' ', ' ', ' ', ' '],
|
2678
|
+
[' ', '*', ' ', ' ', ' ', ' ', ' ', '*', ' ', ' ']
|
2679
|
+
Solutions found: 1
|
2680
|
+
status: OPTIMAL
|
2681
|
+
Time taken: 0.02 seconds
|
2682
|
+
```
|
2683
|
+
|
2684
|
+
**Solved puzzle**
|
2685
|
+
|
2686
|
+
<img src="https://raw.githubusercontent.com/Ar-Kareem/puzzle_solver/master/images/star_battle_shapeless_solved.png" alt="Star Battle Shapeless solved" width="500">
|
2687
|
+
|
2688
|
+
---
|
2689
|
+
|
2615
2690
|
---
|
2616
2691
|
|
2617
2692
|
## Why SAT / CP-SAT?
|
@@ -2694,3 +2769,4 @@ Issues and PRs welcome!
|
|
2694
2769
|
[29]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/battleships "puzzle_solver/src/puzzle_solver/puzzles/battleships at master · Ar-Kareem/puzzle_solver · GitHub"
|
2695
2770
|
[30]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/kakurasu "puzzle_solver/src/puzzle_solver/puzzles/kakurasu at master · Ar-Kareem/puzzle_solver · GitHub"
|
2696
2771
|
[31]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/star_battle "puzzle_solver/src/puzzle_solver/puzzles/star_battle at master · Ar-Kareem/puzzle_solver · GitHub"
|
2772
|
+
[32]: https://github.com/Ar-Kareem/puzzle_solver/tree/master/src/puzzle_solver/puzzles/star_battle_shapeless "puzzle_solver/src/puzzle_solver/puzzles/star_battle_shapeless at master · Ar-Kareem/puzzle_solver · GitHub"
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/multi_puzzle_solver.egg-info/SOURCES.txt
RENAMED
@@ -33,6 +33,7 @@ src/puzzle_solver/puzzles/range/range.py
|
|
33
33
|
src/puzzle_solver/puzzles/signpost/signpost.py
|
34
34
|
src/puzzle_solver/puzzles/singles/singles.py
|
35
35
|
src/puzzle_solver/puzzles/star_battle/star_battle.py
|
36
|
+
src/puzzle_solver/puzzles/star_battle/star_battle_shapeless.py
|
36
37
|
src/puzzle_solver/puzzles/stitches/stitches.py
|
37
38
|
src/puzzle_solver/puzzles/stitches/parse_map/parse_map.py
|
38
39
|
src/puzzle_solver/puzzles/sudoku/sudoku.py
|
@@ -21,6 +21,7 @@ from puzzle_solver.puzzles.range import range as range_solver
|
|
21
21
|
from puzzle_solver.puzzles.signpost import signpost as signpost_solver
|
22
22
|
from puzzle_solver.puzzles.singles import singles as singles_solver
|
23
23
|
from puzzle_solver.puzzles.star_battle import star_battle as star_battle_solver
|
24
|
+
from puzzle_solver.puzzles.star_battle import star_battle_shapeless as star_battle_shapeless_solver
|
24
25
|
from puzzle_solver.puzzles.stitches import stitches as stitches_solver
|
25
26
|
from puzzle_solver.puzzles.sudoku import sudoku as sudoku_solver
|
26
27
|
from puzzle_solver.puzzles.tents import tents as tents_solver
|
@@ -32,4 +33,4 @@ from puzzle_solver.puzzles.unruly import unruly as unruly_solver
|
|
32
33
|
|
33
34
|
from puzzle_solver.puzzles.inertia.parse_map.parse_map import main as inertia_image_parser
|
34
35
|
|
35
|
-
__version__ = '0.9.
|
36
|
+
__version__ = '0.9.9'
|
@@ -6,19 +6,22 @@ from puzzle_solver.core.utils_ortools import generic_solve_all, SingleSolution
|
|
6
6
|
|
7
7
|
|
8
8
|
class Board:
|
9
|
-
def __init__(self, board: np.array, star_count: int = 1):
|
9
|
+
def __init__(self, board: np.array, star_count: int = 1, shapeless: bool = False):
|
10
10
|
assert board.ndim == 2, f'board must be 2d, got {board.ndim}'
|
11
11
|
assert board.shape[0] == board.shape[1], 'board must be square'
|
12
12
|
assert star_count >= 1 and isinstance(star_count, int), 'star_count must be an integer greater than or equal to 1'
|
13
|
-
assert all((str(c.item()).isdecimal() for c in np.nditer(board))), 'board must contain only digits'
|
14
13
|
self.board = board
|
15
14
|
self.V = board.shape[0]
|
16
15
|
self.H = board.shape[1]
|
17
16
|
self.N = self.V * self.H
|
18
17
|
self.star_count = star_count
|
19
|
-
self.
|
20
|
-
|
21
|
-
|
18
|
+
self.shapeless = shapeless
|
19
|
+
if not shapeless:
|
20
|
+
assert all((str(c.item()).isdecimal() for c in np.nditer(board))), 'board must contain only digits'
|
21
|
+
self.block_numbers = set([int(c.item()) for c in np.nditer(board)])
|
22
|
+
self.blocks = {i: [pos for pos in get_all_pos(self.V, self.H) if int(get_char(self.board, pos)) == i] for i in self.block_numbers}
|
23
|
+
else:
|
24
|
+
assert all((str(c.item()) in [' ', 'B'] for c in np.nditer(board))), 'board must contain only digits'
|
22
25
|
self.model = cp_model.CpModel()
|
23
26
|
self.model_vars: dict[Pos, cp_model.IntVar] = {}
|
24
27
|
|
@@ -30,13 +33,18 @@ class Board:
|
|
30
33
|
self.model_vars[pos] = self.model.NewBoolVar(f'{pos}')
|
31
34
|
|
32
35
|
def add_all_constraints(self):
|
33
|
-
# N stars per row / column
|
36
|
+
# N stars per row / column
|
34
37
|
for row in range(self.V):
|
35
38
|
self.model.Add(sum(self.model_vars[pos] for pos in get_row_pos(row, H=self.H)) == self.star_count)
|
36
39
|
for col in range(self.H):
|
37
40
|
self.model.Add(sum(self.model_vars[pos] for pos in get_col_pos(col, V=self.V)) == self.star_count)
|
38
|
-
|
39
|
-
|
41
|
+
if self.shapeless: # shapeless version = no blocks but disallow black cells
|
42
|
+
for pos in get_all_pos(self.V, self.H):
|
43
|
+
if get_char(self.board, pos) == 'B':
|
44
|
+
self.model.Add(self.model_vars[pos] == 0)
|
45
|
+
else: # shaped version = blocks
|
46
|
+
for block_i in self.block_numbers:
|
47
|
+
self.model.Add(sum(self.model_vars[pos] for pos in self.blocks[block_i]) == self.star_count)
|
40
48
|
# stars cant be adjacent
|
41
49
|
for pos in get_all_pos(self.V, self.H):
|
42
50
|
for neighbor in get_neighbors8(pos, V=self.V, H=self.H):
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import numpy as np
|
2
2
|
|
3
3
|
from puzzle_solver import star_battle_solver as solver
|
4
|
+
from puzzle_solver import star_battle_shapeless_solver as shapeless_solver
|
4
5
|
from puzzle_solver.core.utils import get_pos
|
5
6
|
|
6
7
|
|
@@ -94,6 +95,26 @@ def test_ground_2():
|
|
94
95
|
for pos in solution.keys():
|
95
96
|
assert solution[pos] == ground_assignment[pos], f'solution[{pos}] != ground_assignment[{pos}], {solution[pos]} != {ground_assignment[pos]}'
|
96
97
|
|
98
|
+
def test_ground_3():
|
99
|
+
# https://www.puzzle-star-battle.com/?e=MTQ6OSw4ODEsNTc1
|
100
|
+
board = np.array([
|
101
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
102
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
103
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'B', ' '],
|
104
|
+
['B', 'B', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
105
|
+
['B', 'B', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
106
|
+
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '],
|
107
|
+
[' ', ' ', ' ', ' ', 'B', ' ', ' ', ' ', 'B', ' '],
|
108
|
+
['B', ' ', ' ', ' ', ' ', ' ', ' ', 'B', 'B', ' '],
|
109
|
+
['B', 'B', ' ', ' ', ' ', ' ', 'B', 'B', 'B', ' '],
|
110
|
+
['B', ' ', ' ', ' ', 'B', ' ', ' ', ' ', ' ', ' '],
|
111
|
+
])
|
112
|
+
binst = shapeless_solver.Board(board=board, star_count=2)
|
113
|
+
solutions = binst.solve_and_print()
|
114
|
+
assert len(solutions) == 1, f'unique solutions != 1, == {len(solutions)}'
|
115
|
+
solution = solutions[0].assignment
|
116
|
+
|
117
|
+
|
97
118
|
if __name__ == '__main__':
|
98
119
|
test_ground_1()
|
99
120
|
test_ground_2()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/core/utils_ortools.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/bridges/bridges.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/filling/filling.py
RENAMED
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/guess/guess.py
RENAMED
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/inertia/inertia.py
RENAMED
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/inertia/tsp.py
RENAMED
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/keen/keen.py
RENAMED
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/magnets/magnets.py
RENAMED
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/map/map.py
RENAMED
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/mosaic/mosaic.py
RENAMED
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/pearl/pearl.py
RENAMED
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/range/range.py
RENAMED
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/singles/singles.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/sudoku/sudoku.py
RENAMED
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/tents/tents.py
RENAMED
File without changes
|
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/towers/towers.py
RENAMED
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/tracks/tracks.py
RENAMED
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/undead/undead.py
RENAMED
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/puzzles/unruly/unruly.py
RENAMED
File without changes
|
{multi_puzzle_solver-0.9.8 → multi_puzzle_solver-0.9.9}/src/puzzle_solver/utils/visualizer.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|