puzzlekit 0.3.2__tar.gz → 0.3.3__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.
Files changed (351) hide show
  1. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/PKG-INFO +62 -4
  2. puzzlekit-0.3.2/src/puzzlekit.egg-info/PKG-INFO → puzzlekit-0.3.3/README.md +59 -52
  3. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/pyproject.toml +3 -3
  4. puzzlekit-0.3.3/src/puzzlekit/__init__.py +224 -0
  5. puzzlekit-0.3.3/src/puzzlekit/formats/base.py +250 -0
  6. puzzlekit-0.3.3/src/puzzlekit/formats/debug.py +570 -0
  7. puzzlekit-0.3.3/src/puzzlekit/formats/penpa_converter.py +478 -0
  8. puzzlekit-0.3.3/src/puzzlekit/formats/penpa_template.py +188 -0
  9. puzzlekit-0.3.3/src/puzzlekit/formats/puzzle_types.py +175 -0
  10. puzzlekit-0.3.3/src/puzzlekit/formats/puzzlink_converter.py +1690 -0
  11. puzzlekit-0.3.3/src/puzzlekit/formats/utils.py +194 -0
  12. puzzlekit-0.3.2/README.md → puzzlekit-0.3.3/src/puzzlekit.egg-info/PKG-INFO +110 -1
  13. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit.egg-info/SOURCES.txt +15 -2
  14. puzzlekit-0.3.3/tests/__init__.py +0 -0
  15. puzzlekit-0.3.3/tests/__pycache__/__init__.cpython-310.pyc +0 -0
  16. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/metadata_test_utils.cpython-310.pyc +0 -0
  17. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_abc_end_view.cpython-310-pytest-9.0.2.pyc +0 -0
  18. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_akari.cpython-310-pytest-9.0.2.pyc +0 -0
  19. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_balance_loop.cpython-310-pytest-9.0.2.pyc +0 -0
  20. puzzlekit-0.3.3/tests/__pycache__/test_battleship.cpython-310-pytest-9.0.2.pyc +0 -0
  21. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_binairo.cpython-310-pytest-9.0.2.pyc +0 -0
  22. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_bosanowa.cpython-310-pytest-9.0.2.pyc +0 -0
  23. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_bricks.cpython-310-pytest-9.0.2.pyc +0 -0
  24. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_buraitoraito.cpython-310-pytest-9.0.2.pyc +0 -0
  25. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_butterfly_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  26. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_castle_wall.cpython-310-pytest-9.0.2.pyc +0 -0
  27. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_cave.cpython-310-pytest-9.0.2.pyc +0 -0
  28. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_clueless_1_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  29. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_clueless_2_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  30. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_country_road.cpython-310-pytest-9.0.2.pyc +0 -0
  31. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_creek.cpython-310-pytest-9.0.2.pyc +0 -0
  32. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_detour.cpython-310-pytest-9.0.2.pyc +0 -0
  33. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_diff_neighbors.cpython-310-pytest-9.0.2.pyc +0 -0
  34. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_dominos.cpython-310-pytest-9.0.2.pyc +0 -0
  35. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_dotchi_loop.cpython-310-pytest-9.0.2.pyc +0 -0
  36. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_double_back.cpython-310-pytest-9.0.2.pyc +0 -0
  37. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_entry_exit.cpython-310-pytest-9.0.2.pyc +0 -0
  38. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_eulero.cpython-310-pytest-9.0.2.pyc +0 -0
  39. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_even_odd_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  40. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_fobidoshi.cpython-310-pytest-9.0.2.pyc +0 -0
  41. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_fuzuli.cpython-310-pytest-9.0.2.pyc +0 -0
  42. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_gappy.cpython-310-pytest-9.0.2.pyc +0 -0
  43. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_gattai_8_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  44. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_grand_tour.cpython-310-pytest-9.0.2.pyc +0 -0
  45. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_grid.cpython-310-pytest-9.0.2.pyc +0 -0
  46. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_hakoiri.cpython-310-pytest-9.0.2.pyc +0 -0
  47. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_hakyuu.cpython-310-pytest-9.0.2.pyc +0 -0
  48. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_heyawake.cpython-310-pytest-9.0.2.pyc +0 -0
  49. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_hidoku.cpython-310-pytest-9.0.2.pyc +0 -0
  50. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_hitori.cpython-310-pytest-9.0.2.pyc +0 -0
  51. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_jigsaw_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  52. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_juosan.cpython-310-pytest-9.0.2.pyc +0 -0
  53. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_kakkuru.cpython-310-pytest-9.0.2.pyc +0 -0
  54. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_kakurasu.cpython-310-pytest-9.0.2.pyc +0 -0
  55. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_kakuro.cpython-310-pytest-9.0.2.pyc +0 -0
  56. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_ken_ken.cpython-310-pytest-9.0.2.pyc +0 -0
  57. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_killer_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  58. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_koburin.cpython-310-pytest-9.0.2.pyc +0 -0
  59. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_kuromasu.cpython-310-pytest-9.0.2.pyc +0 -0
  60. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_kuroshuto.cpython-310-pytest-9.0.2.pyc +0 -0
  61. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_linesweeper.cpython-310-pytest-9.0.2.pyc +0 -0
  62. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_lits.cpython-310-pytest-9.0.2.pyc +0 -0
  63. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_magnetic.cpython-310-pytest-9.0.2.pyc +0 -0
  64. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_makaro.cpython-310-pytest-9.0.2.pyc +0 -0
  65. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_masyu.cpython-310-pytest-9.0.2.pyc +0 -0
  66. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_mathrax.cpython-310-pytest-9.0.2.pyc +0 -0
  67. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_minesweeper.cpython-310-pytest-9.0.2.pyc +0 -0
  68. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_moon_sun.cpython-310-pytest-9.0.2.pyc +0 -0
  69. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_mosaic.cpython-310-pytest-9.0.2.pyc +0 -0
  70. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_munraito.cpython-310-pytest-9.0.2.pyc +0 -0
  71. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_nawabari.cpython-310-pytest-9.0.2.pyc +0 -0
  72. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_nondango.cpython-310-pytest-9.0.2.pyc +0 -0
  73. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_nonogram.cpython-310-pytest-9.0.2.pyc +0 -0
  74. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_norinori.cpython-310-pytest-9.0.2.pyc +0 -0
  75. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_number_cross.cpython-310-pytest-9.0.2.pyc +0 -0
  76. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_one_to_x.cpython-310-pytest-9.0.2.pyc +0 -0
  77. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_paint_area.cpython-310-pytest-9.0.2.pyc +0 -0
  78. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_patchwork.cpython-310-pytest-9.0.2.pyc +0 -0
  79. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_pfeilzahlen.cpython-310-pytest-9.0.2.pyc +0 -0
  80. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_pills.cpython-310-pytest-9.0.2.pyc +0 -0
  81. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_putteria.cpython-310-pytest-9.0.2.pyc +0 -0
  82. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_regional_yajilin.cpython-310-pytest-9.0.2.pyc +0 -0
  83. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_renban.cpython-310-pytest-9.0.2.pyc +0 -0
  84. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_samurai_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  85. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_shikaku.cpython-310-pytest-9.0.2.pyc +0 -0
  86. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_shingoki.cpython-310-pytest-9.0.2.pyc +0 -0
  87. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_shogun_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  88. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_simple_loop.cpython-310-pytest-9.0.2.pyc +0 -0
  89. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_skyscraper.cpython-310-pytest-9.0.2.pyc +0 -0
  90. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_slitherlink.cpython-310-pytest-9.0.2.pyc +0 -0
  91. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_snake.cpython-310-pytest-9.0.2.pyc +0 -0
  92. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_sohei_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  93. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_square_o.cpython-310-pytest-9.0.2.pyc +0 -0
  94. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_starbattle.cpython-310-pytest-9.0.2.pyc +0 -0
  95. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_stitches.cpython-310-pytest-9.0.2.pyc +0 -0
  96. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_str8t.cpython-310-pytest-9.0.2.pyc +0 -0
  97. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  98. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_suguru.cpython-310-pytest-9.0.2.pyc +0 -0
  99. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_sumo_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  100. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_tenner_grid.cpython-310-pytest-9.0.2.pyc +0 -0
  101. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_tent.cpython-310-pytest-9.0.2.pyc +0 -0
  102. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_terra_x.cpython-310-pytest-9.0.2.pyc +0 -0
  103. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_thermometer.cpython-310-pytest-9.0.2.pyc +0 -0
  104. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_tile_paint.cpython-310-pytest-9.0.2.pyc +0 -0
  105. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_trinairo.cpython-310-pytest-9.0.2.pyc +0 -0
  106. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_windmill_sudoku.cpython-310-pytest-9.0.2.pyc +0 -0
  107. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_yajikabe.cpython-310-pytest-9.0.2.pyc +0 -0
  108. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_yajilin.cpython-310-pytest-9.0.2.pyc +0 -0
  109. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/__pycache__/test_yin_yang.cpython-310-pytest-9.0.2.pyc +0 -0
  110. puzzlekit-0.3.3/tests/formats/__pycache__/conftest.cpython-310-pytest-9.0.2.pyc +0 -0
  111. puzzlekit-0.3.3/tests/formats/__pycache__/test_cross_format.cpython-310-pytest-9.0.2.pyc +0 -0
  112. puzzlekit-0.3.3/tests/formats/__pycache__/test_roundtrip.cpython-310-pytest-9.0.2.pyc +0 -0
  113. puzzlekit-0.3.3/tests/formats/conftest.py +173 -0
  114. puzzlekit-0.3.3/tests/formats/test_cross_format.py +23 -0
  115. puzzlekit-0.3.3/tests/formats/test_roundtrip.py +96 -0
  116. puzzlekit-0.3.2/src/puzzlekit/__init__.py +0 -75
  117. puzzlekit-0.3.2/src/puzzlekit/core/puzzlink.py +0 -536
  118. puzzlekit-0.3.2/tests/__pycache__/__init__.cpython-310.pyc +0 -0
  119. puzzlekit-0.3.2/tests/__pycache__/test_battleship.cpython-310-pytest-9.0.2.pyc +0 -0
  120. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/LICENSE +0 -0
  121. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/MANIFEST.in +0 -0
  122. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/setup.cfg +0 -0
  123. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/core/__init__.py +0 -0
  124. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/core/direction.py +0 -0
  125. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/core/docs_template.py +0 -0
  126. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/core/grid.py +0 -0
  127. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/core/position.py +0 -0
  128. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/core/regionsgrid.py +0 -0
  129. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/core/result.py +0 -0
  130. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/core/solver.py +0 -0
  131. {puzzlekit-0.3.2/src/puzzlekit/utils → puzzlekit-0.3.3/src/puzzlekit/formats}/__init__.py +0 -0
  132. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/parsers/__init__.py +0 -0
  133. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/parsers/common.py +0 -0
  134. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/parsers/registry.py +0 -0
  135. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/__init__.py +0 -0
  136. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/abc_end_view.py +0 -0
  137. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/akari.py +0 -0
  138. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/aqre.py +0 -0
  139. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/balance_loop.py +0 -0
  140. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/battleship.py +0 -0
  141. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/binairo.py +0 -0
  142. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/bosanowa.py +0 -0
  143. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/bricks.py +0 -0
  144. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/buraitoraito.py +0 -0
  145. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/butterfly_sudoku.py +0 -0
  146. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/canal_view.py +0 -0
  147. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/castle_wall.py +0 -0
  148. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/cave.py +0 -0
  149. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/clueless_1_sudoku.py +0 -0
  150. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/clueless_2_sudoku.py +0 -0
  151. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/cojun.py +0 -0
  152. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/country_road.py +0 -0
  153. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/creek.py +0 -0
  154. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/detour.py +0 -0
  155. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/diff_neighbors.py +0 -0
  156. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/dominos.py +0 -0
  157. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/dotchi_loop.py +0 -0
  158. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/double_back.py +0 -0
  159. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/entry_exit.py +0 -0
  160. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/eulero.py +0 -0
  161. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/even_odd_sudoku.py +0 -0
  162. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/fobidoshi.py +0 -0
  163. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/fuzuli.py +0 -0
  164. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/gappy.py +0 -0
  165. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/gattai_8_sudoku.py +0 -0
  166. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/geradeweg.py +0 -0
  167. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/grand_tour.py +0 -0
  168. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/hakoiri.py +0 -0
  169. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/hakyuu.py +0 -0
  170. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/heyawake.py +0 -0
  171. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/hidoku.py +0 -0
  172. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/hitori.py +0 -0
  173. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/jigsaw_sudoku.py +0 -0
  174. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/juosan.py +0 -0
  175. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/kakkuru.py +0 -0
  176. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/kakurasu.py +0 -0
  177. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/kakuro.py +0 -0
  178. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/ken_ken.py +0 -0
  179. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/killer_sudoku.py +0 -0
  180. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/koburin.py +0 -0
  181. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/kuromasu.py +0 -0
  182. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/kuroshuto.py +0 -0
  183. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/kurotto.py +0 -0
  184. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/linesweeper.py +0 -0
  185. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/lits.py +0 -0
  186. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/magnetic.py +0 -0
  187. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/makaro.py +0 -0
  188. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/masyu.py +0 -0
  189. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/mathrax.py +0 -0
  190. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/mejilink.py +0 -0
  191. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/mid_loop.py +0 -0
  192. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/minesweeper.py +0 -0
  193. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/moon_sun.py +0 -0
  194. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/mosaic.py +0 -0
  195. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/munraito.py +0 -0
  196. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/nanro.py +0 -0
  197. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/nawabari.py +0 -0
  198. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/nondango.py +0 -0
  199. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/nonogram.py +0 -0
  200. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/norinori.py +0 -0
  201. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/number_cross.py +0 -0
  202. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/nurikabe.py +0 -0
  203. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/nurimisaki.py +0 -0
  204. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/one_to_x.py +0 -0
  205. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/paint_area.py +0 -0
  206. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/patchwork.py +0 -0
  207. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/pfeilzahlen.py +0 -0
  208. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/pills.py +0 -0
  209. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/pipes.py +0 -0
  210. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/putteria.py +0 -0
  211. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/regional_yajilin.py +0 -0
  212. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/renban.py +0 -0
  213. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/samurai_sudoku.py +0 -0
  214. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/shikaku.py +0 -0
  215. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/shimaguni.py +0 -0
  216. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/shingoki.py +0 -0
  217. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/shirokuro.py +0 -0
  218. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/shogun_sudoku.py +0 -0
  219. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/shugaku.py +0 -0
  220. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/simple_loop.py +0 -0
  221. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/skyscraper.py +0 -0
  222. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/slitherlink.py +0 -0
  223. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/slitherlink_duality.py +0 -0
  224. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/snake.py +0 -0
  225. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/sohei_sudoku.py +0 -0
  226. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/square_o.py +0 -0
  227. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/starbattle.py +0 -0
  228. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/stitches.py +0 -0
  229. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/str8t.py +0 -0
  230. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/sudoku.py +0 -0
  231. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/suguru.py +0 -0
  232. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/sumo_sudoku.py +0 -0
  233. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/tatamibari.py +0 -0
  234. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/tenner_grid.py +0 -0
  235. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/tent.py +0 -0
  236. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/terra_x.py +0 -0
  237. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/thermometer.py +0 -0
  238. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/tile_paint.py +0 -0
  239. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/trinairo.py +0 -0
  240. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/usoone.py +0 -0
  241. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/windmill_sudoku.py +0 -0
  242. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/yajikabe.py +0 -0
  243. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/yajilin.py +0 -0
  244. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/solvers/yin_yang.py +0 -0
  245. {puzzlekit-0.3.2/tests → puzzlekit-0.3.3/src/puzzlekit/utils}/__init__.py +0 -0
  246. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/utils/file_loader.py +0 -0
  247. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/utils/name_utils.py +0 -0
  248. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/utils/ortools_utils.py +0 -0
  249. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/utils/puzzle_math.py +0 -0
  250. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/verifiers/__init__.py +0 -0
  251. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/verifiers/common.py +0 -0
  252. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/viz/__init__.py +0 -0
  253. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/viz/base.py +0 -0
  254. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit/viz/drawers.py +0 -0
  255. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit.egg-info/dependency_links.txt +0 -0
  256. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit.egg-info/requires.txt +0 -0
  257. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/src/puzzlekit.egg-info/top_level.txt +0 -0
  258. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/metadata_test_utils.py +0 -0
  259. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_abc_end_view.py +0 -0
  260. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_akari.py +0 -0
  261. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_balance_loop.py +0 -0
  262. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_battleship.py +0 -0
  263. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_binairo.py +0 -0
  264. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_bosanowa.py +0 -0
  265. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_bricks.py +0 -0
  266. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_buraitoraito.py +0 -0
  267. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_butterfly_sudoku.py +0 -0
  268. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_castle_wall.py +0 -0
  269. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_cave.py +0 -0
  270. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_clueless_1_sudoku.py +0 -0
  271. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_clueless_2_sudoku.py +0 -0
  272. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_country_road.py +0 -0
  273. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_creek.py +0 -0
  274. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_detour.py +0 -0
  275. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_diff_neighbors.py +0 -0
  276. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_dominos.py +0 -0
  277. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_dotchi_loop.py +0 -0
  278. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_double_back.py +0 -0
  279. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_entry_exit.py +0 -0
  280. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_eulero.py +0 -0
  281. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_even_odd_sudoku.py +0 -0
  282. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_fobidoshi.py +0 -0
  283. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_fuzuli.py +0 -0
  284. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_gappy.py +0 -0
  285. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_gattai_8_sudoku.py +0 -0
  286. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_grand_tour.py +0 -0
  287. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_grid.py +0 -0
  288. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_hakoiri.py +0 -0
  289. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_hakyuu.py +0 -0
  290. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_heyawake.py +0 -0
  291. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_hidoku.py +0 -0
  292. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_hitori.py +0 -0
  293. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_jigsaw_sudoku.py +0 -0
  294. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_juosan.py +0 -0
  295. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_kakkuru.py +0 -0
  296. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_kakurasu.py +0 -0
  297. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_kakuro.py +0 -0
  298. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_ken_ken.py +0 -0
  299. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_killer_sudoku.py +0 -0
  300. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_koburin.py +0 -0
  301. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_kuromasu.py +0 -0
  302. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_kuroshuto.py +0 -0
  303. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_linesweeper.py +0 -0
  304. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_lits.py +0 -0
  305. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_magnetic.py +0 -0
  306. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_makaro.py +0 -0
  307. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_masyu.py +0 -0
  308. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_mathrax.py +0 -0
  309. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_minesweeper.py +0 -0
  310. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_moon_sun.py +0 -0
  311. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_mosaic.py +0 -0
  312. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_munraito.py +0 -0
  313. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_nawabari.py +0 -0
  314. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_nondango.py +0 -0
  315. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_nonogram.py +0 -0
  316. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_norinori.py +0 -0
  317. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_number_cross.py +0 -0
  318. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_one_to_x.py +0 -0
  319. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_paint_area.py +0 -0
  320. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_patchwork.py +0 -0
  321. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_pfeilzahlen.py +0 -0
  322. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_pills.py +0 -0
  323. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_putteria.py +0 -0
  324. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_regional_yajilin.py +0 -0
  325. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_renban.py +0 -0
  326. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_samurai_sudoku.py +0 -0
  327. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_shikaku.py +0 -0
  328. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_shingoki.py +0 -0
  329. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_shogun_sudoku.py +0 -0
  330. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_simple_loop.py +0 -0
  331. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_skyscraper.py +0 -0
  332. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_slitherlink.py +0 -0
  333. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_snake.py +0 -0
  334. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_sohei_sudoku.py +0 -0
  335. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_square_o.py +0 -0
  336. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_starbattle.py +0 -0
  337. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_stitches.py +0 -0
  338. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_str8t.py +0 -0
  339. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_sudoku.py +0 -0
  340. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_suguru.py +0 -0
  341. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_sumo_sudoku.py +0 -0
  342. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_tenner_grid.py +0 -0
  343. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_tent.py +0 -0
  344. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_terra_x.py +0 -0
  345. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_thermometer.py +0 -0
  346. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_tile_paint.py +0 -0
  347. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_trinairo.py +0 -0
  348. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_windmill_sudoku.py +0 -0
  349. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_yajikabe.py +0 -0
  350. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_yajilin.py +0 -0
  351. {puzzlekit-0.3.2 → puzzlekit-0.3.3}/tests/test_yin_yang.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: puzzlekit
