This repository has been archived on 2023-11-10. You can view files and clone it, but cannot push or open issues or pull requests.
freecodecamp-projects/7-quality-assurance/4-sudoku-solver/controllers/sudoku-solver.js

128 lines
3.5 KiB
JavaScript

let currentPuzzle = "";
class SudokuSolver {
getPuzzleArray(puzzleString) {
const puzzleArray = [[], [], [], [], [], [], [], [], []];
for (let i = 0; i <= 80; i++) {
let value = puzzleString[i];
value === "." || !value
? (puzzleArray[Math.floor(i / 9)][i % 9] = " ")
: (puzzleArray[Math.floor(i / 9)][i % 9] = value);
}
return puzzleArray;
}
getRow(puzzle, row) {
return puzzle[row];
}
getColumn(puzzle, row, column) {
let col = [];
for (let i in puzzle) {
col.push(puzzle[i][column]);
}
return col;
}
getRegion(puzzle, row, column) {
let region = [];
for (let r = 0; r < 3; r++) {
for (let c = 0; c < 3; c++) {
region.push(
puzzle[Math.floor(row / 3) * 3 + r][Math.floor(column / 3) * 3 + c]
);
}
}
return region;
}
validate(puzzleString) {
if (puzzleString.length !== 81) {
return {
error: "Expected puzzle to be 81 characters long",
};
} else if (!/^[1-9.]+$/.test(puzzleString)) {
return { error: "Invalid characters in puzzle" };
} else {
for (let i in puzzleString) {
let val = puzzleString[i];
let row = Math.floor(i / 9);
let column = i % 9;
if (val !== ".") {
let temp = puzzleString.split("");
temp[i] = ".";
if (
this.checkRowPlacement(temp, row, column, val) &&
this.checkColPlacement(temp, row, column, val) &&
this.checkRegionPlacement(temp, row, column, val)
) {
temp[i] = val;
puzzleString = temp.join("");
} else {
return { error: "Puzzle cannot be solved" };
}
}
}
return true;
}
}
checkRowPlacement(puzzleString, row, column, value) {
let puzzle = this.getPuzzleArray(puzzleString);
let puzzleRow = this.getRow(puzzle, row, column);
return !(
puzzleRow.includes(value.toString()) &&
puzzleRow[column] !== value.toString()
);
}
checkColPlacement(puzzleString, row, column, value) {
let puzzle = this.getPuzzleArray(puzzleString);
let puzzleCol = this.getColumn(puzzle, row, column);
return !(
puzzleCol.includes(value.toString()) &&
puzzleCol[row] !== value.toString()
);
}
checkRegionPlacement(puzzleString, row, column, value) {
let puzzle = this.getPuzzleArray(puzzleString);
let puzzleRegion = this.getRegion(puzzle, row, column);
return !(
puzzleRegion.includes(value.toString()) &&
puzzle[row][column] !== value.toString()
);
}
solve(puzzleString) {
if (puzzleString) currentPuzzle = puzzleString;
let valid = this.validate(currentPuzzle);
if (valid !== true) {
return valid;
}
let empty = currentPuzzle.indexOf(".");
let row = Math.floor(empty / 9);
let column = empty % 9;
if (empty !== -1) {
for (let i = 1; i <= 9; i++) {
if (
this.checkRowPlacement(currentPuzzle, row, column, i) &&
this.checkColPlacement(currentPuzzle, row, column, i) &&
this.checkRegionPlacement(currentPuzzle, row, column, i)
) {
let temp = currentPuzzle.split("");
temp[empty] = i;
currentPuzzle = temp.join("");
this.solve();
}
}
}
if (currentPuzzle.indexOf(".") !== -1) {
let temp = currentPuzzle.split("");
temp[empty] = ".";
currentPuzzle = temp.join("");
}
return { solution: currentPuzzle };
}
}
module.exports = SudokuSolver;