├── gfg.png
├── index.html
└── sudoku.js
/gfg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cv692001/sudokuSolver/2a1837f2fc9501e4ebf8a0951cbef5be573cd806/gfg.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
18 |
19 |
20 |
21 |
22 |
23 |

24 |
25 |
Sudoku Solver
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | | | | | | | | | |
35 |
| | | | | | | | |
36 |
| | | | | | | | |
37 |
38 | | | | | | | | | |
39 |
| | | | | | | | |
40 |
| | | | | | | | |
41 |
42 | | | | | | | | | |
43 |
| | | | | | | | |
44 |
| | | | | | | | |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
114 |
115 |
--------------------------------------------------------------------------------
/sudoku.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var EASY_PUZZLE = "1-58-2----9--764-52--4--819-19--73-6762-83-9-----61-5---76---3-43--2-5-16--3-89--";
4 | var MEDIUM_PUZZLE = "-3-5--8-45-42---1---8--9---79-8-61-3-----54---5------78-----7-2---7-46--61-3--5--";
5 | var HARD_PUZZLE = "8----------36------7--9-2---5---7-------457-----1---3---1----68--85---1--9----4--";
6 |
7 | // Set this variable to true to publicly expose otherwise private functions inside of SudokuSolver
8 | var TESTABLE = true;
9 |
10 | var SudokuSolver = function (testable) {
11 | var solver;
12 |
13 | // PUBLIC FUNCTIONS
14 | function solve(boardString) {
15 | var boardArray = boardString.split("");
16 | if (boardIsInvalid(boardArray)) {
17 | return false;
18 | }
19 | return recursiveSolve(boardString);
20 | }
21 |
22 | function solveAndPrint(boardString) {
23 | var solvedBoard = solve(boardString);
24 | console.log(toString(solvedBoard.split("")));
25 | return solvedBoard;
26 | }
27 |
28 | // PRIVATE FUNCTIONS
29 | function recursiveSolve(boardString) {
30 | var boardArray = boardString.split("");
31 | if (boardIsSolved(boardArray)) {
32 | return boardArray.join("");
33 | }
34 | var cellPossibilities = getNextCellAndPossibilities(boardArray);
35 | var nextUnsolvedCellIndex = cellPossibilities.index;
36 | var possibilities = cellPossibilities.choices;
37 | for (var i = 0; i < possibilities.length; i++) {
38 | boardArray[nextUnsolvedCellIndex] = possibilities[i];
39 | var solvedBoard = recursiveSolve(boardArray.join(""));
40 | if (solvedBoard) {
41 | return solvedBoard;
42 | }
43 | }
44 | return false;
45 | }
46 |
47 | function boardIsInvalid(boardArray) {
48 | return !boardIsValid(boardArray);
49 | }
50 |
51 | function boardIsValid(boardArray) {
52 | return allRowsValid(boardArray) && allColumnsValid(boardArray) && allBoxesValid(boardArray);
53 | }
54 |
55 | function boardIsSolved(boardArray) {
56 | for (var i = 0; i < boardArray.length; i++) {
57 | if (boardArray[i] === "-") {
58 | return false;
59 | }
60 | }
61 | return true;
62 | }
63 |
64 | function getNextCellAndPossibilities(boardArray) {
65 | for (var i = 0; i < boardArray.length; i++) {
66 | if (boardArray[i] === "-") {
67 | var existingValues = getAllIntersections(boardArray, i);
68 | var choices = ["1", "2", "3", "4", "5", "6", "7", "8", "9"].filter(function (num) {
69 | return existingValues.indexOf(num) < 0;
70 | });
71 | return { index: i, choices: choices };
72 | }
73 | }
74 | }
75 |
76 | function getAllIntersections(boardArray, i) {
77 | return getRow(boardArray, i).concat(getColumn(boardArray, i)).concat(getBox(boardArray, i));
78 | }
79 |
80 | function allRowsValid(boardArray) {
81 | return [0, 9, 18, 27, 36, 45, 54, 63, 72].map(function (i) {
82 | return getRow(boardArray, i);
83 | }).reduce(function (validity, row) {
84 | return collectionIsValid(row) && validity;
85 | }, true);
86 | }
87 |
88 | function getRow(boardArray, i) {
89 | var startingEl = Math.floor(i / 9) * 9;
90 | return boardArray.slice(startingEl, startingEl + 9);
91 | }
92 |
93 | function allColumnsValid(boardArray) {
94 | return [0, 1, 2, 3, 4, 5, 6, 7, 8].map(function (i) {
95 | return getColumn(boardArray, i);
96 | }).reduce(function (validity, row) {
97 | return collectionIsValid(row) && validity;
98 | }, true);
99 | }
100 |
101 | function getColumn(boardArray, i) {
102 | var startingEl = Math.floor(i % 9);
103 | return [0, 1, 2, 3, 4, 5, 6, 7, 8].map(function (num) {
104 | return boardArray[startingEl + num * 9];
105 | });
106 | }
107 |
108 | function allBoxesValid(boardArray) {
109 | return [0, 3, 6, 27, 30, 33, 54, 57, 60].map(function (i) {
110 | return getBox(boardArray, i);
111 | }).reduce(function (validity, row) {
112 | return collectionIsValid(row) && validity;
113 | }, true);
114 | }
115 |
116 | function getBox(boardArray, i) {
117 | var boxCol = Math.floor(i / 3) % 3;
118 | var boxRow = Math.floor(i / 27);
119 | var startingIndex = boxCol * 3 + boxRow * 27;
120 | return [0, 1, 2, 9, 10, 11, 18, 19, 20].map(function (num) {
121 | return boardArray[startingIndex + num];
122 | });
123 | }
124 |
125 | function collectionIsValid(collection) {
126 | var numCounts = {};
127 | for(var i = 0; i < collection.length; i++) {
128 | if (collection[i] != "-") {
129 | if (numCounts[collection[i]] === undefined) {
130 | numCounts[collection[i]] = 1;
131 | } else {
132 | return false;
133 | }
134 | }
135 | }
136 | return true;
137 | }
138 |
139 | function toString(boardArray) {
140 | return [0, 9, 18, 27, 36, 45, 54, 63, 72].map(function (i) {
141 | return getRow(boardArray, i).join(" ");
142 | }).join("\n");
143 | }
144 |
145 | if (testable) {
146 | // These methods will be exposed publicly when testing is on.
147 | solver = {
148 | solve: solve,
149 | solveAndPrint: solveAndPrint,
150 | recursiveSolve: recursiveSolve,
151 | boardIsInvalid: boardIsInvalid,
152 | boardIsValid: boardIsValid,
153 | boardIsSolved: boardIsSolved,
154 | getNextCellAndPossibilities: getNextCellAndPossibilities,
155 | getAllIntersections: getAllIntersections,
156 | allRowsValid: allRowsValid,
157 | getRow: getRow,
158 | allColumnsValid: allColumnsValid,
159 | getColumn: getColumn,
160 | allBoxesValid: allBoxesValid,
161 | getBox: getBox,
162 | collectionIsValid: collectionIsValid,
163 | toString: toString };
164 | } else {
165 | // These will be the only public methods when testing is off.
166 | solver = { solve: solve,
167 | solveAndPrint: solveAndPrint };
168 | }
169 |
170 | return solver;
171 | }(TESTABLE);
172 |
--------------------------------------------------------------------------------