3
- Version: 0.3.2
4
- Summary: A comprehensive logic puzzle solver (100+) based on Google OR-Tools. e.g., solvers for Nonogram, Slitherlink, Akari, Yajilin, Hitori and Sudoku-variants.
3
+ Version: 0.3.3
4
+ Summary: 100+ logic puzzle solvers on Google OR-Tools (e.g., yajilin, slitherlink, nonogram), with bidirectional conversion between puzz.link and Penpa+ URLs for supported genres (shared IR).
5
5
  Author-email: SmilingWayne <xiaoxiaowayne@gmail.com>
6
6
  License: MIT License
7
7
 
@@ -28,7 +28,7 @@ License: MIT License
28
28
  Project-URL: Homepage, https://github.com/SmilingWayne/PuzzleSolver
29
29
  Project-URL: Repository, https://github.com/SmilingWayne/PuzzleSolver
30
30
  Project-URL: Issues, https://github.com/SmilingWayne/PuzzleSolver/issues
31
- Keywords: puzzle,solver,logic,cp-sat,efficient,python,nonogram,slitherlink,yajilin,hitori,sudoku,akari
31
+ Keywords: puzzle,solver,logic,cp-sat,python,nonogram,slitherlink,yajilin,sudoku,puzzlink,penpa,url-conversion
32
32
  Classifier: Development Status :: 3 - Alpha
