|
3 | 3 | * @return {void} Do not return anything, modify board in-place instead.
|
4 | 4 | */
|
5 | 5 | var solveSudoku = function(board) {
|
6 |
| - while (true) { |
7 |
| - const prevBoard = board |
8 |
| - for (let rowIndex = 0; rowIndex < 9; rowIndex++) { |
9 |
| - for (let colIndex = 0; colIndex < 9; colIndex++) { |
10 |
| - const solvable = solveElement(board, rowIndex, colIndex) |
11 |
| - if (!solvable) return false |
12 |
| - } |
13 |
| - } |
14 |
| - if (isSameBoard(board, prevBoard)) break |
15 |
| - } |
16 |
| - |
17 |
| - if (isBoardSolved(board)) return board |
18 |
| - |
19 |
| - const branchBoards = generateBranchBoards(board) |
20 |
| - |
21 | 6 |
|
22 | 7 |
|
23 |
| - const solvedBoards = branchBoards.map((branchBoard) => solveSudoku(branchBoard)).filter((solvedBoard) => solvedBoard) |
24 |
| - |
25 |
| - if (solvedBoards.length === 1){ |
| 8 | + function possible(y,x,n) { |
26 | 9 | for (let i = 0; i < 9; i++){
|
27 |
| - for (let j = 0; j < 9; j++){ |
28 |
| - board[i][j] = solvedBoards[0][i][j] |
| 10 | + if (board[y][i] === n.toString()) { |
| 11 | + return false |
29 | 12 | }
|
30 | 13 | }
|
31 |
| - return solvedBoards[0] |
32 |
| - } |
33 |
| - |
34 |
| - return false |
35 |
| -}; |
36 |
| - |
37 |
| - |
38 | 14 |
|
39 |
| -const isBoardSolved = (board) => { |
40 |
| - for (let row of board) { |
41 |
| - for (let el of row) { |
42 |
| - if (el === ".") return false |
| 15 | + for (let i = 0; i < 9; i++){ |
| 16 | + if (board[i][x] === n.toString()) { |
| 17 | + return false |
| 18 | + } |
43 | 19 | }
|
44 |
| - } |
45 |
| - |
46 |
| - return true |
47 |
| -} |
48 |
| - |
49 |
| -const possibilities = ['1','2','3','4','5','6','7','8','9'] |
50 |
| - |
51 |
| - |
52 |
| -const solveElement = (board, rowIndex, colIndex) => { |
53 |
| - if (board[rowIndex][colIndex] !== ".") return true |
54 |
| - |
55 | 20 |
|
56 |
| - const rowElements = findRowElements(board, rowIndex, colIndex) |
57 |
| - const colElements = findColElements(board, rowIndex, colIndex) |
58 |
| - const boxElements = findBoxElements(board, rowIndex, colIndex) |
| 21 | + const x0 = Math.floor(x / 3) * 3 |
| 22 | + const y0 = Math.floor(y/3) * 3 |
59 | 23 |
|
60 |
| - const possibilitiesToRemove = [...rowElements, ...colElements, ...boxElements] |
61 |
| - |
62 |
| - const remainingPossibilties = possibilities.filter((number) => !possibilitiesToRemove.includes(number)) |
63 |
| - if (!remainingPossibilties.length) return false |
64 |
| - |
65 |
| - if (remainingPossibilties.length === 1) { |
66 |
| - board[rowIndex][colIndex] = remainingPossibilties[0] |
67 |
| - |
68 |
| - const solvable = solveRowElements(board, rowIndex) && solveColElements(board, colIndex) && solveBoxElements(board, rowIndex, colIndex) |
69 |
| - if (!solvable) return false |
70 |
| - } |
71 |
| - |
72 |
| - return true |
73 |
| - |
74 |
| -} |
75 |
| - |
76 |
| -const findRowElements = (board, rowIndex, colIndex) => { |
77 |
| - const result = [] |
78 |
| - |
79 |
| - for (let j = 0; j < 9; j++) { |
80 |
| - const value = board[rowIndex][j] |
81 |
| - if (j !== colIndex && value !== ".") result.push(value) |
82 |
| - } |
83 |
| - |
84 |
| - return result |
85 |
| -} |
86 |
| - |
87 |
| -const findColElements = (board, rowIndex, colIndex) => { |
88 |
| - const result = [] |
89 |
| - |
90 |
| - for (let i = 0; i < 9; i++) { |
91 |
| - const value = board[i][colIndex] |
92 |
| - if (i !== rowIndex && value !== ".") result.push(value) |
93 |
| - } |
94 |
| - |
95 |
| - return result |
96 |
| -} |
97 |
| - |
98 |
| -const findBoxElements = (board, rowIndex, colIndex) => { |
99 |
| - const result = [] |
100 |
| - |
101 |
| - for (let i = Math.floor(rowIndex/3) * 3; i < Math.floor(rowIndex/3) * 3 + 3; i++){ |
102 |
| - for (let j = Math.floor(colIndex/3) * 3; j < Math.floor(colIndex/3) * 3 + 3; j++){ |
103 |
| - const value = board[i][j] |
104 |
| - |
105 |
| - if (!(i === rowIndex && j === colIndex) && value !== ".") { |
106 |
| - result.push(value) |
| 24 | + for (let i = 0; i < 3; i++) { |
| 25 | + for (let j = 0; j < 3; j++) { |
| 26 | + if (board[y0+i][x0+j] === n.toString()) { |
| 27 | + return false |
| 28 | + } |
107 | 29 | }
|
108 | 30 | }
|
| 31 | + |
| 32 | + return true |
109 | 33 | }
|
110 |
| - |
111 |
| - return result |
112 |
| -} |
113 |
| - |
114 |
| -const solveRowElements = (board, rowIndex) => { |
115 |
| - for (let j = 0; j < 9; j++) { |
116 |
| - const solvable = solveElement(board, rowIndex, j) |
117 |
| - if (!solvable) return false |
118 |
| - } |
119 |
| - |
120 |
| - return true |
121 |
| -} |
122 |
| - |
123 |
| - |
124 |
| -const solveColElements = (board, colIndex) => { |
125 |
| - for (let i = 0; i < 9; i++) { |
126 |
| - const solvable = solveElement(board, i, colIndex) |
127 |
| - if (!solvable) return false |
128 |
| - } |
129 |
| - |
130 |
| - return true |
131 |
| -} |
| 34 | + |
132 | 35 |
|
133 | 36 |
|
134 |
| -const solveBoxElements = (board, rowIndex, colIndex) => { |
135 |
| - for (let i = Math.floor(rowIndex/3) * 3; i < Math.floor(rowIndex/3) * 3 + 3; i++){ |
136 |
| - for (let j = Math.floor(colIndex/3) * 3; j < Math.floor(colIndex/3) * 3 + 3; j++){ |
137 |
| - const solvable = solveElement(board, i, j) |
138 |
| - if (!solvable) return false |
139 |
| - } |
140 |
| - } |
141 | 37 |
|
142 |
| - return true |
143 |
| -} |
144 | 38 |
|
145 |
| -const isSameBoard = (board, prevBoard) => { |
146 |
| - for (let i = 0; i < 9; i++) { |
| 39 | + for (let i = 0; i < 9; i++){ |
147 | 40 | for (let j = 0; j < 9; j++) {
|
148 |
| - if (board[i][j] !== prevBoard[i][j]) return false |
149 |
| - } |
150 |
| - } |
151 |
| - return true |
152 |
| -} |
153 |
| - |
154 |
| -const generateBranchBoards = (board) => { |
155 |
| - let leastPossibilitiesPosition = { |
156 |
| - rowIndex: 0, |
157 |
| - colIndex: 0, |
158 |
| - possibilities: ['1','2','3','4','5','6','7','8','9'] |
159 |
| - } |
160 |
| - |
161 |
| - for (let rowIndex = 0; rowIndex < 9; rowIndex++) { |
162 |
| - for (let colIndex = 0; colIndex < 9; colIndex++) { |
163 |
| - if (board[rowIndex][colIndex] === ".") { |
164 |
| - const rowElements = findRowElements(board, rowIndex, colIndex) |
165 |
| - const colElements = findColElements(board, rowIndex, colIndex) |
166 |
| - const boxElements = findBoxElements(board, rowIndex, colIndex) |
167 | 41 |
|
168 |
| - const possibilitiesToRemove = [...rowElements, ...colElements, ...boxElements] |
169 |
| - |
170 |
| - const remainingPossibilties = possibilities.filter((number) => !possibilitiesToRemove.includes(number)) |
171 |
| - |
172 |
| - if (remainingPossibilties.length < leastPossibilitiesPosition.possibilities.length) { |
173 |
| - leastPossibilitiesPosition.rowIndex = rowIndex |
174 |
| - leastPossibilitiesPosition.colIndex = colIndex |
175 |
| - leastPossibilitiesPosition.possibilities = remainingPossibilties |
| 42 | + if (board[i][j] === ".") { |
| 43 | + for (let k = 1; k < 10; k++) { |
| 44 | + if (possible(i, j, k)) { |
| 45 | + board[i][j] = k.toString() |
| 46 | + solveSudoku(board) |
| 47 | + board[i][j] = "." |
| 48 | + } |
176 | 49 | }
|
177 | 50 | }
|
| 51 | + |
| 52 | + return board |
178 | 53 | }
|
179 | 54 | }
|
180 |
| - |
181 |
| - |
182 |
| - return leastPossibilitiesPosition.possibilities.map((number) => { |
183 |
| - const boardCopy = board.map((row) => [...row]) |
184 |
| - boardCopy[leastPossibilitiesPosition.rowIndex][leastPossibilitiesPosition.colIndex] = number |
185 |
| - return boardCopy |
186 |
| - }) |
187 |
| - |
188 |
| - |
189 | 55 | }
|
190 | 56 |
|
191 | 57 |
|
| 58 | + |
192 | 59 | const board = [
|
193 | 60 | [".", ".", "9", "7", "4", "8", ".", ".", "."],
|
194 | 61 | ["7", ".", ".", ".", ".", ".", ".", ".", "."],
|
|
0 commit comments