void Solver::findPossibleSlots( const int box, std::vector<std::stack<std::pair<int,int>>>& backTrackStack, const int num) { int highestRow = (box/3)*3; //Row of upper-left box int highestCol = (box%3)*3; //Column of upper-left box std::vector<std::pair<int,int>> shuffleVec; /* Reversed the order so first item on stack is the upper-leftmost slot */ for(int rowIter = 2; rowIter >= 0; --rowIter) { for(int colIter = 2; colIter >= 0; --colIter) { bool existsRow = checkRow(highestRow + rowIter, num); bool existsCol = checkColumn(highestCol + colIter, num); if(!existsRow && !existsCol) { shuffleVec.push_back(std::make_pair(rowIter,colIter)); #ifdef DEBUG std::cout << "Adding possible slot " << rowIter << "," << colIter << " for " << num << std::endl; #endif } else if(existsRow) break; else continue; } } std::random_device seedGen; std::mt19937 randGen(seedGen()); std::shuffle(shuffleVec.begin(), shuffleVec.end(), randGen); for(auto p : shuffleVec) backTrackStack[num-1].push(p); }
void Solver::solveSemiSeed(const int semiSeed) { /* Create RNG */ std::random_device seedGen; std::mt19937 randGen(seedGen()); /* Generate semiSeed first */ int highestRow = (semiSeed/3)*3; //Row of upper-left box int highestCol = (semiSeed%3)*3; //Column of upper-left box std::array<int, 9> nums = {1,2,3,4,5,6,7,8,9}; std::shuffle(nums.begin(), nums.end(), randGen); #ifdef DEBUG std::cout << "nums:" << std::endl; for(auto e : nums) std::cout << e << " "; std::cout << std::endl; #endif for(int valIter = 0; valIter < 9; valIter++) { for(int boxIter = 0; boxIter < 9; boxIter++) { int currentRow = highestRow+boxIter/3; int currentCol = highestCol+boxIter%3; bool rowExists = checkRow(currentRow,nums[valIter]); bool colExists = checkColumn(currentCol,nums[valIter]); if(!rowExists && !colExists) { if( !sudokuBoard[semiSeed].addNumber( boxIter/3, boxIter%3, nums[valIter]) ) { #ifdef DEBUG std::cout << "Did not add " << nums[valIter] << " to semiSeed at " << boxIter/3 << "," << boxIter%3 << std::endl; #endif } else break; } else if(rowExists) boxIter+=2; else continue; } } #ifdef DEBUG std::cout << "semiSeed values:" << std::endl; sudokuBoard[semiSeed].debugPrint(); #endif }
int main(int argc, char* argv[]) { size_t NumRows = pow(2, MyRow::NumCol); if (argc > 1) { NumRows = atoi(argv[1]); } std::mt19937 seedGen(getpid()); std::uniform_int_distribution<uint32_t> numGen(0, MaxRangeForEachCol); typedef std::vector<MyRow> Table; Table table; // Enumerate all the combinations of possible columns for (uint32_t idx = 0; idx < NumRows; idx ++) { std::vector<uint32_t> arr; //std::generate_n(std::back_inserter(arr), MyRow::NumCol, [&] () -> uint32_t {return numGen(seedGen);}); // //std::cout << "idx=" << idx << "{"; for (uint32_t col = 0; col < MyRow::NumCol; col ++) { // if the bit-rep of i-th row has j-th bit set // set the j-th col for i-th row auto bit = (((0x1 << col) & idx) >> col); //std::cout << bit << ","; arr.push_back(bit); } //std::cout << "}" << std::endl; MyRow a(arr); table.push_back(a); } // Sort table based on Morton code std::sort(table.begin(), table.end()); // Print the rows sorted by Morton code for (auto& row : table) { std::cout << row << std::endl; } }
bool Solver::solve(const int box) { /* Create RNG */ std::random_device seedGen; std::mt19937 randGen(seedGen()); std::array<int, 9> nums = {1,2,3,4,5,6,7,8,9}; std::shuffle(nums.begin(), nums.end(), randGen); bool isSolved = true; #ifdef DEBUG std::cout << "solve2() random array" << std::endl; for(auto e : nums) std::cout << e << " "; std::cout << std::endl; #endif /* Create backtrack stack */ std::vector<std::stack<std::pair<int,int>>> backTrackStack(9); /* Find possible slots for each value */ for(int number = 1; number <= 9; ++number) findPossibleSlots(box, backTrackStack, number); for(int numsIter = 0; numsIter < 9; ++numsIter) { int number = nums[numsIter]-1; if(backTrackStack[number].empty()) { #ifdef DEBUG std::cout << "Empty at " << number+1 << std::endl; #endif findPossibleSlots(box, backTrackStack, number+1); numsIter--; if(numsIter == -1) { #ifdef DEBUG std::cout << "No solution possible for box " << box << std::endl; #endif isSolved = false; break; } number = nums[numsIter]-1; //Since numsIter is already decremented auto slot = backTrackStack[number].top(); int row = std::get<0>(slot); int col = std::get<1>(slot); sudokuBoard[box].removeNumber(row,col,number+1); backTrackStack[number].pop(); numsIter--; //Decrement even further continue; } auto slot = backTrackStack[number].top(); int row = std::get<0>(slot); int col = std::get<1>(slot); #ifdef DEBUG1 std::cout << "Adding " << number+1 << " at " << row << "," << col << std::endl; #endif if(!sudokuBoard[box].addNumber(row, col, number+1)) { #ifdef DEBUG1 std::cout << "Rejected " << number+1 << " at " << row << "," << col << std::endl; #endif /* Remove invalid slots */ backTrackStack[number].pop(); numsIter--; if(backTrackStack[number].empty()) { #ifdef DEBUG std::cout << "Empty at " << number+1 << std::endl; #endif findPossibleSlots(box, backTrackStack, number+1); number = nums[numsIter]-1; //Since numsIter is already decremented slot = backTrackStack[number].top(); row = std::get<0>(slot); col = std::get<1>(slot); sudokuBoard[box].removeNumber(row,col,number+1); backTrackStack[number].pop(); numsIter--; //Decrement even further if(numsIter <= -1) { #ifdef DEBUG std::cout << "No solution possible for box " << box << std::endl; #endif isSolved = false; break; } } } #ifdef DEBUG1 else std::cout << "Added!" << std::endl; #endif } //End of for-loop return isSolved; }