-
Notifications
You must be signed in to change notification settings - Fork 0
/
sudoku_solver.js
166 lines (149 loc) · 5.11 KB
/
sudoku_solver.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
let inputs = document.querySelectorAll('.grid-input');
let btnSolve = document.querySelector('.solve');
let btnClear = document.querySelector('.clear');
// let btnFill = document.querySelector('#fill');
let grid = document.querySelector('.puzzle');
let recursionCounter = 0;
let intervalID;
const RECURSIONLIMIT = 10000;
const LIMITON = false;
// btnFill.addEventListener('click', ()=>{
// let puzzle = getInitialValue();
// fillCells(puzzle);
// displayPuzzle(puzzle);
// });
btnSolve.addEventListener('click', ()=>{
let puzzle = getInitialValue();
console.table(puzzle);
intervalID = setInterval(displayPuzzle, 10, puzzle);
if(solve(puzzle)){
clearInterval(intervalID);
alert('Puzzle Solved.');
}
else{
clearInterval(intervalID);
alert('Puzzle is unsolvable.');
}
});
btnClear.addEventListener('click', ()=>{ clear();});
inputs.forEach(input => {
input.addEventListener('change', (e)=>{
if(e.target.value == 0 || e.target.value === ''){
e.target.value = ''
e.target.classList.remove('userInput');
return;
}
e.target.classList.add('userInput');
});
});
function getInitialValue(){
let ret = [[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0]];
// let ret = [[8,0,4,0,5,7,0,0,0],
// [0,0,0,8,0,0,0,4,0],
// [0,0,0,1,0,4,0,7,8],
// [9,0,0,6,0,0,0,5,0],
// [4,0,5,0,0,0,6,0,3],
// [0,8,0,0,0,5,0,0,9],
// [5,2,0,4,0,1,0,0,0],
// [0,4,0,5,0,8,0,0,0],
// [0,0,0,3,9,0,0,0,0]];
inputs.forEach(cell => {
let id = cell.getAttribute('id');
let row = parseInt(id.substring(0,1));
let col = parseInt(id.substring(1));
let value = document.getElementById(id).value;
// if(isNaN(cell.getAttribute('value'))) console.log('Not a number: ' + cell.getAttribute('value'));
ret[row][col] = value == '' ? 0 : parseInt(value);
});
recursionCounter = 0;
return ret;
}
function solve(puzzle){
recursionCounter++;
console.log(`Recursion counter: ${recursionCounter}`)
// console.log("Recursion Counter: " + recursionCounter);
// setTimeout(displayPuzzle, 10, puzzle);
// setTimeout(displayPuzzle,1,puzzle);
displayPuzzle(puzzle);
if((recursionCounter > RECURSIONLIMIT) && LIMITON){
console.log("Recursion Limit");
return true;
}
// find the next empty cell; returns true if there is no remaining empty cell
let emptyCell = findEmptyCell(puzzle);
// if there is no remaining empty cell, return true
if(emptyCell === true){
console.log('Puzzle Solved');
console.table(puzzle);
return true;
}
for (let i = 1; i <= 9; i++) {
// validate function will check if the value i is valid in the next cell;
// if it is valid, the value will be inserted to the puzzle and the recursion will happen.
if(validatePuzzle(puzzle, emptyCell, i)){
console.log(`inserting value: ${i} in Cell [${emptyCell.row}][${emptyCell.col}].`);
puzzle[emptyCell.row][emptyCell.col] = i;
// recursive function. returns true if there are no remaining cells
if(solve(puzzle)) return true;
else puzzle[emptyCell.row][emptyCell.col] = 0;
}
}
return false;
}
function clear(){
inputs.forEach(cell => {
cell.classList.remove('userInput');
cell.value = '';
});
}
function displayPuzzle(puzzle){
for(let i = 0 ; i < puzzle.length; i++){
for (let j = 0; j < puzzle[i].length; j++) {
let id = '' + i + j;
let cell = document.getElementById(id);
cell.value = puzzle[i][j] === 0 ? '' : puzzle[i][j];
}
}
}
function findEmptyCell(puzzle){
for(let i = 0 ; i < puzzle.length; i++){
for (let j = 0; j < puzzle[i].length; j++) {
if(puzzle[i][j] === 0)
return {row:i,col:j};
}
}
return true;
}
function fillCells(puzzle){
for(let i = 0 ; i < puzzle.length; i++){
for (let j = 0; j < puzzle[i].length; j++) {
puzzle[i][j] = 1;
}
}
}
function validatePuzzle(puzzle, cellToCheck, digit){
// console.table(puzzle,cellToCheck, digit);
//check row
if(puzzle[cellToCheck.row].indexOf(digit) !== -1) return false;
//check col
for (let index = 0; index < 9; index++) {
if(puzzle[index][cellToCheck.col] === digit) return false;
}
//check 3x3
let bigSquareRow = Math.floor(cellToCheck.row/3) * 3;
let bigSquareCol = Math.floor(cellToCheck.col/3) * 3;
for (let i = bigSquareRow; i < bigSquareRow + 3; i++) {
for (let j = bigSquareCol; j < bigSquareCol + 3; j++) {
if(puzzle[i][j] === digit) return false;
}
}
return true;
}