npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sudoku-dlx

v2.0.1

Published

Fast Sudoku solver using Dancing Links

Downloads

343

Readme

sudoku-dlx

A fast Sudoku solver for modern JavaScript runtimes, powered by dancing-links and Algorithm X.

sudoku-dlx is an ESM TypeScript library with a command-line interface. It supports one-shot solves, enumeration of every solution, and compiled fixed puzzles for low-overhead repeated solving.

Requirements

  • Node.js 22.13 or newer
  • Bun is also tested as a library runtime

Install

npm install sudoku-dlx

Library API

Puzzle strings contain exactly 81 characters. Use digits 1 through 9 for givens and either . or 0 for empty cells.

import { printBoard, solveString } from 'sudoku-dlx'

const puzzle = '.....12..1..7...45...43.7...9...63...5.8.7.2...62...9...3.19...97...4..6..25.....'
const [solution] = solveString(puzzle)

if (solution) {
  console.log(printBoard(solution))
}

Solutions are arrays of SudokuCell objects:

interface SudokuCell {
  number: number // 1-9
  row: number // 0-8
  col: number // 0-8
}

The primary APIs always return an array of solutions. An empty array means the puzzle has no solution.

solveString(sudoku, all?)

Solves an 81-character puzzle. By default the search stops after its first solution; pass true to enumerate every solution.

const first = solveString(puzzle)
const every = solveString(puzzle, true)

solveCells(cells, all?)

Solves a puzzle supplied as its zero-indexed givens.

import { solveCells, type SudokuCell } from 'sudoku-dlx'

const givens: SudokuCell[] = [
  { row: 0, col: 5, number: 1 },
  { row: 0, col: 6, number: 2 }
]

const solutions = solveCells(givens)

compileString(sudoku) and compileCells(cells)

Compilation builds an immutable solver topology for one fixed puzzle. Reuse it when the same puzzle will be solved repeatedly; one-shot calls are the appropriate path when the givens change.

import { compileString } from 'sudoku-dlx'

const compiled = compileString(puzzle)
const first = compiled.solve()
const every = compiled.solve(true)

The package also exports parseStringFormat, printBoard, and generateConstraints for input, display, and lower-level integration.

Command line

Run without installing globally:

npx --package sudoku-dlx sudoku-solve \
  '.....12..1..7...45...43.7...9...63...5.8.7.2...62...9...3.19...97...4..6..25.....'

Or install the executable globally:

npm install --global sudoku-dlx
sudoku-solve '.................................................................................'

The CLI prints the first solution. Invalid input and unsatisfiable puzzles return a non-zero exit status.

Development

Install exactly the locked dependency graph, then run the complete local check:

npm ci
npm run check

Useful focused commands include:

npm run build          # production ESM and declarations
npm test               # Mocha unit tests through tsx
npm run test:bun       # unit tests on Bun
npm run cover          # c8 text and LCOV coverage
npm run lint
npm run format:check

See DEVELOPMENT.md for the full workflow and PERFORMANCE.md for performance rules.

Benchmarking

The benchmark harness reports honest corpus throughput: every timed sample solves one complete pass over the same 64 independently generated puzzle structures, and puzzles per second is calculated from total work divided by total elapsed time. Each ranked pass uses fresh exact strings and fresh prepared objects outside timing, so an exact-result cache or input mutation cannot benefit from the harness loop. Warmup puzzles are disjoint from measured puzzles, and measured solutions are validated after timing.

Direct rankings distinguish end-to-end calls, where public input conversion and puzzle-specific setup are timed, from prepared calls, where only conversion to each library's natural input shape is excluded. Sudoku-dlx's exact-puzzle compilation mode is shown separately as an unranked capability; it is useful when identical givens are solved repeatedly, but it is not contrasted with ordinary one-shot solver APIs.

npm run benchmark                 # sudoku-dlx regression paths
npm run benchmark:competitive     # maintained npm solvers
npm run benchmark:comprehensive   # ranked maintained, capability, and legacy sections
npm run benchmark:corpus:verify   # reproduce and verify both checked-in corpora
npm run benchmark:json -- run.json

Historical pure-JavaScript packages are a best-effort legacy group:

npm run benchmark:legacy

Every competitor is an exact-pinned npm development dependency installed by the normal npm ci. Packages compete through the same public solve-once contract whether their implementation is JavaScript or WebAssembly. The benchmark suite does not clone third-party repositories or maintain C, C++, or Rust runner programs.

For comparisons that mean anything, use the same machine, runtime, lockfile, warmup, measurement duration, and dataset. Schema-versioned JSON includes runtime, CPU, platform, commit, lockfile hash, timing configuration, dataset semantics, and solver versions. npm run compare-benchmarks compares two such reports and keeps the assessment neutral when their reported confidence intervals overlap. The published competitive table runs on a controlled runner profile; ordinary GitHub-hosted CPU measurements are not presented as release performance.

Benchmarks