33
33
  Classifier: Intended Audience :: Developers
34
34
  Classifier: Intended Audience :: Science/Research
@@ -55,7 +55,7 @@ This repository provides **100+ useful, efficient and problem‑specific solvers
55
55
 
56
56
  For simplicity, the dataset is removed to [puzzlekit-dataset](https://github.com/SmilingWayne/puzzlekit-dataset) repo. The structured dataset contains 41k+ instances covering 130+ specific and popular puzzle types (e.g. Nonogram, Slitherlink, Akari, Fillomino, Hitori, Kakuro, Kakuro), mostly from [Raetsel's Janko](https://www.janko.at/Raetsel/index.htm) and [puzz.link](https://puzz.link). The details are listed in the table below.
57
57
 
58
-
58
+ This repo also provides **bidirectional conversion between [puzz.link](https://puzz.link) and [Penpa+](https://swaroopg92.github.io/penpa-edit/) puzzle URLs** for supported genres (19 for now) via a shared intermediate representation. puzz.link-like links from common mirrors (e.g., `pzplus.tck.mn`, `pzv.jp`) are also accepted.
59
59
 
60
60
  <details>
61
61
  <summary><strong>Table of puzzles, datasets and solvers.</strong></summary>
@@ -215,6 +215,37 @@ For simplicity, the dataset is removed to [puzzlekit-dataset](https://github.com
215
215
 
216
216
  </details>
217
217
 
218
+ <details>
219
+ <summary><strong>Supported puzzle types for URL interchange</strong>
220
+ </summary>
221
+
222
+ > (canonical IR name, puzz.link token, aliases, Penpa genre tag)
223
+
224
+ | Canonical (IR) | puzz.link token | puzz.link aliases | Penpa genre tag |
225
+ | -------------- | --------------- | ------------------------------- | --------------------- |
226
+ | `aqre` | `aqre` | aqre | `aqre` |
227
+ | `ayeheya` | `ayeheya` | ayeheya | `ayeheya (ekawayeh)` |
228
+ | `castle` | `castle` | castle | `castlewall` |
229
+ | `country` | `country` | country | `country road` |
230
+ | `hebi` | `hebi` | hebi, snakes | `hebi-ichigo` |
231
+ | `heyawake` | `heyawake` | heyawake, heyawacky, heyawack | `heyawake` |
232
+ | `kurochute` | `kurochute` | kurochute, kuroshuto, kurochuto | `kurochute` |
233
+ | `kurodoko` | `kurodoko` | kurodoko | `kurodoko` |
234
+ | `kurotto` | `kurotto` | kurotto | `kurotto` |
235
+ | `masyu` | `masyu` | masyu, mashu, pearl | `masyu` |
236
+ | `moonsun` | `moonsun` | moonsun | `moon or sun` |
237
+ | `nonogram` | `nonogram` | nonogram | `nonogram` |
238
+ | `nurikabe` | `nurikabe` | nurikabe | `nurikabe` |
239
+ | `nurimisaki` | `nurimisaki` | nurimisaki | `nurimisaki` |
240
+ | `shikaku` | `shikaku` | shikaku | `shikaku` |
241
+ | `shimaguni` | `shimaguni` | shimaguni | `shimaguni (islands)` |
242
+ | `slitherlink` | `slither` | slitherlink | `slitherlink` |
243
+ | `stostone` | `stostone` | stostone | `stostone` |
244
+ | `yajilin` | `yajilin` | yajilin, yajirin | `yajilin` |
245
+
246
+ </details>
247
+
248
+
218
249
 
219
250
  <details>
220
251
  <summary><strong>Gallery of some puzzles (not complete!)</strong></summary>
@@ -291,6 +322,33 @@ python scripts/benchmark.py -a
291
322
 
292
323
  Currently it will take ~30 min to solve all 30k+ instances available.
293
324
 
325
+ ---
326
+
327
+ If you want to try the bi-directional conversion between penpa+ and puzz.link, follow the quick tour:
328
+
329
+
330
+ ```python
331
+ import puzzlekit
332
+
333
+ # 1st method
334
+ ir = puzzlekit.decode("https://puzz.link/p?slither/10/10/g188227cl1dg367bdcg3ddgbhdgd1agbd760dg2cl633661d")
335
+ penpa_url = puzzlekit.encode(ir, "penpa")
336
+ print(penpa_url)
337
+ # get:
338
+ # https://swaroopg92.github.io/penpa-edit/#m=edit&p=7VdtT9swEP7Or0...
339
+
340
+
341
+ # 2nd method (recommend)
342
+ penpa_url = "YOUR_PENPA_URL" # both full URL or `m=edit&p=...` are okay
343
+ puzzlink_url = puzzlekit.convert(penpa_url, "puzzlink")
344
+ print(puzzlink_url)
345
+ # get:
346
+ # https://puzz.link/p?slither/10/10/b86ag68dg127bg62aldg8dad8bgdl26dg722cg68dg88b3
347
+ ```
348
+
349
+ See also `scripts/quick_start.py` for a runnable sample.
350
+
351
+
294
352
  ## Roadmap
295
353
 
296
354
  - [x] 130+ Puzzle Solvers & 40k+ Dataset.
@@ -1,61 +1,10 @@
1
- Metadata-Version: 2.4
2
- Name: puzzlekit
3
- Version: 0.3.2
4
- Summary: A comprehensive logic puzzle solver (100+) based on Google OR-Tools. e.g., solvers for Nonogram, Slitherlink, Akari, Yajilin, Hitori and Sudoku-variants.
5
- Author-email: SmilingWayne <xiaoxiaowayne@gmail.com>
6
- License: MIT License
7
-
8
- Copyright (c) 2025 SmilingWayne
9
-
10
- Permission is hereby granted, free of charge, to any person obtaining a copy
11
- of this software and associated documentation files (the "Software"), to deal
12
- in the Software without restriction, including without limitation the rights
13
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
- copies of the Software, and to permit persons to whom the Software is
15
- furnished to do so, subject to the following conditions:
16
-
17
- The above copyright notice and this permission notice shall be included in all
18
- copies or substantial portions of the Software.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
- SOFTWARE.
27
-
28
- Project-URL: Homepage, https://github.com/SmilingWayne/PuzzleSolver
29
- Project-URL: Repository, https://github.com/SmilingWayne/PuzzleSolver
30
- Project-URL: Issues, https://github.com/SmilingWayne/PuzzleSolver/issues
31
- Keywords: puzzle,solver,logic,cp-sat,efficient,python,nonogram,slitherlink,yajilin,hitori,sudoku,akari
32
- Classifier: Development Status :: 3 - Alpha
33
- Classifier: Intended Audience :: Developers
34
- Classifier: Intended Audience :: Science/Research
35
- Classifier: License :: OSI Approved :: MIT License
36
- Classifier: Programming Language :: Python :: 3
37
- Classifier: Programming Language :: Python :: 3.10
38
- Classifier: Programming Language :: Python :: 3.11
39
- Classifier: Programming Language :: Python :: 3.12
40
- Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
41
- Classifier: Topic :: Games/Entertainment :: Puzzle Games
42
- Classifier: Operating System :: OS Independent
43
- Requires-Python: >=3.10
44
- Description-Content-Type: text/markdown
45
- License-File: LICENSE
46
- Requires-Dist: numpy
47
- Requires-Dist: ortools>=9.6
48
- Requires-Dist: matplotlib
49
- Requires-Dist: typeguard
50
- Dynamic: license-file
51
-
52
1
  # Puzzle Kit
53
2
 
54
3
  This repository provides **100+ useful, efficient and problem‑specific solvers** for a variety of **logic puzzles**. The underlying solving engine is the open‑source Google [OR-Tools](https://developers.google.cn/optimization) CP-SAT solver. For more details of puzzles and their input format, you can refer to [docs of puzzlekit](https://smilingwayne.github.io/PuzzleSolver/).
55
4
 
56
5
  For simplicity, the dataset is removed to [puzzlekit-dataset](https://github.com/SmilingWayne/puzzlekit-dataset) repo. The structured dataset contains 41k+ instances covering 130+ specific and popular puzzle types (e.g. Nonogram, Slitherlink, Akari, Fillomino, Hitori, Kakuro, Kakuro), mostly from [Raetsel's Janko](https://www.janko.at/Raetsel/index.htm) and [puzz.link](https://puzz.link). The details are listed in the table below.
57
6
 
58
-
7
+ This repo also provides **bidirectional conversion between [puzz.link](https://puzz.link) and [Penpa+](https://swaroopg92.github.io/penpa-edit/) puzzle URLs** for supported genres (19 for now) via a shared intermediate representation. puzz.link-like links from common mirrors (e.g., `pzplus.tck.mn`, `pzv.jp`) are also accepted.
59
8
 
60
9
  <details>
61
10
  <summary><strong>Table of puzzles, datasets and solvers.</strong></summary>
@@ -215,6 +164,37 @@ For simplicity, the dataset is removed to [puzzlekit-dataset](https://github.com
215
164
 
216
165
  </details>
217
166
 
167
+ <details>
168
+ <summary><strong>Supported puzzle types for URL interchange</strong>
169
+ </summary>
170
+
171
+ > (canonical IR name, puzz.link token, aliases, Penpa genre tag)
172
+
173
+ | Canonical (IR) | puzz.link token | puzz.link aliases | Penpa genre tag |
174
+ | -------------- | --------------- | ------------------------------- | --------------------- |
175
+ | `aqre` | `aqre` | aqre | `aqre` |
176
+ | `ayeheya` | `ayeheya` | ayeheya | `ayeheya (ekawayeh)` |
177
+ | `castle` | `castle` | castle | `castlewall` |
178
+ | `country` | `country` | country | `country road` |
179
+ | `hebi` | `hebi` | hebi, snakes | `hebi-ichigo` |
180
+ | `heyawake` | `heyawake` | heyawake, heyawacky, heyawack | `heyawake` |
181
+ | `kurochute` | `kurochute` | kurochute, kuroshuto, kurochuto | `kurochute` |
182
+ | `kurodoko` | `kurodoko` | kurodoko | `kurodoko` |
183
+ | `kurotto` | `kurotto` | kurotto | `kurotto` |
184
+ | `masyu` | `masyu` | masyu, mashu, pearl | `masyu` |
185
+ | `moonsun` | `moonsun` | moonsun | `moon or sun` |
186
+ | `nonogram` | `nonogram` | nonogram | `nonogram` |
187
+ | `nurikabe` | `nurikabe` | nurikabe | `nurikabe` |
188
+ | `nurimisaki` | `nurimisaki` | nurimisaki | `nurimisaki` |
189
+ | `shikaku` | `shikaku` | shikaku | `shikaku` |
190
+ | `shimaguni` | `shimaguni` | shimaguni | `shimaguni (islands)` |
191
+ | `slitherlink` | `slither` | slitherlink | `slitherlink` |
192
+ | `stostone` | `stostone` | stostone | `stostone` |
193
+ | `yajilin` | `yajilin` | yajilin, yajirin | `yajilin` |
194
+
195
+ </details>
196
+
197
+
218
198
 
219
199
  <details>
220
200
  <summary><strong>Gallery of some puzzles (not complete!)</strong></summary>
@@ -291,6 +271,33 @@ python scripts/benchmark.py -a
291
271
 
292
272
  Currently it will take ~30 min to solve all 30k+ instances available.
293
273
 
274
+ ---
275
+
276
+ If you want to try the bi-directional conversion between penpa+ and puzz.link, follow the quick tour:
277
+
278
+
279
+ ```python
280
+ import puzzlekit
281
+
282
+ # 1st method
283
+ ir = puzzlekit.decode("https://puzz.link/p?slither/10/10/g188227cl1dg367bdcg3ddgbhdgd1agbd760dg2cl633661d")
284
+ penpa_url = puzzlekit.encode(ir, "penpa")
285
+ print(penpa_url)
286
+ # get:
287
+ # https://swaroopg92.github.io/penpa-edit/#m=edit&p=7VdtT9swEP7Or0...
288
+
289
+
290
+ # 2nd method (recommend)
291
+ penpa_url = "YOUR_PENPA_URL" # both full URL or `m=edit&p=...` are okay
292
+ puzzlink_url = puzzlekit.convert(penpa_url, "puzzlink")
293
+ print(puzzlink_url)
294
+ # get:
295
+ # https://puzz.link/p?slither/10/10/b86ag68dg127bg62aldg8dad8bgdl26dg722cg68dg88b3
296
+ ```
297
+
298
+ See also `scripts/quick_start.py` for a runnable sample.
299
+
300
+
294
301
  ## Roadmap
295
302
 
296
303
  - [x] 130+ Puzzle Solvers & 40k+ Dataset.
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "puzzlekit"
7
- version = "0.3.2"
8
- description = "A comprehensive logic puzzle solver (100+) based on Google OR-Tools. e.g., solvers for Nonogram, Slitherlink, Akari, Yajilin, Hitori and Sudoku-variants."
7
+ version = "0.3.3"
8
+ description = "100+ logic puzzle solvers on Google OR-Tools (e.g., yajilin, slitherlink, nonogram), with bidirectional conversion between puzz.link and Penpa+ URLs for supported genres (shared IR)."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  authors = [{name = "SmilingWayne", email = "xiaoxiaowayne@gmail.com"}]
12
12
  license = {file = "LICENSE"}
13
- keywords = ["puzzle", "solver", "logic", "cp-sat", "efficient", "python", "nonogram", "slitherlink", "yajilin", "hitori", "sudoku", "akari"]
13
+ keywords = ["puzzle", "solver", "logic", "cp-sat", "python", "nonogram", "slitherlink", "yajilin", "sudoku", "puzzlink", "penpa", "url-conversion"]
14
14
  classifiers = [
15
15
  "Development Status :: 3 - Alpha",
16
16
  "Intended Audience :: Developers",
@@ -0,0 +1,224 @@
1
+ from typing import Dict, Any, Optional, Union
2
+ from puzzlekit.solvers import get_solver_class
3
+ from puzzlekit.parsers.registry import get_parser
4
+ from puzzlekit.formats.base import PuzzleInstance
5
+ from puzzlekit.formats.puzzlink_converter import PuzzlinkConverter
6
+ from puzzlekit.formats.penpa_converter import (
7
+ PenpaConverter,
8
+ PENPA_PREFIX,
9
+ PENPA_URLPREFIX,
10
+ PenpaDecodeError,
11
+ )
12
+
13
+
14
+ _FORMAT_ALIASES = {
15
+ "puzzlink": "puzzlink",
16
+ "pzl": "puzzlink",
17
+ "penpa": "penpa",
18
+ "ppa": "penpa",
19
+ "ir": "ir",
20
+ "instance": "ir",
21
+ "puzzleinstance": "ir",
22
+ }
23
+
24
+
25
+ def _normalize_format_name(name: str) -> str:
26
+ if not isinstance(name, str) or not name.strip():
27
+ raise ValueError("Format name must be a non-empty string.")
28
+ key = name.strip().lower()
29
+ if key not in _FORMAT_ALIASES:
30
+ raise ValueError(f"Unknown format '{name}'. Supported: puzzlink, penpa, ir.")
31
+ return _FORMAT_ALIASES[key]
32
+
33
+
34
+ def _normalize_penpa_source(source: str) -> str:
35
+ s = source.strip()
36
+ if s.startswith("#"):
37
+ s = s[1:]
38
+ if s.startswith(PENPA_PREFIX):
39
+ return s
40
+ if s.startswith(PENPA_URLPREFIX):
41
+ frag = s.split("#", 1)[1] if "#" in s else ""
42
+ if frag.startswith("#"):
43
+ frag = frag[1:]
44
+ return frag if frag.startswith(PENPA_PREFIX) else f"{PENPA_PREFIX}{frag}"
45
+ return s
46
+
47
+
48
+ def _detect_source_format(source: str) -> str:
49
+ s = source.strip()
50
+ if "puzz.link/p?" in s:
51
+ return "puzzlink"
52
+ if s.startswith(PENPA_PREFIX) or s.startswith("#" + PENPA_PREFIX) or PENPA_URLPREFIX in s:
53
+ return "penpa"
54
+ raise ValueError("Cannot detect source format. Please pass source_format explicitly.")
55
+
56
+
57
+ def _build_converter(fmt: str, converter_config: Optional[Dict[str, Any]] = None):
58
+ if fmt == "puzzlink":
59
+ return PuzzlinkConverter(converter_config or {})
60
+ if fmt == "penpa":
61
+ return PenpaConverter(converter_config or {})
62
+ raise ValueError(f"Unsupported converter format '{fmt}'.")
63
+
64
+ def solve(
65
+ source: Union[str, Dict[str, Any]],
66
+ puzzle_type: str,
67
+ **kwargs
68
+ ) -> Any:
69
+ """
70
+ Unified entry point for solving puzzles.
71
+
72
+ Args:
73
+ source:
74
+ - A string containing the raw puzzle data (with headers, e.g. "9 9\n...").
75
+ - A dictionary (pre-parsed data).
76
+ puzzle_type: The snake_case type name (e.g., 'akari', 'fuzuli').
77
+ show: Whether to visualize the result.
78
+ **kwargs: Overrides for solver parameters.
79
+ """
80
+
81
+ # --- 1. (Parsing) ---
82
+ init_params = {}
83
+
84
+ if isinstance(source, dict):
85
+ init_params = source.copy()
86
+
87
+ elif isinstance(source, str):
88
+ try:
89
+ target_parser = get_parser(puzzle_type)
90
+ parsed_data = target_parser(source.strip())
91
+
92
+ if parsed_data is None:
93
+ raise ValueError(f"Parser returned None for type '{puzzle_type}'")
94
+
95
+ init_params.update(parsed_data)
96
+ except ValueError as e:
97
+ raise ValueError(f"Parsing failed for type '{puzzle_type}': {e}")
98
+
99
+ else:
100
+ raise TypeError(f"Source must be dict or raw string, got {type(source)}")
101
+
102
+ init_params.update(kwargs)
103
+
104
+ try:
105
+ SolverClass = get_solver_class(puzzle_type)
106
+ except ValueError as e:
107
+ raise ValueError(f"Unknown puzzle type '{puzzle_type}'.") from e
108
+
109
+
110
+ solver_instance = SolverClass(**init_params)
111
+
112
+ result = solver_instance.solve()
113
+
114
+ return result
115
+
116
+ def solver(puzzle_type: str, data: Dict[str, Any] = None, **kwargs) -> Any:
117
+ # return solve(source=data, puzzle_type=puzzle_type, **kwargs)
118
+ init_params = {}
119
+
120
+ if isinstance(data, dict):
121
+ init_params = data.copy()
122
+ else:
123
+ raise TypeError(f"Source must be dict or raw string, got {type(data)}")
124
+
125
+ init_params.update(kwargs)
126
+
127
+ try:
128
+ SolverClass = get_solver_class(puzzle_type)
129
+ except ValueError as e:
130
+ raise ValueError(f"Unknown puzzle type '{puzzle_type}'.") from e
131
+ return SolverClass(**init_params)
132
+
133
+
134
+ def decode(
135
+ source: str,
136
+ source_format: Optional[str] = None,
137
+ converter_config: Optional[Dict[str, Any]] = None,
138
+ ) -> PuzzleInstance:
139
+ """
140
+ Decode puzzle URL/text into PuzzleInstance (IR).
141
+
142
+ Args:
143
+ source: puzz.link URL, penpa URL, or penpa payload (`m=edit&p=...`).
144
+ source_format: Optional explicit source format ('puzzlink' or 'penpa').
145
+ converter_config: Optional converter config dict.
146
+ """
147
+ if not isinstance(source, str):
148
+ raise TypeError(f"source must be str, got {type(source)}")
149
+
150
+ fmt = _normalize_format_name(source_format) if source_format else _detect_source_format(source)
151
+ if fmt == "ir":
152
+ raise ValueError("decode(source_format='ir') is not valid.")
153
+
154
+ converter = _build_converter(fmt, converter_config)
155
+ normalized_source = _normalize_penpa_source(source) if fmt == "penpa" else source
156
+ return converter.decode(normalized_source)
157
+
158
+
159
+ def encode(
160
+ instance: PuzzleInstance,
161
+ target_format: str,
162
+ converter_config: Optional[Dict[str, Any]] = None,
163
+ ) -> str:
164
+ """
165
+ Encode PuzzleInstance (IR) into target format URL/text.
166
+
167
+ Args:
168
+ instance: PuzzleInstance IR.
169
+ target_format: 'puzzlink' or 'penpa'.
170
+ converter_config: Optional converter config dict.
171
+ """
172
+ if not isinstance(instance, PuzzleInstance):
173
+ raise TypeError(f"instance must be PuzzleInstance, got {type(instance)}")
174
+
175
+ fmt = _normalize_format_name(target_format)
176
+ if fmt == "ir":
177
+ raise ValueError("encode(target_format='ir') is not valid.")
178
+
179
+ converter = _build_converter(fmt, converter_config)
180
+ return converter.encode(instance)
181
+
182
+
183
+ def convert(
184
+ source: Union[str, PuzzleInstance],
185
+ target_format: str,
186
+ source_format: Optional[str] = None,
187
+ converter_config: Optional[Dict[str, Any]] = None,
188
+ decode_converter_config: Optional[Dict[str, Any]] = None,
189
+ encode_converter_config: Optional[Dict[str, Any]] = None,
190
+ ) -> Union[str, PuzzleInstance]:
191
+ """
192
+ Convert between puzzlink/penpa/IR.
193
+
194
+ Examples:
195
+ - URL -> IR: convert(url, "ir")
196
+ - puzzlink -> penpa: convert(url, "penpa")
197
+ - penpa -> puzzlink: convert(url, "puzzlink")
198
+ - IR -> puzzlink: convert(ir, "puzzlink")
199
+
200
+ Notes:
201
+ - `converter_config` is kept for backward compatibility and applies to both
202
+ decode/encode when side-specific configs are not provided.
203
+ - `decode_converter_config` and `encode_converter_config` let callers pass
204
+ different settings per stage in a two-step conversion.
205
+ """
206
+ dst = _normalize_format_name(target_format)
207
+ decode_cfg = decode_converter_config if decode_converter_config is not None else converter_config
208
+ encode_cfg = encode_converter_config if encode_converter_config is not None else converter_config
209
+
210
+ if isinstance(source, PuzzleInstance):
211
+ if dst == "ir":
212
+ return source
213
+ return encode(source, dst, converter_config=encode_cfg)
214
+
215
+ if not isinstance(source, str):
216
+ raise TypeError(f"source must be str or PuzzleInstance, got {type(source)}")
217
+
218
+ ir = decode(source, source_format=source_format, converter_config=decode_cfg)
219
+ if dst == "ir":
220
+ return ir
221
+ return encode(ir, dst, converter_config=encode_cfg)
222
+
223
+ __all__ = ["solve", "solver", "decode", "encode", "convert", "PenpaDecodeError"]
224
+ __version__ = '0.3.3'