fast-sudoku-solver
Version:
A fast Sudoku solver written in TypeScript.
64 lines • 3.25 kB
JavaScript
import { cloneSudoku, getPossibleEntries, isCorrectlySolved } from './solver-utils';
/**
* Calculates the next number for the specified Sudoku puzzle.
* The function returns whether the puzzle *isSolvable*, and it returns the *row*, the *column*, and the *entry* itself for the next number.
*
* In particular, the function returns the entry for the field with the fewest number of possible entries.
* For instance, if there is a field with 7 possible entries and another field with only 2 possible entries, a correct entry for the latter is returned.
*
* **NOTE:** If the Sudoku puzzle is already completely solved, this function returns value -1 for *row*, *column*, and *entry*.
* @param sudoku the Sudoku puzzle for which the next entry should be calculated
* @returns the entry for the next field
*/
export function solveNextNumber(sudoku) {
let minNumberOfPossibleEntries = 10; // initially set to something greather than 9 such that one field is picked even in empty Sudoku
let rowMinNumber = -1;
let columnMinNumber = -1;
let possibleEntriesMinNumber = [];
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
// field already filled? continue with next field
if (sudoku[i][j] >= 1) {
continue;
}
// get possible entries for current field
const possibleEntries = getPossibleEntries(sudoku, i, j);
// no possible entries? Sudoku not solvable
if (possibleEntries.length === 0) {
return { isSolvable: false, row: i, column: j, entry: -1 };
}
// only one possibility left? add entry and start recursive call
// NOTE: recursive call is needed as we still want to check whether the puzzle is completely solvable
if (possibleEntries.length === 1) {
const clone = cloneSudoku(sudoku);
clone[i][j] = possibleEntries[0];
return { isSolvable: solveNextNumber(clone).isSolvable, row: i, column: j, entry: possibleEntries[0] };
}
// multiple possible entries? find field with lowest number of possibilities
if (possibleEntries.length < minNumberOfPossibleEntries) {
minNumberOfPossibleEntries = possibleEntries.length;
rowMinNumber = i;
columnMinNumber = j;
possibleEntriesMinNumber = possibleEntries;
}
}
}
// if arrived here: try out as many possibilities as needed for field with lowest number of possibilities
const clone = cloneSudoku(sudoku);
for (let i = 0; i < possibleEntriesMinNumber.length; i++) {
clone[rowMinNumber][columnMinNumber] = possibleEntriesMinNumber[i];
const result = solveNextNumber(clone);
if (!result.isSolvable) {
continue;
}
return {
isSolvable: result.isSolvable,
row: rowMinNumber,
column: columnMinNumber,
entry: possibleEntriesMinNumber[i],
};
}
// if arrived here: solver is done
return { isSolvable: isCorrectlySolved(clone), row: -1, column: -1, entry: -1 };
}
//# sourceMappingURL=next-number-solver.js.map