Ranked tables compare the same ordinary first-solution workload regardless of whether an npm package is implemented in JavaScript or WebAssembly. Module loading and one-time runtime initialization happen before timing; per-call marshalling, public input conversion, puzzle-specific setup, and solving remain timed. Each timed sample processes one complete corpus pass, and throughput is total puzzles divided by total elapsed time. Prepared cases exclude only conversion to each library's natural input representation. Ranked passes receive fresh deterministic digit-isomorphic strings and fresh prepared objects outside timing, preventing exact-result caches or input mutation from benefiting from harness repetition. Warmup uses a disjoint corpus, and measured outputs are validated after timing.

Representative corpus — string to first solution

Dataset: representative-64 (64 puzzles per pass); warmup: representative-warmup-8 (8 puzzles); tier: end-to-end; input schedule: fresh-deterministic-digit-isomorph-v1-per-pass.

Direct comparison: every solver receives the same independent puzzles and performs the same first-solution work.

| Solver | Puzzles/sec | Relative | Margin | | -------------------------- | ----------: | ----------------: | ------: | | SudokuBlitz | 49,236.67 | 1.00× fastest | ±1.01% | | sudoku-dlx solveString | 42,064.66 | 0.85× | ±1.38% | | sudoku-dlx solveCells | 40,096.13 | 0.81× | ±0.73% | | @reetesh/sudoku-engine | 25,997.77 | 0.53× | ±3.33% | | @algorithm.ts/sudoku | 21,516.9 | 0.44× | ±0.51% | | fast-sudoku-solver | 7,807.72 | 0.16× | ±5.52% | | openzeloku | 3,979.81 | 0.08× | ±4.90% | | sudoku-pro | 2,879.61 | 0.06× | ±8.34% | | @pyroth/sodo (WebAssembly) | 1,225.98 | 0.02× | ±3.60% | | @hackettyam/sudoku-tools | 88.94 | <0.01× | ±12.03% |

Representative corpus — parsed input to first solution

Dataset: representative-64 (64 puzzles per pass); warmup: representative-warmup-8 (8 puzzles); tier: prepared-input; input schedule: fresh-deterministic-digit-isomorph-v1-per-pass.

Direct comparison: every solver receives the same independent puzzles and performs the same first-solution work.

| Solver | Puzzles/sec | Relative | Margin | | ------------------------ | ----------: | ----------------: | ------: | | sudoku-dlx solveCells | 39,636.94 | 1.00× fastest | ±0.79% | | @reetesh/sudoku-engine | 30,968.24 | 0.78× | ±0.97% | | @algorithm.ts/sudoku | 23,678.71 | 0.60× | ±0.58% | | fast-sudoku-solver | 8,360.61 | 0.21× | ±3.66% | | openzeloku | 3,997.17 | 0.10× | ±4.88% | | sudoku-pro | 2,918.86 | 0.07× | ±8.79% | | @hackettyam/sudoku-tools | 91.52 | <0.01× | ±12.19% |

Compiled fixed-puzzle replay — sudoku-dlx capability

Dataset: representative-64 (64 puzzles per pass); warmup: representative-warmup-8 (8 puzzles); tier: compiled-replay; input schedule: fixed-corpus-replay.

Capability only: exact-puzzle compilation happened before timing. These absolute rates describe repeated solving of already-compiled givens and are intentionally not contrasted with ordinary one-shot solver APIs.

| Mode | Puzzles/sec | Margin | | -------------------------------- | ----------: | -----: | | sudoku-dlx compiled-string solve | 75,426.75 | ±1.89% | | sudoku-dlx compiled-cells solve | 73,447.23 | ±3.19% |

Reproduction metadata

  • Runtime: node v24.18.0 (Node 24.18.0)
  • CPU: AMD EPYC; 4 logical CPUs
  • Platform: linux 7.1.3, x64
  • Repository state: b0882528faea56d01532ee7f6b92ccfc2b70c213 (clean)
  • Lockfile SHA-256: 5e57fe42385e96d7e35f974be3c13e76d885adbe753036df997030e1331978c5
  • Tinybench minima: 100 ms warmup and 500 ms measurement per task; iteration minima may run longer
  • Measurement: complete-corpus-pass; rate: total-puzzles-per-total-elapsed-time
  • Ranked input schedule: fresh-deterministic-digit-isomorph-v1-per-pass
  • Validation: warmup-before-and-last-timed-pass-after
  • Solvers: sudoku-dlx solveString workspace (MIT, javascript); sudoku-dlx solveCells workspace (MIT, javascript); fast-sudoku-solver 3.0.3 (MIT, javascript); @algorithm.ts/sudoku 4.0.4 (MIT, javascript); SudokuBlitz 1.0.0 (MIT, javascript); @reetesh/sudoku-engine 2.1.0 (MIT, javascript); openzeloku 0.1.0 (MIT, javascript); sudoku-pro 1.0.15 (MIT, javascript); @hackettyam/sudoku-tools 1.1.0 (MIT, javascript); @pyroth/sodo (WebAssembly) 0.2.1 (MIT, wasm); sudoku-dlx compiled-string solve workspace (MIT, javascript); sudoku-dlx compiled-cells solve workspace (MIT, javascript)
  • Generated: 2026-07-18T21:37:11.171Z

Compiled replay is an unranked sudoku-dlx capability for repeatedly solving identical givens. Legacy all-solution APIs remain in their own best-effort group.

License

MIT