Sudoku Javascript¶
Sudoku Solver.
Introduction¶
This library is attempting to solve 9x9 Sudoku grids based on built-in strategies. It records the modified cells and keep track of the strategies used in order to be used for didactic purposes.
It is inspired from the excellent solver from Sudoku Wiki.
Installing¶
Building from source¶
Ensure you have Node.js (>6.0) installed.
Then obtain a copy of the source by either downloading the zipball or cloning the public repository:
git clone https://github.com/buddly27/sudoku-javascript.git
cd sudoku-javascript
Install dependencies using NPM:
npm install
Build a production ready version of the application:
npm run build
Deploy the built files behind a web-server.
Building documentation from source¶
Documentation is built using Sphinx which runs under Python.
Ensure you have installed the ‘extra’ packages required for building the documentation:
pip install .
Then you can build the documentation with the command:
python setup.py build_sphinx
View the result in a browser at:
file:///path/to/sudoku-javascript/build/doc/html/index.html
Running tests against the source¶
With a copy of the source it is also possible to run the unit tests:
npm test
Ensure that the code linting is correct with the following command:
npm run lint
Tutorial¶
The library can be imported with the ES6 import statement as follow:
import {SudokuGrid, SudokuSolver} from "sudoku-javascript";
It can also be imported in a Node.JS interactive shell, using the require function:
>>> const {SudokuGrid, SudokuSolver} = require("sudoku-javascript")
Let’s consider the following example:

A SudokuGrid()
can be created with initial cell values:
>>> const grid = new SudokuGrid({
... c12: 1, c13: 9, c16: 5,
... c20: 5, c21: 6, c23: 3, c24: 1, c27: 9,
... c30: 1, c33: 6, c37: 2, c38: 8,
... c42: 4, c46: 7,
... c50: 2, c51: 7, c55: 4, c58: 3,
... c61: 4, c64: 6, c65: 8, c67: 3, c68: 5,
... c72: 2, c75: 5, c76: 9,
... })
The grid is composed of SudokuCell()
instances which
indicate the value and the candidates available:
>>> const cell1 = grid.cell(0, 0)
>>> cell1.isSolved()
false
>>> cell1.value
0
>>> cell1.candidates
[1, 2, 3, 4, 5, 6, 7, 8, 9]
When the value of a cell is zero, it means that the cell is not solved yet. A cell with a non-zero value is considered solved and does not have candidates:
>>> const cell2 = grid.cell(1, 3)
>>> cell1.isSolved()
true
>>> cell2.value
9
>>> cell2.candidates
[]
A SudokuSolver()
must then be created and used to resolve
the grid:
>>> const solver = SudokuSolver()
>>> solver.resolve(grid)
true
If the process is successful, the grid is now solved:
>>> grid.isSolved()
true
The solver keep track of the strategies used to solve the grid:
>>> solver.strategiesUsed
[
"Hidden Single Strategy",
"Hidden Pair Strategy",
"Hidden Triple Strategy",
]
The grid can then be returned as a mapping:
>>> grid.toValueMapping()
{
c00: 9, c01: 2, c02: 8, c03: 5, c04: 4, c05: 7, c06: 3, c07: 1, c08: 6,
c10: 4, c11: 3, c12: 1, c13: 9, c14: 8, c15: 6, c16: 5, c17: 7, c18: 2,
c20: 5, c21: 6, c22: 7, c23: 3, c24: 1, c25: 2, c26: 8, c27: 9, c28: 4,
c30: 1, c31: 9, c32: 5, c33: 6, c34: 7, c35: 3, c36: 4, c37: 2, c38: 8,
c40: 3, c41: 8, c42: 4, c43: 2, c44: 5, c45: 1, c46: 7, c47: 6, c48: 9,
c50: 2, c51: 7, c52: 6, c53: 8, c54: 9, c55: 4, c56: 1, c57: 5, c58: 3,
c60: 7, c61: 4, c62: 9, c63: 1, c64: 6, c65: 8, c66: 2, c67: 3, c68: 5,
c70: 6, c71: 1, c72: 2, c73: 4, c74: 3, c75: 5, c76: 9, c77: 8, c78: 7,
c80: 8, c81: 5, c82: 3, c83: 7, c84: 2, c85: 9, c86: 6, c87: 4, c88: 1,
}
Which once translated into a grid gives the following result:

