multi-puzzle-solver 0.9.26__py3-none-any.whl → 0.9.30__py3-none-any.whl

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.

@@ -1,9 +1,11 @@
1
- puzzle_solver/__init__.py,sha256=ScIPz0Gi0xGaY-v7N0JcfFgKUvfdSF3lUggAh8yagdg,3201
2
- puzzle_solver/core/utils.py,sha256=LyrdhExCcdp7jWJJv1cu2urgS2gpcI44OsIipPeBAeQ,14113
1
+ puzzle_solver/__init__.py,sha256=f79JI0EQhfQi12yO6gvuzzLtxXQgojVrq-v8HZrzjS0,3693
2
+ puzzle_solver/core/utils.py,sha256=XBW5j-IwtJMPMP-ycmY6SqRCM1NOVl5O6UeoGqNj618,8153
3
3
  puzzle_solver/core/utils_ortools.py,sha256=_i8cixHOB5XGqqcr-493bOiZgYJidnvxQMEfj--Trns,10278
4
+ puzzle_solver/core/utils_visualizer.py,sha256=2jBnS2PeI4keFf-rneScSxX669zXu5F1lkClZ5EkMhE,21152
4
5
  puzzle_solver/puzzles/aquarium/aquarium.py,sha256=BUfkAS2d9eG3TdMoe1cOGGeNYgKUebRvn-z9nsC9gvE,5708
5
6
  puzzle_solver/puzzles/battleships/battleships.py,sha256=RuYCrs4j0vUjlU139NRYYP-uNPAgO0V7hAzbsHrRwD8,7446
6
- puzzle_solver/puzzles/binairo/binairo.py,sha256=sRtflnlGrN8xQ64beRZBGr74R8KptzxYDdFgXuW27pM,4595
7
+ puzzle_solver/puzzles/binairo/binairo.py,sha256=4xgYd1ewYIQCqEzsHdgp6hWzyW_TF_2rt6PO8QLFKWU,6838
8
+ puzzle_solver/puzzles/binairo/binairo_plus.py,sha256=TvLG3olwANtft3LuCF-y4OofpU9PNa4IXDqgZqsD-g0,267
7
9
  puzzle_solver/puzzles/black_box/black_box.py,sha256=ZnHDVt6PFS_r1kMNSsbz9hav1hxIrNDUvPyERGPjLjM,15635
8
10
  puzzle_solver/puzzles/bridges/bridges.py,sha256=15A9uV4xjoqPRo_9CTnoKeGRxS3z2aMF619T1n0dTOQ,5402
9
11
  puzzle_solver/puzzles/chess_range/chess_melee.py,sha256=D-_Oi8OyxsVe1j3dIKYwRlxgeb3NWLmDWGcv-oclY0c,195
@@ -16,10 +18,12 @@ puzzle_solver/puzzles/flip/flip.py,sha256=ZngJLUhRNc7qqo2wtNLdMPx4u9w9JTUge27Pmd
16
18
  puzzle_solver/puzzles/galaxies/galaxies.py,sha256=p10lpmW0FjtneFCMEjG1FSiEpQuvD8zZG9FG8zYGoes,5582
17
19
  puzzle_solver/puzzles/galaxies/parse_map/parse_map.py,sha256=v5TCrdREeOB69s9_QFgPHKA7flG69Im1HVzIdxH0qQc,9355
18
20
  puzzle_solver/puzzles/guess/guess.py,sha256=sH-NlYhxM3DNbhk4eGde09kgM0KaDvSbLrpHQiwcFGo,10791
21
+ puzzle_solver/puzzles/heyawake/heyawake.py,sha256=qMnc_CuHn8K5Rw40tefjueI1pycpHQ7eN1R9Xg5WEuw,5601
19
22
  puzzle_solver/puzzles/inertia/inertia.py,sha256=gJBahkh69CrSWNscalKEoP1j4X-Q3XpbIBMiG9PUpU0,5657
20
23
  puzzle_solver/puzzles/inertia/tsp.py,sha256=gobiISHtARA4Elq0jr90p6Yhq11ULjGoqsS-rLFhYcc,15389
