A TypeScript-first Sudoku engine. Human techniques, machine precision.
TSudoku is an open-source TypeScript port of SudokuExplainer (SE), the Java Sudoku technique classifier the competitive Sudoku community has used for two decades. It runs natively in Node.js, browsers, and React Native (via Hermes), with no JVM dependency.
Website: tsudoku.dev
Most Sudoku solvers use backtracking — they find a solution but can't explain how. TSudoku identifies the named human technique that applies at each step, explains why it works, and rates puzzle difficulty by the hardest technique required.
The goal is a Sudoku game that teaches you to play better, not one that just checks your answers. The engine is the foundation for that.
Phase 1 is complete, with 100% agreement against SudokuExplainer across a 607-puzzle corpus. The core engine correctly detects and rates every direct technique in the SE 1.0–2.5 band.
Everything downstream of @tsudoku/core — solver, generator, CLI, UI — is still scaffolding.
See STATUS.md for the honest, current picture: what works, what's next, and the known issues.
$ pnpm benchmark:quick
DirectHiddenPair 103/103 (100.0%) PASS
DirectHiddenTriplet 100/100 (100.0%) PASS
DirectPointing 100/100 (100.0%) PASS
HiddenSingle 204/204 (100.0%) PASS
NakedSingle 100/100 (100.0%) PASS
Overall: 607/607 (100.0%) Status: PASS
@tsudoku/core solves puzzles through the Phase 1 technique band and explains every step:
import { createGrid, applyHint, Solver } from '@tsudoku/core';
let grid = createGrid(
'530070000600195000098000060800060003400803001700020006060000280000419005000080079',
);
const solver = new Solver();
const hint = solver.getNextHint(grid);
// {
// type: 'direct',
// technique: 'HiddenSingle',
// cell: 5,
// digit: 8,
// difficulty: 1.2,
// explanation: '8 can only go in R1C6 in box 2',
// involvedCells: [...],
// involvedCandidates: Map(...)
// }
grid = applyHint(grid, hint); // immutable — returns a new GridEvery hint carries a human-readable explanation plus the cells and candidates
involved, which is what makes technique teaching possible rather than just
technique detection.
Not published to npm yet. Build from source — see below.
pnpm monorepo; packages publish under the @tsudoku scope.
| Package | Description | Status |
|---|---|---|
@tsudoku/core |
Grid model, candidate engine, techniques, solver | Phase 1 complete |
@tsudoku/solver |
Full solve-path recording | Stub |
@tsudoku/generator |
Puzzle generation + SE-compatible rating | Stub |
@tsudoku/cli |
CLI for solving, rating, explaining, generating | Stub |
@tsudoku/react-native |
React Native components and hooks | Stub |
Planned but not yet created: @tsudoku/game (framework-free game state) and @tsudoku/web (the web UI). See STATUS.md for how the layers divide.
Phases match SudokuExplainer's difficulty scale. For technique descriptions and visual examples, see SudokuWiki.
| Technique | SE rating | SE parity |
|---|---|---|
| Hidden Single | 1.0 / 1.2 / 1.5 | 204/204 |
| Direct Pointing | 1.7 | 100/100 |
| Direct Claiming | 1.9 | no corpus yet |
| Direct Hidden Pair | 2.0 | 103/103 |
| Naked Single | 2.3 | 100/100 |
| Direct Hidden Triplet | 2.5 | 100/100 |
Pointing & Claiming (Locked Candidates), Naked/Hidden Sets (pairs–quads), X-Wing, Swordfish, Jellyfish, XY-Wing, XYZ-Wing.
Unique Rectangles (types 1–4), Unique Loops, Bivalue Universal Graves.
Aligned Pair Exclusion, X/Y-Cycles, Forcing Chains, Nishio, Dynamic and Nested variants. Server-side only; deprioritized in favor of the teaching app.
Requires Node 20+ and pnpm 10+.
pnpm install
pnpm build
pnpm testOther useful commands:
pnpm benchmark:quick # SE parity check, Phase 1 only
pnpm typecheck
pnpm lint
pnpm formatRun a single test file:
cd packages/core && npx vitest run tests/techniques/phase1/NakedSingle.test.tsThe benchmark is a CI gate: parity below 95% on any implemented technique fails the build. To rate puzzles against the real SE (requires Java):
bash tools/se-reference/setup.sh
bash tools/se-reference/rate.sh '530070000600195000098000060800060003400803001700020006060000280000419005000080079'The SE Java source is a git submodule at tools/se-reference/SudokuExplainer-source, used as the reference for every port.
Contributions welcome — this is a hobby project that would be more fun with company.
Each technique is a self-contained file implementing one interface. Adding a technique means one source file, one test file, and registering it in the solver's producer list.
Start here: STATUS.md for what needs doing, PORTING.md for the Java→TypeScript porting workflow, and CONTRIBUTING.md for conventions.
The one non-negotiable rule: techniques are line-by-line ports of the SE Java source — same structure, same iteration order, same control flow. SE parity is the project's entire credibility claim. Improvements over SE's algorithms are welcome as notes in notes/improvements.md, not as code changes.
TSudoku is a TypeScript port of Nicolas Juillerat's SudokuExplainer (v1.2.1, 2006). Juillerat's original website is no longer online; the canonical source is the 1to9only/SudokuExplainer fork, which preserves the original implementation alongside Glenn Fowler's (gsf) serate command-line rating modifications.
The SE difficulty scale, technique hierarchy, and technique names are derived from Juillerat's work and reproduced with attribution.
MIT © TSudoku Contributors