Compare commits

...

2 Commits
master ... dev

Author SHA1 Message Date
Trianta
dd3c92f6f7 Minor final check performance increase 2023-11-03 01:01:28 -05:00
Trianta
6255b786a1 Lots of performance improvements and fixed solution to work with subgrid 2023-11-03 00:56:45 -05:00
3 changed files with 70 additions and 76 deletions

View File

@ -25,13 +25,19 @@ void Sudoku::FillBoard(std::string filePath) {
// Base global call for solving // Base global call for solving
void Sudoku::Solve(void) { void Sudoku::Solve(void) {
_Solve(); if (!_Solve()) { std::cerr << "No solution found" << std::endl; }
} }
bool Sudoku::IsBoardSolved(void) { bool Sudoku::IsBoardSolved(void) {
int column, row; int row, column;
if (!FindEmptyCell(&column, &row)) { return true; } for (row = 0; row < 9; row += 3) {
return false; 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) { void Sudoku::Print(void) {
@ -57,12 +63,19 @@ void Sudoku::RawPrint(void) {
// Recursive call for solving // Recursive call for solving
bool Sudoku::_Solve(void) { bool Sudoku::_Solve(void) {
int column, row; int row, column;
if (!FindEmptyCell(&column, &row)) { return true; } if (!FindEmptyCell(row, column)) {
for (int i : GetUnusedRow(row)) { if (IsBoardSolved()) { return true; }
for (int j : GetUnusedColumn(column)) { return false;
for (int k : GetUnusedSubgrid(column, row)) { }
if (i == j == k) { 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; board[row][column] = i;
if (_Solve()) { return true; } if (_Solve()) { return true; }
board[row][column] = 0; 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 // Fills column and row of an empty cell and returns true
// If no empty cell is found, return false // If no empty cell is found, return false
bool Sudoku::FindEmptyCell(int* column, int* row) { bool Sudoku::FindEmptyCell(int& row, int& column) {
for (*row = 0; *row < 9; ++(*row)) { for (row = 0; row < 9; ++(row)) {
for (*column = 0; *column < 9; ++(*column)) { for (column = 0; column < 9; ++(column)) {
if (board[*row][*column] == 0) { return true; } if (board[row][column] == 0) { return true; }
} }
} }
return false; return false;
} }
bool Sudoku::IsValidPlacement(int column, int row, int box) { // Returns vector of unused numbers in row
// Check column and row std::vector<int> Sudoku::GetUnusedRow(const int& row) {
for (int i = 0; i < 9; ++i) { std::vector<int> leftOver{0,1,2,3,4,5,6,7,8,9};
if (board[row][i] == box || board[i][column] == box) { int* box;
return false; for (int i = 0; i < 9; i++) {
box = &board[row][i];
if (leftOver[*box] == *box) { leftOver[*box] = 0; }
} }
TrimPossiblities(leftOver);
return leftOver;
} }
// Check subgrid // Returns vector of unused numbers in column
int startRow = row - row % 3; std::vector<int> Sudoku::GetUnusedColumn(const int& column) {
int startColumn = column - column % 3; 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 i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) { 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; TrimPossiblities(leftOver);
}
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; }
}
return leftOver; return leftOver;
} }
std::vector<int> Sudoku::GetUnusedColumn(int column) { void TrimPossiblities(std::vector<int>& possibilities) {
std::vector<int> leftOver{0,1,2,3,4,5,6,7,8,9}; for (auto it = possibilities.begin(); it != possibilities.end();) {
int box; if (*it == 0) { it = possibilities.erase(it); }
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); }
else { ++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;
} }

View File

@ -15,11 +15,12 @@ public:
void RawPrint(void); void RawPrint(void);
private: private:
bool _Solve(void); bool _Solve(void);
bool FindEmptyCell(int* column, int* row); bool FindEmptyCell(int& row, int& column);
bool IsValidPlacement(int column, int row, int box); std::vector<int> GetUnusedRow(const int& row);
std::vector<int> GetUnusedRow(int row); std::vector<int> GetUnusedColumn(const int& column);
std::vector<int> GetUnusedColumn(int column); std::vector<int> GetUnusedSubgrid(const int& row, const int& column);
std::vector<int> GetUnusedSubgrid(int column, int row);
}; };
void TrimPossiblities(std::vector<int>& possibilities);
#endif #endif

View File

@ -9,6 +9,6 @@ int main(int argc, char* argv[]) {
Sudoku newGame; Sudoku newGame;
newGame.FillBoard(argv[1]); newGame.FillBoard(argv[1]);
newGame.Solve(); newGame.Solve();
newGame.RawPrint(); newGame.Print();
return 0; return 0;
} }