21
24
  puzzle_solver/puzzles/inertia/parse_map/parse_map.py,sha256=A9JQTNqamUdzlwqks0XQp3Hge3mzyTIVK6YtDJvqpL4,8422
22
25
  puzzle_solver/puzzles/kakurasu/kakurasu.py,sha256=VNGMJnBHDi6WkghLObRLhUvkmrPaGphTTUDMC0TkQvQ,2064
26
+ puzzle_solver/puzzles/kakuro/kakuro.py,sha256=Jf0Iilv32EPcaWikX92_vgBOVRp5MAE27aFRmnLotGQ,4374
23
27
  puzzle_solver/puzzles/keen/keen.py,sha256=tDb6C5S3Q0JAKPsdw-84WQ6PxRADELZHr_BK8FDH-NA,5039
24
28
  puzzle_solver/puzzles/light_up/light_up.py,sha256=iSA1rjZMFsnI0V0Nxivxox4qZkB7PvUrROSHXcoUXds,4541
25
29
  puzzle_solver/puzzles/lits/lits.py,sha256=3fPIkhAIUz8JokcfaE_ZM3b0AFEnf5xPzGJ2qnm8SWY,7099
@@ -29,20 +33,24 @@ puzzle_solver/puzzles/minesweeper/minesweeper.py,sha256=LiQVOGkWCsc1WtX8CdPgL_Ww
29
33
  puzzle_solver/puzzles/mosaic/mosaic.py,sha256=QX_nVpVKQg8OfaUcqFk9tKqsDyVqvZc6-XWvfI3YcSw,2175
30
34
  puzzle_solver/puzzles/nonograms/nonograms.py,sha256=1jmDTOCnmivmBlwtMDyyk3TVqH5IjapzLn7zLQ4qubk,6056
31
35
  puzzle_solver/puzzles/norinori/norinori.py,sha256=uC8vXAw35xsTmpmTeKqYW7tbcssms9LCcXFBONtV2Ng,4743
32
- puzzle_solver/puzzles/palisade/palisade.py,sha256=GTtzuc1OZCm3D5p-Po7LzK1d-whJkNSZ9G9rWr3vFMc,4966
36
+ puzzle_solver/puzzles/nurikabe/nurikabe.py,sha256=VMJjB9KAKmfBkG1mDT3Jf2I1PZJb--Qx0BicN8xL4eg,6519
37
+ puzzle_solver/puzzles/palisade/palisade.py,sha256=T-LXlaLU5OwUQ24QWJWhBUFUktg0qDODTilNmBaXs4I,5014
33
38
  puzzle_solver/puzzles/pearl/pearl.py,sha256=OhzpMYpxqvR3GCd5NH4ETT0NO4X753kRi6p5omYLChM,6798
34
39
  puzzle_solver/puzzles/range/range.py,sha256=rruvD5ZSaOgvQuX6uGV_Dkr82nSiWZ5kDz03_j7Tt24,4425
35
- puzzle_solver/puzzles/rectangles/rectangles.py,sha256=V7p6GSCwYrFfILDWiLLUbX08WlnPbQKdhQm8bMa2Mgw,7060
40
+ puzzle_solver/puzzles/rectangles/rectangles.py,sha256=zaPg3qI9TNxr2iXmNi2kOL8R2RsS9DyQPUTY3ukgYIA,7033
41
+ puzzle_solver/puzzles/shakashaka/shakashaka.py,sha256=PRpg_qI7XA3ysAo_g1TRJsT3VwB5Vial2UcFyBOMwKQ,9571
42
+ puzzle_solver/puzzles/shingoki/shingoki.py,sha256=uwX1ZIGGDlshMtsZedlgGYE8hDB1ou3h6aBnZEr_l8I,7425
36
43
  puzzle_solver/puzzles/signpost/signpost.py,sha256=-0_S6ycwzwlUf9-ZhP127Rgo5gMBOHiTM6t08dLLDac,3869
