Source code for sudoku.solver

/**
 * Sudoku solver.
 */

import {
    HiddenSingleStrategy,
    HiddenPairStrategy,
    HiddenTripleStrategy,
    HiddenQuadStrategy,
    NakedPairStrategy,
    NakedTripleStrategy,
    PointingStrategy,
    BoxLineReductionStrategy,
} from "./strategy";


/**
 * Represent a Sudoku Solver object.
 */
[docs]export class SudokuSolver { /** * Create a Sudoku Solver. * * The list of strategies to use in order to resolve a grid is initiated. */
[docs] constructor() { this._strategies = [ HiddenSingleStrategy, HiddenPairStrategy, HiddenTripleStrategy, HiddenQuadStrategy, NakedPairStrategy, NakedTripleStrategy, PointingStrategy, BoxLineReductionStrategy, ]; this._strategiesUsed = []; } /** Return a list of all strategies available. */
[docs] get strategies() { return this._strategies; } /** Return a list of identifiers for each strategy used. */
[docs] get strategiesUsed() { return this._strategiesUsed; } /** * 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 :class:`sudoku.grid.SudokuGrid` instance. * * Return whether the grid has been successfully solved. */
[docs] resolve(grid) { let solved = false; let solutionsFound; do { solutionsFound = 0; // Update candidates for each cell of the grid and find potential // values. grid.update(); // If the grid is already solved, stop here. solved = grid.isSolved(); if (solved) { break; } // Apply all strategy until one return a result. const mapping = this.applyStrategiesUntilFirstResult(grid); // Update the grid with new candidates found. // eslint-disable-next-line no-loop-func Object.keys(mapping).forEach((identifier) => { const cell = grid.cellFromId(identifier); cell.candidates = mapping[identifier].candidates; solutionsFound += 1; }); // Keep looping if solutions have been found. } while (solutionsFound); return solved; } /** * Apply the strategies until one is resolving part of the grid. * * *grid* must be a :class:`sudoku.grid.SudokuGrid` instance. * * Return a mapping of each modified :class:`sudoku.cell.SudokuCell` * instances organized per identifier. * * Example:: * * >>> solver.applyStrategiesUntilFirstResult(grid) * { * "c40": [SudokuCell], * "c43": [SudokuCell], * } */
[docs] applyStrategiesUntilFirstResult(grid) { let mapping = {}; // eslint-disable-next-line no-restricted-syntax for (const strategy of this.strategies) { if (strategy.processGrid) { mapping = strategy.processGrid(grid); if (Object.keys(mapping).length > 0) { const id = strategy.identifier; if (this._strategiesUsed.indexOf(id) === -1) { this._strategiesUsed.push(id); } break; } } } return mapping; } }