generated from Trianta/cpp-unity-template
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
dd3c92f6f7 | ||
|
6255b786a1 |
133
src/sudoku.cpp
133
src/sudoku.cpp
@ -25,13 +25,19 @@ void Sudoku::FillBoard(std::string filePath) {
|
||||
|
||||
// Base global call for solving
|
||||
void Sudoku::Solve(void) {
|
||||
_Solve();
|
||||
if (!_Solve()) { std::cerr << "No solution found" << std::endl; }
|
||||
}
|
||||
|
||||
bool Sudoku::IsBoardSolved(void) {
|
||||
int column, row;
|
||||
if (!FindEmptyCell(&column, &row)) { return true; }
|
||||
return false;
|
||||
int row, column;
|
||||
for (row = 0; row < 9; row += 3) {
|
||||
for (column = 0; column < 9; column += 3) {
|
||||
if (!GetUnusedRow(row).empty()) { return false; }
|
||||
if (!GetUnusedColumn(column).empty()) { return false; }
|
||||
if (!GetUnusedSubgrid(row, column).empty()) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sudoku::Print(void) {
|
||||
@ -57,12 +63,19 @@ void Sudoku::RawPrint(void) {
|
||||
|
||||
// Recursive call for solving
|
||||
bool Sudoku::_Solve(void) {
|
||||
int column, row;
|
||||
if (!FindEmptyCell(&column, &row)) { return true; }
|
||||
for (int i : GetUnusedRow(row)) {
|
||||
for (int j : GetUnusedColumn(column)) {
|
||||
for (int k : GetUnusedSubgrid(column, row)) {
|
||||
if (i == j == k) {
|
||||
int row, column;
|
||||
if (!FindEmptyCell(row, column)) {
|
||||
if (IsBoardSolved()) { return true; }
|
||||
return false;
|
||||
}
|
||||
std::vector<int> rowPossiblities, columnPossibilities, subgridPossibilities;
|
||||
rowPossiblities = GetUnusedRow(row);
|
||||
columnPossibilities = GetUnusedColumn(column);
|
||||
subgridPossibilities = GetUnusedSubgrid(row, column);
|
||||
for (int i : rowPossiblities) {
|
||||
for (int j : columnPossibilities) {
|
||||
for (int k : subgridPossibilities) {
|
||||
if (i == j && j == k) {
|
||||
board[row][column] = i;
|
||||
if (_Solve()) { return true; }
|
||||
board[row][column] = 0;
|
||||
@ -70,83 +83,63 @@ bool Sudoku::_Solve(void) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fills column and row of an empty cell and returns true
|
||||
// If no empty cell is found, return false
|
||||
bool Sudoku::FindEmptyCell(int* column, int* row) {
|
||||
for (*row = 0; *row < 9; ++(*row)) {
|
||||
for (*column = 0; *column < 9; ++(*column)) {
|
||||
if (board[*row][*column] == 0) { return true; }
|
||||
bool Sudoku::FindEmptyCell(int& row, int& column) {
|
||||
for (row = 0; row < 9; ++(row)) {
|
||||
for (column = 0; column < 9; ++(column)) {
|
||||
if (board[row][column] == 0) { return true; }
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sudoku::IsValidPlacement(int column, int row, int box) {
|
||||
// Check column and row
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
if (board[row][i] == box || board[i][column] == box) {
|
||||
return false;
|
||||
}
|
||||
// Returns vector of unused numbers in row
|
||||
std::vector<int> Sudoku::GetUnusedRow(const int& row) {
|
||||
std::vector<int> leftOver{0,1,2,3,4,5,6,7,8,9};
|
||||
int* box;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
box = &board[row][i];
|
||||
if (leftOver[*box] == *box) { leftOver[*box] = 0; }
|
||||
}
|
||||
|
||||
// Check subgrid
|
||||
int startRow = row - row % 3;
|
||||
int startColumn = column - column % 3;
|
||||
TrimPossiblities(leftOver);
|
||||
return leftOver;
|
||||
}
|
||||
|
||||
// Returns vector of unused numbers in column
|
||||
std::vector<int> Sudoku::GetUnusedColumn(const int& column) {
|
||||
std::vector<int> leftOver{0,1,2,3,4,5,6,7,8,9};
|
||||
int* box;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
box = &board[i][column];
|
||||
if (leftOver[*box] == *box) { leftOver[*box] = 0; }
|
||||
}
|
||||
TrimPossiblities(leftOver);
|
||||
return leftOver;
|
||||
}
|
||||
|
||||
// Returns vector of unused numbers in subgrid
|
||||
std::vector<int> Sudoku::GetUnusedSubgrid(const int& row, const int& column) {
|
||||
std::vector<int> leftOver{0,1,2,3,4,5,6,7,8,9};
|
||||
int* box;
|
||||
int startRow = row - (row % 3);
|
||||
int startColumn = column - (column % 3);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
if (board[startRow + i][startColumn + j] == box) { return false; }
|
||||
box = &board[startRow + i][startColumn + j];
|
||||
if (leftOver[*box] == *box) { leftOver[*box] = 0; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<int> Sudoku::GetUnusedRow(int row) {
|
||||
std::vector<int> leftOver{0,1,2,3,4,5,6,7,8,9};
|
||||
int box;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
box = board[row][i];
|
||||
if (leftOver[box] == box) { leftOver[box] = 0; }
|
||||
}
|
||||
for (auto it = leftOver.begin(); it != leftOver.end();) {
|
||||
if (*it == 0) { it = leftOver.erase(it); }
|
||||
else { ++it; }
|
||||
}
|
||||
TrimPossiblities(leftOver);
|
||||
return leftOver;
|
||||
}
|
||||
|
||||
std::vector<int> Sudoku::GetUnusedColumn(int column) {
|
||||
std::vector<int> leftOver{0,1,2,3,4,5,6,7,8,9};
|
||||
int box;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
box = board[i][column];
|
||||
if (leftOver[box] == box) { leftOver[box] = 0; }
|
||||
}
|
||||
for (auto it = leftOver.begin(); it != leftOver.end();) {
|
||||
if (*it == 0) { it = leftOver.erase(it); }
|
||||
void TrimPossiblities(std::vector<int>& possibilities) {
|
||||
for (auto it = possibilities.begin(); it != possibilities.end();) {
|
||||
if (*it == 0) { it = possibilities.erase(it); }
|
||||
else { ++it; }
|
||||
}
|
||||
return leftOver;
|
||||
}
|
||||
|
||||
std::vector<int> Sudoku::GetUnusedSubgrid(int column, int row) {
|
||||
std::vector<int> leftOver{0,1,2,3,4,5,6,7,8,9};
|
||||
int box;
|
||||
int startRow = row - row % 3;
|
||||
int startColumn = column - column % 3;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
box = board[row][column];
|
||||
if (board[startRow + i][startColumn + j] == box) {
|
||||
leftOver[box] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = leftOver.begin(); it != leftOver.end();) {
|
||||
if (*it == 0) { it = leftOver.erase(it); }
|
||||
else { ++it; }
|
||||
}
|
||||
return leftOver;
|
||||
}
|
||||
|
@ -15,11 +15,12 @@ public:
|
||||
void RawPrint(void);
|
||||
private:
|
||||
bool _Solve(void);
|
||||
bool FindEmptyCell(int* column, int* row);
|
||||
bool IsValidPlacement(int column, int row, int box);
|
||||
std::vector<int> GetUnusedRow(int row);
|
||||
std::vector<int> GetUnusedColumn(int column);
|
||||
std::vector<int> GetUnusedSubgrid(int column, int row);
|
||||
bool FindEmptyCell(int& row, int& column);
|
||||
std::vector<int> GetUnusedRow(const int& row);
|
||||
std::vector<int> GetUnusedColumn(const int& column);
|
||||
std::vector<int> GetUnusedSubgrid(const int& row, const int& column);
|
||||
};
|
||||
|
||||
void TrimPossiblities(std::vector<int>& possibilities);
|
||||
|
||||
#endif
|
||||
|
@ -9,6 +9,6 @@ int main(int argc, char* argv[]) {
|
||||
Sudoku newGame;
|
||||
newGame.FillBoard(argv[1]);
|
||||
newGame.Solve();
|
||||
newGame.RawPrint();
|
||||
newGame.Print();
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user