37
- puzzle_solver/puzzles/singles/singles.py,sha256=3wACiUa1Vmh2ce6szQ2hPjyBuH7aHiQ888p4R2jFkW4,3342
44
+ puzzle_solver/puzzles/singles/singles.py,sha256=KKn_Yl-eW874Bl1UmmcqoQ5vhNiO1JbM7fxKczOV5M4,2847
38
45
  puzzle_solver/puzzles/slant/slant.py,sha256=xF-N4PuXYfx638NP1f1mi6YncIZB4mLtXtdS79XyPbg,6122
39
46
  puzzle_solver/puzzles/slant/parse_map/parse_map.py,sha256=dxnALSDXe9wU0uSD0QEXnzoh1q801mj1ePTNLtG0n60,4796
40
- puzzle_solver/puzzles/slitherlink/slitherlink.py,sha256=N3jv1Z-yYFlQDinii-DZfuJvLUsn9fT0h5Kyruxjn94,7017
47
+ puzzle_solver/puzzles/slitherlink/slitherlink.py,sha256=e1A_f_3J-QXN9fmt_Nf3FsYnp-TmE9TRKN06Wn4NnAU,7056
41
48
  puzzle_solver/puzzles/star_battle/star_battle.py,sha256=IX6w4H3sifN01kPPtrAVRCK0Nl_xlXXSHvJKw8K1EuE,3718
42
49
  puzzle_solver/puzzles/star_battle/star_battle_shapeless.py,sha256=lj05V0Y3A3NjMo1boMkPIwBhMtm6SWydjgAMeCf5EIo,225
43
50
  puzzle_solver/puzzles/stitches/stitches.py,sha256=iK8t02q43gH3FPbuIDn4dK0sbaOgZOnw8yHNRNvNuIU,6534
44
- puzzle_solver/puzzles/stitches/parse_map/parse_map.py,sha256=1LNJkIqpcz1LvY0H0uRedABQWm44dgNf9XeQuKm36WM,10275
51
+ puzzle_solver/puzzles/stitches/parse_map/parse_map.py,sha256=f49ZGVBPXjAGgqZnqPab6PcO_DsFDFZnG3uA8b-1d7k,10441
45
52
  puzzle_solver/puzzles/sudoku/sudoku.py,sha256=SE4TM_gic6Jj0fkDR_NzUJdX2XKyQ8eeOnVAQ011Xbo,8870
53
+ puzzle_solver/puzzles/tapa/tapa.py,sha256=TsOQhnEvlC1JxaWiEjQg2KxRXJR49GrN71DsMvPpia8,5337
46
54
  puzzle_solver/puzzles/tents/tents.py,sha256=iyVK2WXfIT5j_9qqlQg0WmwvixwXlZSsHGK3XA-KpII,6283
47
55
  puzzle_solver/puzzles/thermometers/thermometers.py,sha256=nsvJZkm7G8FALT27bpaB0lv5E_AWawqmvapQI8QcYXw,4015
48
56
  puzzle_solver/puzzles/towers/towers.py,sha256=QvL0Pp-Z2ewCeq9ZkNrh8MShKOh-Y52sFBSudve68wk,6496
@@ -53,7 +61,7 @@ puzzle_solver/puzzles/unruly/unruly.py,sha256=sDF0oKT50G-NshyW2DYrvAgD9q9Ku9ANUy
53
61
  puzzle_solver/puzzles/yin_yang/yin_yang.py,sha256=WrRdNhmKhIARdGOt_36gpRxRzrfLGv3wl7igBpPFM64,5259
54
62
  puzzle_solver/puzzles/yin_yang/parse_map/parse_map.py,sha256=drjfoHqmFf6U-ZQUwrBbfGINRxDQpgbvy4U3D9QyMhM,6617
55
63
  puzzle_solver/utils/visualizer.py,sha256=tsX1yEKwmwXBYuBJpx_oZGe2UUt1g5yV73G3UbtmvtE,6817
