From 6255b786a1000b822c4c1c400e6cf8d6752e8382 Mon Sep 17 00:00:00 2001 From: Trianta <56975502+Trimutex@users.noreply.github.com> Date: Fri, 3 Nov 2023 00:56:45 -0500 Subject: [PATCH] Lots of performance improvements and fixed solution to work with subgrid --- src/sudoku.cpp | 133 ++++++++++++++++++++---------------------- src/sudoku.hpp | 11 ++-- src/sudoku_solver.cpp | 2 +- 3 files changed, 70 insertions(+), 76 deletions(-) diff --git a/src/sudoku.cpp b/src/sudoku.cpp index a8fb836..782bfc6 100644 --- a/src/sudoku.cpp +++ b/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) { + for (column = 0; column < 9; ++column) { + 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 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 Sudoku::GetUnusedRow(const int& row) { + std::vector 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 Sudoku::GetUnusedColumn(const int& column) { + std::vector 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 Sudoku::GetUnusedSubgrid(const int& row, const int& column) { + std::vector 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 Sudoku::GetUnusedRow(int row) { - std::vector 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 Sudoku::GetUnusedColumn(int column) { - std::vector 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& possibilities) { + for (auto it = possibilities.begin(); it != possibilities.end();) { + if (*it == 0) { it = possibilities.erase(it); } else { ++it; } } - return leftOver; -} - -std::vector Sudoku::GetUnusedSubgrid(int column, int row) { - std::vector 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; } diff --git a/src/sudoku.hpp b/src/sudoku.hpp index b6ff2e8..a15bd7a 100644 --- a/src/sudoku.hpp +++ b/src/sudoku.hpp @@ -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 GetUnusedRow(int row); - std::vector GetUnusedColumn(int column); - std::vector GetUnusedSubgrid(int column, int row); + bool FindEmptyCell(int& row, int& column); + std::vector GetUnusedRow(const int& row); + std::vector GetUnusedColumn(const int& column); + std::vector GetUnusedSubgrid(const int& row, const int& column); }; +void TrimPossiblities(std::vector& possibilities); + #endif diff --git a/src/sudoku_solver.cpp b/src/sudoku_solver.cpp index af2f165..879c0d7 100644 --- a/src/sudoku_solver.cpp +++ b/src/sudoku_solver.cpp @@ -9,6 +9,6 @@ int main(int argc, char* argv[]) { Sudoku newGame; newGame.FillBoard(argv[1]); newGame.Solve(); - newGame.RawPrint(); + newGame.Print(); return 0; }