What the Heck: Research Tools & Ideas¶
Larsdoku-ZS ships with tools for puzzle construction, uniqueness analysis,
and forge-based generation. For oracle-guided research solving (Super Sus),
see the companion package larsdoku which has larsdoku-research.
Which package has what?
| Feature | larsdoku-zs | larsdoku |
|---|---|---|
| Board class | yes | no |
| Uniqueness checking | yes | yes |
| Forge variant | yes | yes |
| Constellation Forge | yes | yes |
| Mask Forge | yes | no |
| Super Sus (oracle-guided) | no | yes |
larsdoku-research CLI |
no | yes |
Uniqueness Checking¶
Test whether a puzzle has exactly one solution or multiple.
The One-Clue Cliff¶
Remove a single clue from a minimal puzzle and it shatters into multiple solutions:
from larsdoku_zs.engine import has_unique_solution
original = "980700000600050000004008300700000040002004003000500020060000001008001030000090408"
removed = "980700000600050000004008300700000040002004003000500020060000001008001030000090400"
print(has_unique_solution(original)) # True (23 clues)
print(has_unique_solution(removed)) # False (22 clues — R9C9 removed)
One digit. That's the difference between a puzzle with exactly one answer and a puzzle with many. In a minimal puzzle, every given is load-bearing.
Forge Variant¶
Turn a non-unique (multi-solution) puzzle into unique ones by reshuffling digits while keeping the same clue pattern:
Same mask, different unique puzzles. Some need only basic techniques, others pull in ALS-XZ -- same skeleton, different difficulty. Useful for generating puzzle sets or testing how much variety a single clue pattern can produce.
Constellation Forge¶
Generate unique puzzles from any unique puzzle by relabeling digits 1-9. Every permutation of the digit mapping produces a structurally identical puzzle with different numbers.
Key finding: For well-formed masks (23-24 clues), 100% of digit permutations produce unique puzzles. That's 362,880 unique puzzles from a single source puzzle.
Mask Forge¶
Generate a unique puzzle from a bare mask (which positions have clues):
from larsdoku_zs.mask_forge import forge_unique
# 'X' = clue position, '0' = empty
mask = "X00X0000000X00X000X000000X0000X00000X000X0000X00000X000X000X000X00000X0000X000X0"
puzzle, solution, checks, elapsed = forge_unique(mask, max_seconds=60, verbose=True)
print(f"Puzzle: {puzzle}")
print(f"Found in {checks} checks ({elapsed:.1f}s)")
The forge fills a random solved grid, maps it onto the mask, and verifies uniqueness -- repeating until it finds one that works.
Board Class: Solve + Analyze¶
The Board class wraps all of the above into a single object:
from larsdoku_zs import Board
b = Board("530070000600195000098000060800060003400803001700020006060000280000419005000080079")
# Full solve
result = b.solve()
print(result['success'])
print(result['technique_counts'])
# Single technique detection
det = b.detect("nakedPair")
print(det.found, det.eliminations)
# GF(2) linear algebra
gf2_result = b.gf2()
# SIRO prediction
b.compute_zones()
pred = b.siro_predict()
Super Sus (larsdoku only)¶
Oracle-guided solving lives in the larsdoku package. If you want to explore what techniques can do when steered by a known solution:
larsdoku-research \
--trust-solve-to 179348652536721948284569371912437586358916724467285193723194865845673219691852437 \
--detail --board \
000000000500020008000000000000000000300010004000000000000000000800070009000000000
from larsdoku.research import super_sus_solve
result = super_sus_solve(
"000000000500020008000000000000000000300010004000000000000000000800070009000000000",
solution="179348652536721948284569371912437586358916724467285193723194865845673219691852437",
detail=True,
)
print(f"Steps: {result['n_steps']}, Oracle saves: {result['oracle_saves']}")
# Steps: 100, Oracle saves: 0
8 clues, 72 placements, zero oracle saves. Every FPC-Elim that fired was already pointing at the right answer. The techniques are the engine, the oracle is the steering wheel.
See the larsdoku Research Tool docs for the full deep-dive.