hodoku-difficulty-rating-ts
v0.2.1
Published
TypeScript port of HoDoKu's logical Sudoku difficulty rating engine.
Maintainers
Readme
hodoku-difficulty-rating-ts
TypeScript port of HoDoKu's logical Sudoku solver, scoped to difficulty rating only.
Given an 81-character puzzle string it returns the difficulty score and band that HoDoKu's Java solver would produce.
Please consider that it is far slower than the original Java version. Use this version only if you need JS support.
Deprecation notice
Development has stopped for this partial port. However, a new version powered by TeaVM JS transpilation can be found here. It is much faster than this port and parity is the same, it includes generation, step finding, and additional QoL features.
Difficulty bands
These values are maximum scores, not exclusive score ranges. A puzzle can still be rated above the score-only ceiling if it uses a technique whose minimum difficulty is higher. For example, a MEDIUM puzzle can have an EASY score.
| Difficulty | Max score |
|---|---:|
| EASY | 800 |
| MEDIUM | 1000 |
| HARD | 1600 |
| UNFAIR | 1800 |
| EXTREME | none |
Current parity
Take this numbers as reference only, not guaranteed results. If you find a disparity, please report.
These numbers are generated using parity tool, which uses Java QQwing (generation of 5000 puzzles) and original Hodoku (solving). Then the sudokus are solved using current library, and scores are compared.
You can run it using npm run parity-tool
Note: the tool excludes known disparities. So also check that file.
| Difficulty | Difficulty parity | Score parity | |-----------------------|-----------------------|--------------------| | Easy | 100% | 100% | | Medium | 100% | 100% | | Hard | 100% | 100% | | Unfair | 100% | 99.7% | | Extreme | 99.74% | 97.91% |
Scope
Included:
- Full logical solver engine (naked singles → forcing chains) — all techniques contribute to scoring
SudokuSolver.rate()andSudokuSolver.rateByScore()— public rating entry points- Difficulty bands:
EASY,MEDIUM,HARD,UNFAIR,EXTREME - Scores that match the Java reference implementation
Not included:
- Step-by-step API (
getStep,doStep,solve) - Access to the internal grid state (
Sudoku2, candidates, placed values) - Solution strings or candidate lists
- Display metadata (fish base/cover sets, fin cells)
- Puzzle generation
Usage
import { SudokuSolver } from "hodoku-difficulty-rating-ts";
const { solved, difficulty, score } = SudokuSolver.rate(
"...253..87..1.......1....4...8.94...5.......71.95.8....1......2...785...3.4.2....",
);
console.log(solved); // true
console.log(difficulty); // "EASY"
console.log(score); // 224Optional difficulty cap
Stop early if the puzzle exceeds a given difficulty band:
const r = SudokuSolver.rate(puzzle, "HARD");
if (!r.solved) {
console.log("Puzzle exceeds HARD");
}Optional score cap
Stop early if the puzzle exceeds a given score:
const r = SudokuSolver.rateByScore(puzzle, 1600);
if (!r.solved) {
console.log("Puzzle exceeds score 1600");
}API
SudokuSolver.rate(puzzle, maxDifficulty?)
| Parameter | Type | Default | Description |
|---|---|---|---|
| puzzle | string | — | 81-character string; '0' or '.' for empty cells. |
| maxDifficulty | DifficultyType | "EXTREME" | Stop and return solved: false when score exceeds this band's ceiling. |
SudokuSolver.rateByScore(puzzle, maxScore?)
| Parameter | Type | Default | Description |
|---|---|---|---|
| puzzle | string | — | 81-character string; '0' or '.' for empty cells. |
| maxScore | number | Number.MAX_SAFE_INTEGER | Stop and return solved: false when cumulative score exceeds this threshold. |
Returns SolveRating:
interface SolveRating {
solved: boolean; // true when all 81 cells were filled by logic
score: number; // cumulative HoDoKu score
difficulty: DifficultyType; // "EASY" | "MEDIUM" | "HARD" | "UNFAIR" | "EXTREME"
}Difficulty ceilings (matching Java): EASY max 800, MEDIUM max 1000, HARD max 1600, UNFAIR max 1800, EXTREME has no score ceiling. Difficulty is also bounded below by the hardest technique used, so the final difficulty is not determined by score alone.
Building from source
npm install
npm run build # outputs CJS + ESM + .d.ts to dist/
npm test # runs Jest regression tests against test/test_data.csvLicense
GPL-3.0-only — ported from HoDoKu, Copyright © 2008–2012 Bernhard Hobiger.