API Reference¶
sudoku¶
-
class
sudoku.
SudokuSolver
()[source]¶ import {SudokuSolver} from "sudoku-javascript"
Represent a Sudoku Solver object.
-
constructor
()[source]¶ Create a Sudoku Solver.
The list of strategies to use in order to resolve a grid is initiated.
-
resolve
(grid)[source]¶ Apply all strategies successively in order to resolve the grid.
Each strategy is applied to the grid until the grid is resolved or until no progress can be made.
grid must be a
sudoku.grid.SudokuGrid()
instance.Return whether the grid has been successfully solved.
-
applyStrategiesUntilFirstResult
(grid)[source]¶ Apply the strategies until one is resolving part of the grid.
grid must be a
sudoku.grid.SudokuGrid()
instance.Return a mapping of each modified
sudoku.cell.SudokuCell()
instances organized per identifier.Example:
>>> solver.applyStrategiesUntilFirstResult(grid) { "c40": [SudokuCell], "c43": [SudokuCell], }
-
-
class
sudoku.
SudokuGrid
(cellMapping = {}, candidatesMapping = {})[source]¶ import {SudokuGrid} from "sudoku-javascript"
Represent a Sudoku Grid object.
-
constructor
(cellMapping = {}, candidatesMapping = {})[source]¶ Create a Sudoku Grid 9x9 from a cellMapping.
cellMapping could be a mapping containing values of each cell between 0 and 9 (0 means that the cell is not filled). The grid contains 81 cells with 81 corresponding cell identifier properties that specify the position of the cell in the grid. The first number and the second number of the property name indicate respectfully the row index and the column index. ‘c00’ indicates the cell in the top left corner and ‘c88’ the cell in the bottom right corner.
By default, each cell is initiated to 0.
Example:
>>> new SudokuGrid({ ... c03: 1, c05: 5, ... c10: 1, c11: 4, c16: 6, c17: 7, ... c21: 8, c25: 2, c26: 4, ... c31: 6, c32: 3, c34: 7, c37: 1, ... c40: 9, c48: 3, ... c51: 1, c54: 9, c56: 5, c57: 2, ... c62: 7, c63: 2, c67: 8, ... c71: 2, c72: 6, c77: 3, c78: 5, ... c83: 4, c85: 9, ... });
candidatesMapping could be a mapping containing candidate numbers of each cell, following the same identification logic as the cellMapping.
By default, the candidate numbers of each cell are generated according to the initial value of the cell.
Example:
>>> grid = new SudokuGrid( ... { ... c00: 3, ... c10: 9, c11: 7, c13: 2, c14: 1, ... c20: 6, c23: 5, c24: 8, c25: 3, ... c30: 2, c36: 9, ... c40: 5, c43: 6, c44: 2, c45: 1, c48: 3, ... c52: 8, c58: 5, ... c63: 4, c64: 3, c65: 5, c68: 2, ... c74: 9, c77: 5, c78: 6, ... c88: 1, ... }, ... { ... c01: [1, 2, 4, 5, 8], c02: [1, 2, 4, 5], c03: [2, 7, 9], ... c04: [4, 6, 7], c05: [2, 4, 6, 7, 9], ... c06: [1, 2, 4, 5, 6, 7, 8], c07: [1, 2, 4, 6, 7, 8, 9], ... c08: [4, 7, 8, 9], ... c12: [2, 4, 5], c15: [2, 4, 6], c16: [2, 3, 4, 5, 6, 8], ... c17: [2, 3, 4, 6, 8], c18: [4, 8], ... c21: [1, 2, 4], c22: [1, 2, 4], c26: [1, 2, 4, 7], ... c27: [1, 2, 4, 7, 9], c28: [4, 7, 9], ... c31: [1, 3, 4, 6], c32: [1, 3, 4, 6, 7], c33: [3, 7, 8], ... c34: [4, 5, 7], c35: [4, 7, 8], c37: [1, 4, 6, 7, 8], ... c38: [4, 7, 8], ... c41: [4, 9], c42: [4, 7, 9], c46: [4, 7, 8], c47: [4, 7, 8], ... c50: [1, 4, 7], c51: [1, 3, 4, 6, 9], c53: [3, 7, 9], ... c54: [4, 7], c55: [4, 7, 9], c56: [1, 2, 4, 6, 7], ... c57: [1, 2, 4, 6, 7], ... c60: [1, 7, 8], c61: [1, 6, 8, 9], c62: [1, 6, 7, 9], ... c66: [7, 8], c67: [7, 8, 9], ... c70: [1, 4, 7, 8], c71: [1, 2, 3, 4, 8], ... c72: [1, 2, 3, 4, 7], c73: [1, 2, 7, 8], c75: [2, 7, 8], ... c76: [3, 4, 7, 8], ... c80: [4, 7, 8], c81: [2, 3, 4, 5, 6, 8, 9], ... c82: [2, 3, 4, 5, 6, 7, 9], c83: [2, 7, 8], c84: [6, 7], ... c85: [2, 6, 7, 8], c86: [3, 4, 7, 8, 9], ... c87: [3, 4, 7, 8, 9], ... } ... );
Warning
An Error will be raised if the custom list of candidates given to a cell is incoherent with its value.
-
cellFromId
(identifier)[source]¶ Return the cell from its identifier.
Throw an error if the identifier is incorrect.
-
cellsInColumn
(columnIndex)[source]¶ Return list of values from all cells in column from columnIndex.
-
cellsInBlock
(rowIndex, columnIndex)[source]¶ Return list of values from all cells in block from rowIndex and columnIndex.
-
isSolved
()[source]¶ Indicate whether the grid is solved.
A grid is considered solved when all cells are solved, meaning when all cell has a value other than zero.
-
update
()[source]¶ Update the grid and return the number of solutions found.
Analyse the grid for possible solved cells and compute the resulting candidates for each cell. Repeat this two operations as long as new candidates are found.
-
updateSolvedCells
()[source]¶ Attempt to resolve all cells in the grid and return the number of solutions found.
A cell which has a single candidate left can be updated with the value of this candidate.
-
updateCandidates
()[source]¶ Update candidates for all cells and return whether the grid has been modified.
For each 3x3 block, each cell candidates is compared with the value contained in the neighbor block, row and column. If a number from the cell candidates list is matching values from neighbors, it is removed from the cell candidates list.
-
validate
()[source]¶ Validate the grid and return potential errors.
Errors are returned in the form of an object mapping each cell identifier with a
sudoku.cell.SudokuCell()
instance:>>> grid.validate() { "c42": [SudokuCell], "c47": [SudokuCell], }
A valid grid would return an empty object.
-
toValueMapping
()[source]¶ Return all cell values of the grid as a cell mapping.
The mapping is similar to the cellsMapping argument given to the
constructor()
.
-
toCandidateMapping
()[source]¶ Return all cell candidates of the grid as a cell mapping.
The mapping is similar to the candidatesMapping argument given to the
constructor()
.
-
-
class
sudoku.
SudokuCell
(value, rowIndex, columnIndex, candidates = null)[source]¶ import {SudokuCell} from "sudoku-javascript"
Represent a Sudoku Cell object.
-
constructor
(value, rowIndex, columnIndex, candidates = null)[source]¶ Create a Sudoku Cell with an initial value between 0 and 9.
The coordinates of the cell within a grid must be indicated with the rowIndex and columnIndex value.
If the value is 0, the cell is considered as not solved and a list of candidates from 1 to 9 is set. If the value is not 0, the cell is considered as solved and an empty list of candidates is set.
Example:
>>> const cell1 = new SudokuCell(0, 0, 0); >>> cell1.candidates; [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> const cell2 = new SudokuCell(4, 0, 0); >>> cell2.candidates; []
A custom list of candidates can be given.
Warning
A
SudokuCellError()
is thrown if the custom list of candidates is incoherent with the cell value.
-
validateCandidates
(candidates)[source]¶ Validate candidates and throw an error if invalid.
A
SudokuCellError()
is thrown if the candidates list is not empty while the cell already has a non-zero value, or if the candidates list is empty while the cell do not has a non-zero value yet.
-
set
candidates
(candidates)[source] Set a new list of candidates to replace the current cell candidates.
Warning
A
SudokuCellError()
is thrown if the new list of candidates is incoherent with the cell value.
-
updateCandidates
(rowValues, columnValues, blockValues)[source]¶ Compute candidates from its neighbor list of rowValues, columnValues and blockValues.
If a number from the candidates list is matching values from one of these list, it is removed from the candidates list.
Return whether a list of new candidates has been successfully computed.
Warning
If the list of new candidates is bigger than the current list of candidates, it is not applied.
Warning
A
SudokuCellError()
is thrown if the updated list of candidates is incoherent with the cell value.
-
-
sudoku.
SudokuCellError
(message, identifier)[source]¶ import {SudokuCellError} from "sudoku-javascript"
Error thrown when an error appears in the
SudokuCell()
.It includes the identifier of the cell.
Example:
const cell = new SudokuCell(0, 3, 5); try { cell.candidates = []; } catch (error) { console.log(error.message); console.log(error.identifier); }
-
class
sudoku.
HiddenTripleStrategy
()[source]¶ import {HiddenTripleStrategy} from "sudoku-javascript"
Hidden Triple Strategy.
Identify when three cells from a row, a column or a block can only contain three specific candidate numbers and remove other candidate numbers from those cells.
-
static
processCells
(cells)[source]¶ Attempt to resolve cells.
cells must be a list of
SudokuCell()
instances.Return a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.
-
static
-
class
sudoku.
HiddenQuadStrategy
()[source]¶ import {HiddenQuadStrategy} from "sudoku-javascript"
Hidden Quad Strategy.
Identify when four cells from a row, a column or a block can only contain four specific candidate numbers and remove other candidate numbers from those cells.
-
static
processCells
(cells)[source]¶ Attempt to resolve cells.
cells must be a list of
SudokuCell()
instances.Return a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.
-
static
-
class
sudoku.
HiddenSingleStrategy
()[source]¶ import {HiddenSingleStrategy} from "sudoku-javascript"
Hidden Single Strategy.
Identify when a cell from a row, a column or a block can only contain a specific candidate number and remove other candidate numbers from this cell.
-
static
processCells
(cells)[source]¶ Attempt to resolve cells.
cells must be a list of
SudokuCell()
instances.Return a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.
-
static
-
class
sudoku.
NakedPairStrategy
()[source]¶ import {NakedPairStrategy} from "sudoku-javascript"
Naked Pair Strategy.
Identify when two candidate numbers can only be in two specific cells from a row, a column or a block and remove these candidates from other cells.
-
static
processCells
(cells)[source]¶ Attempt to resolve cells.
cells must be a list of
SudokuCell()
instances.Return a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.
-
static
-
class
sudoku.
NakedTripleStrategy
()[source]¶ import {NakedTripleStrategy} from "sudoku-javascript"
Naked Triple Strategy.
Identify when three candidate numbers can only be in three specific cells from a row, a column or a block and remove these candidates from other cells.
-
static
processCells
(cells)[source]¶ Attempt to resolve cells.
cells must be a list of
SudokuCell()
instances.Return a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.
-
static
-
class
sudoku.
HiddenPairStrategy
()[source]¶ import {HiddenPairStrategy} from "sudoku-javascript"
Hidden Pair Strategy.
Identify when two cells from a row, a column or a block can only contain two specific candidate numbers and remove other candidate numbers from those cells.
-
static
processCells
(cells)[source]¶ Attempt to resolve cells.
cells must be a list of
SudokuCell()
instances.Return a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.
-
static
-
class
sudoku.
PointingStrategy
()[source]¶ import {PointingStrategy} from "sudoku-javascript"
Pointing Strategy.
Identify when a candidate number appears two or three time within the row or column of a block and remove it from other cells in the rest of the row or column.
-
static
processCells
(cellsInRows, cellsInColumns)[source]¶ Attempt to resolve cells.
cellsInRows and cellsInColumns are collections of
sudoku.cell.SudokuCell()
instance lists.Return a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.
-
static
getBlockCounters
(cells)[source]¶ Return candidate counters for intersection block of rows and columns.
Count the occurrence of each cell candidate for the entire block and for each row and column within the intersection.
cells must be a list of
sudoku.cell.SudokuCell()
instances.Example:
>>> getBlocCounters(cells); { global: {'4': 5, '1': 4, '8': 3, '9': 3, '2': 2, '3': 2}, row: { 0: {'8': 2, '4': 2, '2': 1}, 1: {'1': 3, '9': 3, '3': 2, '4': 2, '2': 1}, 2: {'8': 1, '1': 1, '4': 1}, }, column: { 0: {'1': 1, '3': 1, '9': 1}, 1: {'4': 3, '8': 2, '1': 2, '9': 1}, 2: {'2': 2, '4': 2, '1': 1, '3': 1, '8': 1, '9': 1}, }, }
-
static
getNonBlockCellsMapping
(cellsInBlock, cellsInRows, cellsInColumns)[source]¶ Return mapping of cells per row and column indices.
cellsInBlock is a collection of all
sudoku.cell.SudokuCell()
instance lists within the block.cellsInRows is a collection of
sudoku.cell.SudokuCell()
instance lists for each row which has an intersection with the block.cellsInColumns is a collection of
sudoku.cell.SudokuCell()
instance lists for each column which has an intersection with the block.Example:
>>> getNonBlockCellsMapping( ... cellsInBlock, cellsInRows, cellsInColumns ... ); { row: { 0: [[SudokuCell], [SudokuCell], [SudokuCell]], 1: [[SudokuCell], [SudokuCell], [SudokuCell]], 2: [[SudokuCell], [SudokuCell], [SudokuCell]], 6: [[SudokuCell], [SudokuCell], [SudokuCell]], 7: [[SudokuCell], [SudokuCell], [SudokuCell]], 8: [[SudokuCell], [SudokuCell], [SudokuCell]], }, column: { 3: [[SudokuCell], [SudokuCell], [SudokuCell]], 4: [[SudokuCell], [SudokuCell], [SudokuCell]], 5: [[SudokuCell], [SudokuCell], [SudokuCell]], 6: [[SudokuCell], [SudokuCell], [SudokuCell]], 7: [[SudokuCell], [SudokuCell], [SudokuCell]], 8: [[SudokuCell], [SudokuCell], [SudokuCell]], }, }
-
static
getMatchingCandidates
(counters)[source]¶ Return list of matching cell candidates per row and column.
counters is a mapping of candidate counters for intersection block of rows and columns, such as the one returned by
getBlockCounters()
Each candidate is organised by tuple where the first element is the row or column index and the second is the candidate number.
Example:
>>> getMatchingCandidates(counters) { row: [ [1, 3], [1, 9] ], column: [ [8, 2] ], }
-
static
getMatchingCells
(candidatesMapping, cellsMapping)[source]¶ Return cloned cells with updated candidates from candidatesMapping.
The result is a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.candidatesMapping is a mapping of cell candidates lists organised per rows and columns, such as the one returned by
getMatchingCandidates()
cellsMapping is a mapping of all non-block cells organised per row and columns, such as the one returned by
getNonBlockCellsMapping()
-
static
-
class
sudoku.
BoxLineReductionStrategy
()[source]¶ import {BoxLineReductionStrategy} from "sudoku-javascript"
Box Line Reduction Strategy.
Identify when a candidate number appears two or three time within the row or column of a block and remove it from other cells of the block.
-
static
processCells
(cellsInRows, cellsInColumns)[source]¶ Attempt to resolve cells.
cellsInRows and cellsInColumns are collections of
sudoku.cell.SudokuCell()
instance lists.Return a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.
-
static
getCounters
(cellsInRows, cellsInColumns)[source]¶ Return candidate counters for rows and columns.
Count the occurrence of each cell candidate for each row and column.
cellsInRows is a collection of
sudoku.cell.SudokuCell()
instance lists for each row.cellsInColumns is a collection of
sudoku.cell.SudokuCell()
instance lists for each column.Example:
>>> getCounters(cellsInRows, cellsInColumns); { row: { 0: {'1': 2, '2': 3, '3': 3, '6': 2, '7': 2, '8': 3}, 1: {'2': 2, '3': 4, '4': 4, '5': 2, '8': 4, '9': 3}, 2: {'1': 2, '4': 3, '6': 2, '7': 2, '8': 3, '9': 4}, 3: {'7': 1, '8': 1, '9': 1}, 4: {'5': 1, '6': 1, '8': 1, '9': 1}, 5: {'5': 1, '6': 2, '7': 2, '8': 3}, 6: {'1': 2, '2': 2, '3': 1, '4': 2, '6': 2, '9': 3}, 7: {'2': 2, '3': 1, '4': 2, '6': 2, '8': 3}, 8: {'1': 1, '2': 1}, }, column: { 0: {'1': 2, '2': 4, '6': 3, '7': 2, '8': 4, '9': 3}, 1: {'2': 3, '4': 3, '7': 3, '8': 4, '9': 2}, 2: {'1': 3, '3': 2, '4': 4, '5': 2, '6': 4, '8': 6, '9': 4}, 3: {'1': 2, '3': 1, '4': 1, '6': 2, '8': 1}, 4: {'3': 1, '4': 1, '5': 1, '8': 1}, 5: {'3': 2, '4': 2, '5': 1, '7': 2}, 6: {'2': 2, '3': 2, '6': 2, '9': 2}, 7: {'2': 1, '3': 1, '8': 2, '9': 1}, 8: {}, }, }
-
static
getCellsMapping
(cells)[source]¶ Return mapping of cells per row and column indices.
cells must be a list of
sudoku.cell.SudokuCell()
instances.Example:
>>> getCellsMapping(cells); { row: { 0: [[SudokuCell], [SudokuCell], [SudokuCell]], 1: [[SudokuCell], [SudokuCell], [SudokuCell]], 2: [[SudokuCell], [SudokuCell], [SudokuCell]], 6: [[SudokuCell], [SudokuCell], [SudokuCell]], 7: [[SudokuCell], [SudokuCell], [SudokuCell]], 8: [[SudokuCell], [SudokuCell], [SudokuCell]], }, column: { 3: [[SudokuCell], [SudokuCell], [SudokuCell]], 4: [[SudokuCell], [SudokuCell], [SudokuCell]], 5: [[SudokuCell], [SudokuCell], [SudokuCell]], 6: [[SudokuCell], [SudokuCell], [SudokuCell]], 7: [[SudokuCell], [SudokuCell], [SudokuCell]], 8: [[SudokuCell], [SudokuCell], [SudokuCell]], }, }
-
static
getMatchingCandidates
(mapping, counters)[source]¶ Return list of matching cell candidates per row and column.
mapping is a mapping of block cells per row and column indices.
counters is a mapping of candidate counters for rows and columns, such as the one returned by
getCounters()
Each candidate is organised by tuple where the first element is the row or column index and the second is the candidate number.
Example:
>>> getMatchingCandidates(counters) { row: [ [0, 2], [1, 6] ], column: [ [4, 9] ], }
-
static
getMatchingCells
(candidatesMapping, cellsMapping)[source]¶ Return cloned cells with updated candidates from candidatesMapping.
The result is a mapping of
sudoku.cell.SudokuCell()
cloned instances with updated candidates list per cell identifier.candidatesMapping is a mapping of cell candidates lists organised per rows and columns, such as the one returned by
getMatchingCandidates()
cellsMapping is a mapping of all cells organised per row and columns, such as the one returned by
getCellsMapping()
-
static
Release Notes¶
0.6.3¶
18 August 2018- fixed
Add missing dates to release notes.
0.6.1¶
18 August 2018- fixed
Changed lodash dependency to 4.17.5 due to vulnerability issues.
0.6.0¶
18 August 2018- changed
Changed licensing to use the MIT License.
0.5.0¶
28 October 2017- changed
Changed
sudoku.grid.SudokuGrid.update()
to return the number of solved cells instead of whether any candidates have been modified. - changed
Changed
sudoku.cell.SudokuCell.updateCandidates()
to return directly with ‘false’ if the cell is already solved. - new
Added
sudoku.cell.SudokuCellError()
and use it instead of the generic error class forSudokuCell()
in order to include the cell identifier when an error is thrown. - changed
Changed
SudokuCell()
to throwSudokuCellError()
when an incoherent list of candidates is provided to a cell. - changed
Changed
sudoku.cell.SudokuCell.updateCandidates()
to throwSudokuCellError()
when it attempts to set an incoherent list of candidates to a cell.const cell = new SudokuCell(0, 1, 9) // This would result to an empty candidate list, whereas the cell // does not have a value yet... cell.updateCandidates([1, 4, 6], [2, 3, 5], [7, 8, 9])
0.4.0¶
24 October 2017- changed
Renamed
sudoku.grid.SudokuGrid.toMapping()
tosudoku.grid.SudokuGrid.toValueMapping()
for clarity. - new
Added
sudoku.grid.SudokuGrid.toCandidateMapping()
to return a mapping of all candidates per cell identifier.
0.3.2¶
22 October 2017- fixed
Fix package version.
0.3.0¶
21 October 2017- changed
Changed the logic which leads to the modification of cell candidate numbers when a strategy have been successfully applied:
Instead of storing new candidate numbers in a ‘next’ buffer list attribute within the
SudokuCell()
instance and updating the cell candidates list only whensudoku.grid.SudokuGrid.updateCandidates()
is called, each strategy’s ‘processGrid’ method should return a mapping ofcloned instances
which contain the updated candidates.Changed
sudoku.solver.SudokuSolver.resolve()
so to take care of the update of each cell candidates. - new
Added optional argument to set initial candidates to a
SudokuCell()
. - new
Added optional argument to set initial candidates for each
SudokuCell()
instance within aSudokuGrid()
instance. - new
Added
sudoku.cell.SudokuCell.validateCandidates()
to throw an error when the list of candidate numbers set to aSudokuCell()
is incoherent with its value. - new
Added
sudoku.grid.SudokuGrid.cellFromId()
to retrieve a specificSudokuCell()
instance from aSudokuGrid()
using its identifier:>>> const grid = new SudokuGrid({c36: 7}) >>> const cell = grid.cellFromId("c36") >>> cell.value 7
- fixed
The assumption that setting a new value to a cell should automatically empty the candidate list was incorrect as a value of zero should bring back a list of possible candidate numbers, which is impossible to guess from the scope of the cell as it should be computed relatively to the entire grid (see
sudoku.grid.SudokuGrid.updateCandidates()
).Therefore, the setter to manually change the value of a
SudokuCell()
has been removed in favor of a setter to manually change its candidate numbers. It is safer to rely on a candidates setter and on thesudoku.cell.SudokuCell.resolve()
method to update a cell value:>>> cell = new SudokuCell(0, 0, 0) >>> cell.candidates = [3] >>> cell.resolve() >>> cell.value 3
0.2.0¶
15 October 2017- new
Added setter to manually change the value of a
SudokuCell()
and empty its list of candidates.
0.1.0¶
12 October 2017- new
Added
BoxLineReductionStrategy()
to identify when a candidate number appears two or three time within the row or column of a block and remove it from other cells of the block. - new
Added
PointingStrategy()
to identify when a candidate number appears two or three time within the row or column of a block and remove it from other cells in the rest of the row or column. - new
Added
NakedTripleStrategy()
to identify when three candidate numbers can only be in three specific cells from a row, a column or a block and remove these candidates from other cells. - new
Added
NakedPairStrategy()
to identify when two candidate numbers can only be in two specific cells from a row, a column or a block and remove these candidates from other cells. - new
Added
HiddenQuadStrategy()
to identify when four cells from a row, a column or a block can only contain four specific candidate numbers and remove other candidate numbers from those cells. - new
Added
HiddenTripleStrategy()
to identify when three cells from a row, a column or a block can only contain three specific candidate numbers and remove other candidate numbers from those cells. - new
Added
HiddenPairStrategy()
to identify when two cells from a row, a column or a block can only contain two specific candidate numbers and remove other candidate numbers from those cells. - new
Added
HiddenSingleStrategy()
to identify when a cell from a row, a column or a block can only contain a specific candidate number and remove other candidate numbers from this cell. - new
Initial release including a
SudokuSolver()
which can apply strategies to resolveSudokuCell()
within aSudokuGrid()
.
Glossary¶
- JavaScript
Programming language specified in the ECAMScript language specification.
See also
- Node.js
A JavaScript runtime built on Chrome’s V8 JavasScript engine.
See also
- NPM
Package manager for Node.js.
See also
- Python
High-level programming language widely used for general purpose programming.
See also
- PyPI
Python package index. A repository of software for the Python programming language.
See also
- Sphinx
A tool that makes it easy to create intelligent and beautiful documentation.
See also
- Virtualenv
A tool to create isolated Python environments.