-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolver.c
126 lines (110 loc) · 3.83 KB
/
solver.c
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
#include "solver.h"
/**
* solvePuzzleRec is a recursive function (to be called by solvePuzzle). It is used to
* solve a given sudoku puzzle board. In its recursive calls, generatePuzzleRec will
* fill the board, employing the deterministic backtracking algorithm, cell by cell,
* left to right and top to bottom.
*
* @param solution [in, out] a pointer to a Board struct whose cell will be set
* @param curRow [in] row number of the cell currently being set
* @param curCol [in] column number of the cell currently being set
* @return true iff the halting condition was reached: the board is completely
* filled
* @return false iff there exists no valid value to set in the current cell, and
* its value was set to EMPTY_CELL_VALUE.
*/
bool solvePuzzleRec(Board* solution, int curRow, int curCol) {
int nextRow = 0, nextCol = 0;
int value = 0;
if (curRow == N_SQUARE)
return true;
if (curCol == N_SQUARE - 1) {
nextRow = curRow + 1;
nextCol = 0;
} else {
nextRow = curRow;
nextCol = curCol + 1;
}
if (! isCellEmpty(solution, curRow, curCol)) {
return solvePuzzleRec(solution, nextRow, nextCol);
}
for (value = 1; value <= N_SQUARE; value++) {
if (isCellValueValid(solution, curRow, curCol, value)) {
setCellValue(solution, curRow, curCol, value);
if (solvePuzzleRec(solution, nextRow, nextCol)) {
return true;
}
}
}
emptyCell(solution, curRow, curCol);
return false;
}
bool solvePuzzle(State* state, Board* solutionOut) {
Board board;
exportBoard(state, &board);
if (solvePuzzleRec(&board, 0, 0)) {
*solutionOut = board;
return true;
}
return false;
}
/**
* generatePuzzleRec is a recursive function (to be called by generatePuzzle).
* It is used to generate a new sudoku puzzle board. In its recursive calls,
* generatePuzzleRec will fill the board, employing the randomized backtracking
* algorithm, cell by cell, left to right and top to bottom.
*
* @param board [in, out] the board currently being filled
* @param curRow [in] row number of the cell currently being set
* @param curCol [in] column number of the cell currently being set
* @return true iff the halting condition was reached: the board is completely
* filled
* @return false iff there exists no valid value to set in the current cell, and
* its value was set to EMPTY_CELL_VALUE.
*/
bool generatePuzzleRec(Board* board, int curRow, int curCol) {
int nextRow = 0, nextCol = 0;
int value = 0;
int potentialValues[N_SQUARE] = {0};
int numPotentialValues = 0;
/* If the board is completely filled */
if (curRow == N_SQUARE)
return true;
if (curCol == N_SQUARE - 1) {
nextRow = curRow + 1;
nextCol = 0;
} else {
nextRow = curRow;
nextCol = curCol + 1;
}
if (! isCellEmpty(board, curRow, curCol)) {
return generatePuzzleRec(board, nextRow, nextCol);
}
for (value = 1; value <= N_SQUARE; value++) /* NOTE: could improve complexity of this */
if (isCellValueValid(board, curRow, curCol, value))
potentialValues[numPotentialValues++] = value;
while (numPotentialValues > 0) {
int chosenIndex = 0;
if (numPotentialValues > 1) {
chosenIndex = rand() % numPotentialValues;
}
setCellValue(board, curRow, curCol, potentialValues[chosenIndex]);
if (generatePuzzleRec(board, nextRow, nextCol)) {
return true;
} else {
/* NOTE: this is the smart way (complexity-wise) of doing this -
potentialValues[randomIndex] = potentialValues[numPotentialValues--]; */
int i = 0;
numPotentialValues--;
for (i = chosenIndex; i < numPotentialValues; i++)
potentialValues[i] = potentialValues[i + 1];
}
}
emptyCell(board, curRow, curCol);
return false;
}
bool generatePuzzle(Board* board) {
return generatePuzzleRec(board, 0, 0);
}
/* Note: potentially those two functions (randomised vs. deterministic) could be
* merged somehow to reflect indeed how very similar they are */