56
- multi_puzzle_solver-0.9.26.dist-info/METADATA,sha256=iVRpKnMdTJNLrbdh9eP19RsPCloN1iEFwtlvcwy_peg,211081
57
- multi_puzzle_solver-0.9.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
58
- multi_puzzle_solver-0.9.26.dist-info/top_level.txt,sha256=exwVUQa-anK9vYrpKzBPvH8bX43iElWI4VeNiAyBGJY,14
59
- multi_puzzle_solver-0.9.26.dist-info/RECORD,,
64
+ multi_puzzle_solver-0.9.30.dist-info/METADATA,sha256=yxPV6ZvkvGPOs1O2HpIob3e94uFQXjpm5JJKdCXyc2s,335384
65
+ multi_puzzle_solver-0.9.30.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
66
+ multi_puzzle_solver-0.9.30.dist-info/top_level.txt,sha256=exwVUQa-anK9vYrpKzBPvH8bX43iElWI4VeNiAyBGJY,14
67
+ multi_puzzle_solver-0.9.30.dist-info/RECORD,,
puzzle_solver/__init__.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from puzzle_solver.puzzles.aquarium import aquarium as aquarium_solver
2
2
  from puzzle_solver.puzzles.battleships import battleships as battleships_solver
3
3
  from puzzle_solver.puzzles.binairo import binairo as binairo_solver
4
+ from puzzle_solver.puzzles.binairo import binairo_plus as binairo_plus_solver
4
5
  from puzzle_solver.puzzles.black_box import black_box as black_box_solver
5
6
  from puzzle_solver.puzzles.bridges import bridges as bridges_solver
6
7
  from puzzle_solver.puzzles.chess_range import chess_range as chess_range_solver
@@ -11,8 +12,10 @@ from puzzle_solver.puzzles.filling import filling as filling_solver
11
12
  from puzzle_solver.puzzles.flip import flip as flip_solver
12
13
  from puzzle_solver.puzzles.galaxies import galaxies as galaxies_solver
13
14
  from puzzle_solver.puzzles.guess import guess as guess_solver
15
+ from puzzle_solver.puzzles.heyawake import heyawake as heyawake_solver
14
16
  from puzzle_solver.puzzles.inertia import inertia as inertia_solver
15
17
  from puzzle_solver.puzzles.kakurasu import kakurasu as kakurasu_solver
18
+ from puzzle_solver.puzzles.kakuro import kakuro as kakuro_solver
16
19
  from puzzle_solver.puzzles.keen import keen as keen_solver
17
20
  from puzzle_solver.puzzles.light_up import light_up as light_up_solver
18
21
  from puzzle_solver.puzzles.magnets import magnets as magnets_solver
@@ -21,11 +24,14 @@ from puzzle_solver.puzzles.minesweeper import minesweeper as minesweeper_solver
21
24
  from puzzle_solver.puzzles.mosaic import mosaic as mosaic_solver
22
25
  from puzzle_solver.puzzles.nonograms import nonograms as nonograms_solver
23
26
  from puzzle_solver.puzzles.norinori import norinori as norinori_solver
27
+ from puzzle_solver.puzzles.nurikabe import nurikabe as nurikabe_solver
24
28
  from puzzle_solver.puzzles.palisade import palisade as palisade_solver
25
29
  from puzzle_solver.puzzles.lits import lits as lits_solver
26
30
  from puzzle_solver.puzzles.pearl import pearl as pearl_solver
27
31
  from puzzle_solver.puzzles.range import range as range_solver
28
32
  from puzzle_solver.puzzles.rectangles import rectangles as rectangles_solver
33
+ from puzzle_solver.puzzles.shakashaka import shakashaka as shakashaka_solver
34
+ from puzzle_solver.puzzles.shingoki import shingoki as shingoki_solver
29
35
  from puzzle_solver.puzzles.signpost import signpost as signpost_solver
30
36
  from puzzle_solver.puzzles.singles import singles as singles_solver
31
37
  from puzzle_solver.puzzles.slant import slant as slant_solver
@@ -34,6 +40,7 @@ from puzzle_solver.puzzles.star_battle import star_battle as star_battle_solver
34
40
  from puzzle_solver.puzzles.star_battle import star_battle_shapeless as star_battle_shapeless_solver
35
41
  from puzzle_solver.puzzles.stitches import stitches as stitches_solver
