code wiki / _hdl_build / nx_sudoku_core.nx

nx_sudoku_core.nx

buildroot/runtime/_hdl_build/nx_sudoku_core.nx

8398 B222 linesdepth 0pulls 0 transitivereach 3 importersview sourcekind librarytopic sudoku
docsdependenciesstructsconstsfunctions

about

nx_sudoku_core.nx -- LIB (no main): the ONE sudoku algorithm in the estate, written BASE-RELATIVE so the identical code runs natively (base = an mmap'd buffer) and inside our WebAssembly (base = 0). WHY BASE-RELATIVE. The estate's wasm game contract (nx_wasm_2048, nx_wasm_craft) is that a game is pure integer logic over a flat memory image addressed as base+offset. A module written that way needs no allocator, no syscalls and no host cooperation, so the SAME source is the native binary AND the browser module. The alternative -- one copy in NishiLang for the tool and another in JavaScript for the page -- is two implementations of one ruleset, which is the duplicate-ruler defect the estate keeps paying for. There is exactly ONE solver, ONE counter and ONE carver here, and both consumers (nx_sudoku for banks, nx_sudoku_wasm for play) compose them. THE LOAD-BEARING PROPERTY: uniqueness is COUNTED, never assumed. sc_carve empties a cell only when sc_count still returns exactly 1, and sc_count saturates at 2 because "is it still unique" only ever needs to separate 1 from more-than-1. The clue floor is 17 -- McGuire, Tugemann & Civario (2012) proved exhaustively that no 16-clue sudoku has a unique solution, so a request for fewer is CLAMPED rather than honoured: asking for 16 asks for something that provably does not exist. Deterministic: the PRNG is a seeded LCG held in the memory image, so a given seed reproduces a given puzzle exactly. A generator you cannot re-run is not one you can test. license_tier: ORIGINAL No hw writes (Rule 26).

dependencies 0 imports · 2 importers

nx_sudoku_core.nx nx_sudoku.nx nx_sudoku_wasm.nx

imports: none

imported by: nx_sudoku.nxnx_sudoku_wasm.nx

structs

none

consts

23const SC_G: i64 = 0 // 81 i64 the working / puzzle grid
24const SC_SOL: i64 = 648 // 81 i64 its full solution
25const SC_WORK: i64 = 1296 // 81 i64 scratch grid for counting
26const SC_ORD: i64 = 1944 // 81 i64 removal order
27const SC_SHUF: i64 = 2592 // 81*9 per-depth candidate shuffle (never allocated in the hot loop)
28const SC_RNG: i64 = 8424 // 1 i64 LCG state
29const SC_SIZE: i64 = 8432 // total bytes a caller must provide
31const SC_CLUE_FLOOR: i64 = 17
32const SC_LCG_A: i64 = 1103515245
33const SC_LCG_C: i64 = 12345
34const SC_LCG_M: i64 = 2147483648

functions

37func sc_get(base: i64, off: i64, i: i64) -> i64 { let p: *i64 = (base+off) as *i64; return p[i] }
38func sc_put(base: i64, off: i64, i: i64, v: i64) -> i64 { let p: *i64 = (base+off) as *i64; p[i]=v; return 0 }
39func sc_copy(base: i64, src: i64, dst: i64) -> i64
44func sc_clear(base: i64, off: i64) -> i64
49func sc_clues(base: i64, off: i64) -> i64
called by 1: sd_selftest calls 1: sc_get
57func sc_seed(base: i64, s: i64) -> i64
63func sc_next(base: i64) -> i64
called by 1: sc_below calls 2: sc_getsc_put
70func sc_below(base: i64, n: i64) -> i64 { if n<=0 { return 0 } return sc_next(base)%n }
called by 2: sc_fillsc_carve calls 1: sc_next
74func sc_ok(base: i64, off: i64, i: i64, v: i64) -> i64
called by 3: sd_selftestsc_fillsc_count calls 1: sc_get
96func sc_fill(base: i64, off: i64, i: i64) -> i64
124func sc_count(base: i64, off: i64, i: i64, n: i64) -> i64
144func sc_carve(base: i64, clues: i64) -> i64
179func sc_gen(base: i64, clues: i64, seed: i64) -> i64
196func sc_unavoidable(base: i64, off: i64, out: *i64) -> i64
called by 1: sd_selftest calls 1: sc_get