36
42
  from puzzle_solver.puzzles.sudoku import sudoku as sudoku_solver
43
+ from puzzle_solver.puzzles.tapa import tapa as tapa_solver
37
44
  from puzzle_solver.puzzles.tents import tents as tents_solver
38
45
  from puzzle_solver.puzzles.thermometers import thermometers as thermometers_solver
39
46
  from puzzle_solver.puzzles.towers import towers as towers_solver
@@ -45,4 +52,4 @@ from puzzle_solver.puzzles.yin_yang import yin_yang as yin_yang_solver
45
52
 
46
53
  from puzzle_solver.puzzles.inertia.parse_map.parse_map import main as inertia_image_parser
47
54
 
48
- __version__ = '0.9.26'
55
+ __version__ = '0.9.30'
@@ -230,156 +230,3 @@ def polyominoes_with_shape_id(N):
230
230
  result = {(frozenset(Pos(x, y) for x, y in s), _id) for s, _id in result}
231
231
  return result
232
232
 
233
-
234
- def render_grid(cell_flags: np.ndarray,
235
- center_char: Union[np.ndarray, str, None] = None,
236
- show_axes: bool = True,
237
- scale_x: int = 2) -> str:
238
- """
239
- most of this function was AI generated then modified by me, I don't currently care about the details of rendering to the terminal this looked good enough during my testing.
240
- cell_flags: np.ndarray of shape (N, N) with characters 'U', 'D', 'L', 'R' to represent the edges of the cells.
241
- center_char: np.ndarray of shape (N, N) with the center of the cells, or a string to use for all cells, or None to not show centers.
242
- scale_x: horizontal stretch factor (>=1). Try 2 or 3 for squarer cells.
243
- """
244
- assert cell_flags is not None and cell_flags.ndim == 2
245
- R, C = cell_flags.shape
246
-
247
- # Edge presence arrays (note the rectangular shapes)
248
- H = np.zeros((R+1, C), dtype=bool) # horizontal edges between rows
249
- V = np.zeros((R, C+1), dtype=bool) # vertical edges between cols
250
- for r in range(R):
251
- for c in range(C):
252
- s = cell_flags[r, c]
253
- if 'U' in s: H[r, c] = True
254
- if 'D' in s: H[r+1, c] = True
255
- if 'L' in s: V[r, c] = True
256
- if 'R' in s: V[r, c+1] = True
257
-
258
- # Bitmask for corner connections
259
- U, Rb, D, Lb = 1, 2, 4, 8
260
- JUNCTION = {
261
- 0: ' ',
262
- U: '│', D: '│', U|D: '│',
263
- Lb: '─', Rb: '─', Lb|Rb: '─',
264
- U|Rb: '└', Rb|D: '┌', D|Lb: '┐', Lb|U: '┘',
265
- U|D|Lb: '┤', U|D|Rb: '├', Lb|Rb|U: '┴', Lb|Rb|D: '┬',
266
- U|Rb|D|Lb: '┼',
267
- }
268
-
269
- assert scale_x >= 1
270
- assert H.shape == (R+1, C) and V.shape == (R, C+1)
271
-
272
- rows = 2*R + 1
273
- cols = 2*C*scale_x + 1
274
- canvas = [[' ']*cols for _ in range(rows)]
275
-
276
- def x_corner(c): # x of corner column c (0..C)
277
- return (2*c) * scale_x
278
- def x_between(c,k): # kth in-between col (1..2*scale_x-1) between corners c and c+1
279
- return (2*c) * scale_x + k
280
-
281
- # horizontal edges: fill the stretched band between corners with '─'
282
- for r in range(R+1):
283
- rr = 2*r
284
- for c in range(C):
285
- if H[r, c]:
286
- for k in range(1, scale_x*2): # 1..(2*scale_x-1)
287
- canvas[rr][x_between(c, k)] = '─'
288
-
289
- # vertical edges: at the corner columns
290
- for r in range(R):
291
- rr = 2*r + 1
292
- for c in range(C+1):
293
- if V[r, c]:
294
- canvas[rr][x_corner(c)] = '│'
295
-
296
- # junctions at every corner grid point
297
- for r in range(R+1):
298
- rr = 2*r
299
- for c in range(C+1):
300
- m = 0
301
- if r > 0 and V[r-1, c]: m |= U
302
- if c < C and H[r, c]: m |= Rb
303
- if r < R and V[r, c]: m |= D
304
- if c > 0 and H[r, c-1]: m |= Lb
305
- canvas[rr][x_corner(c)] = JUNCTION[m]
306
-
307
- # centers (safe for multi-character strings)
308
- def put_center_text(rr: int, c: int, text: str):
309
- left = x_corner(c) + 1
310
- right = x_corner(c+1) - 1
311
- if right < left:
312
- return
313
- span_width = right - left + 1
314
- s = str(text)
315
- if len(s) > span_width:
316
- s = s[:span_width] # truncate to protect borders
317
- start = left + (span_width - len(s)) // 2
318
- for i, ch in enumerate(s):
319
- canvas[rr][start + i] = ch
320
-
321
- if center_char is not None:
322
- for r in range(R):
323
- rr = 2*r + 1
324
- for c in range(C):
325
- val = center_char if isinstance(center_char, str) else center_char[r, c]
326
- put_center_text(rr, c, '' if val is None else str(val))
327
-
328
- # rows -> strings
329
- art_rows = [''.join(row) for row in canvas]
330
- if not show_axes:
331
- return '\n'.join(art_rows)
332
-
333
- # Axes labels: row indices on the left, column indices on top (handle C, not R)
334
- gut = max(2, len(str(R-1))) # gutter width based on row index width
335
- gutter = ' ' * gut
336
- top_tens = list(gutter + ' ' * cols)
337
- top_ones = list(gutter + ' ' * cols)
338
-
339
- for c in range(C):
340
- xc_center = x_corner(c) + scale_x
341
- if C >= 10:
342
- top_tens[gut + xc_center] = str((c // 10) % 10)
343
- top_ones[gut + xc_center] = str(c % 10)
344
-
345
- if gut >= 2:
346
- top_tens[gut-2:gut] = list(' ')
347
- top_ones[gut-2:gut] = list(' ')
348
-
349
- labeled = []
350
- for r, line in enumerate(art_rows):
351
- if r % 2 == 1: # cell-center row
352
- label = str(r//2).rjust(gut)
353
- else:
354
- label = ' ' * gut
355
- labeled.append(label + line)
356
-
357
- return ''.join(top_tens) + '\n' + ''.join(top_ones) + '\n' + '\n'.join(labeled)
358
-
359
- def id_board_to_wall_board(id_board: np.array, border_is_wall = True) -> np.array:
360
- """In many instances, we have a 2d array where cell values are arbitrary ids
361
- and we want to convert it to a 2d array where cell values are walls "U", "D", "L", "R" to represent the edges that separate me from my neighbors that have different ids.
362
- Args:
363
- id_board: np.array of shape (N, N) with arbitrary ids.
364
- border_is_wall: if True, the edges of the board are considered to be walls.
365
- Returns:
366
- np.array of shape (N, N) with walls "U", "D", "L", "R".
367
- """
368
- res = np.full((id_board.shape[0], id_board.shape[1]), '', dtype=object)
369
- V, H = id_board.shape
370
- def append_char(pos: Pos, s: str):
371
- set_char(res, pos, get_char(res, pos) + s)
372
- def handle_pos_direction(pos: Pos, direction: Direction, s: str):
373
- pos2 = get_next_pos(pos, direction)
374
- if in_bounds(pos2, V, H):
375
- if get_char(id_board, pos2) != get_char(id_board, pos):
376
- append_char(pos, s)
377
- else:
378
- if border_is_wall:
379
- append_char(pos, s)
380
- for pos in get_all_pos(V, H):
381
- handle_pos_direction(pos, Direction.LEFT, 'L')
382
- handle_pos_direction(pos, Direction.RIGHT, 'R')
383
- handle_pos_direction(pos, Direction.UP, 'U')
384
- handle_pos_direction(pos, Direction.DOWN, 'D')
385
- return res