void Table::solve() { if (!isSolvable()) return; clock_t t1 = clock(); unsigned long long masks[9] = { 0x0000000000000000ll, 0x1000000000000000ll, 0x1200000000000000ll, 0x1230000000000000ll, 0x1230000400000000ll, 0x1234000000000000ll, 0x1234500000000000ll, 0x1234560000000000ll, 0x123456789ABCDEF0ll }; Field field = m_startField; for (int i = 1; i < 9; i++) { field = searchForMask(field, masks[(i == 5 ? i - 3 : i - 1)], masks[i]); } while (field != m_startField) { m_solution.push_back(field); field = m_parent.at(field); } m_solution.push_back(m_startField); std::reverse(m_solution.begin(), m_solution.end()); m_isSolved = true; clock_t t2 = clock(); printf("%.3lf seconds\n", double(t2 - t1) / 1000); }
//This function sets the new dimentions of the puzzle and re-shuffles it. void Puzzle::setDimensions( int newWidth, int newHeight) { width = newWidth ; height = newHeight ; //It's not a square, so each dimention must be named turns = 0 ; do { //initialize it and shuffle it again until you come across a solvable one initPuzzle() ; shufflePuzzle() ; //cout << "Shuffled puzzle: \n"; //output(cout); }this was used in debugging, but is no longer needed //system("PAUSE"); } while ( !isSolvable() ) ; //do it until it's solved }
void sudokuBoard::newBoard() { // Robust generator populateBoard(); obfuscateBoard(); if ( isSolvable() ) { isCreated = true; isSolved = false; } else newBoard(); }
void Tile::Shuffle() { Reset(); for (int i = 1; i < 16; i++) { //get random number 1..15 int id = randInt(1,15); //swap it QPushButton *button_1 = idtoButton(i); QPushButton *button_2 = idtoButton(id); QString str = button_1->text(); button_1->setText(button_2->text()); button_2->setText(str); } if (!isSolvable()) { Shuffle(); } else { isRunning = 1; } }
std::vector <bool> GaussianEliminator::getSolution() { std::vector <bool> sol(vars, false) ; if (!isSolvable()) throw; for (int k = vars-1; k >= 0; k --){ unsigned int size = rows[k].eq.size(); bool parity = false; for (int j = size - 1; j > 0; j --) parity ^= sol[rows[k].eq[j]]; sol[k] = parity ^ constTerms[k]; } return sol; }
// This sets the first empty cell to the least possible value and returns a Square with row // and col of cell it edits. This function is used inside the recursiveSolver() function to // make guesses systematically. // If the first empty cell has no possible values the Square that is returned will have -1 for // row and col. Square Sudoku::makeGuess() { Square saved; saved.row = -1; saved.col = -1; // Only make a guess on valid unsolved boards. if( isSolvable() && !isSolved() ) { // Find the first empty cell and save it. for( int r = 0; r < 9; r++ ) { for( int c = 0; c < 9; c++ ) { if( 0 == cell[r][c] ) { saved.row = r; saved.col = c; break; } } if( -1 != saved.row ) break; } // Loop through values 1-9 for( int v = 1; v <= 9; v++ ) { // Try to assign the value to the saved empty cell // Exit once it's set. // This assigns the lowest possible value. if( set( saved.row, saved.col, v ) ) { break; } } } return saved; }
bool GaussianEliminator::addEquation(Equation eq, bool term) { Row nrow; while(eq.size()) { unsigned short int fp = eq[0]; if (rows[fp].set){ eq += rows[fp].eq; term ^= constTerms[fp]; } else { rows[fp].set = true; rows[fp].eq = eq; constTerms[fp] = term; rowsUnset --; break; } } if (isSolvable()) return true; return false; }
// The recursive solver will solve any valid board. // Returns TRUE If the board is solved. // Returns FALSE if the board is not solved and all appropriate guesses have been exhausted. bool Sudoku::recursiveSolver( /*int depth*/ ) { Sudoku original = *this; Sudoku child; Square saved; int guess = 0; bool validGuess; // Solve the board as much as possible deterministically. deterministic(); // Save a copy of the board so that changes made from invalid // guesses can be reverted to the original parent. Sudoku parent = *this; // // Display the depth and current board state. // cout << "depth: " << depth << endl; // print(); // If the board is invalid return false. if( !isSolvable() ) { return false; } // If the board is solved return true. if( isSolved() ) { return true; } // If the board is still valid but not solved we need to make guesses. else { int iter = 0; do { // Make a guess of the lowest possible value in the first empty cell // Save the cell where the guess is. saved = makeGuess(); // If we have exhausted the guesses in the first empty cell then // exit since this is no longer a valid board. if( saved.row == -1 ) { break; } // Save the value of the guess made in the "Square saved" cell. guess = cell[saved.row][saved.col]; // The recursiveSolver() will return whether the board is solved after making that guess. validGuess = recursiveSolver( /*depth + 1*/ ); // If it solved it return true. if( validGuess ) { return true; } // If the board was not solved then the guess was not valid. // Revert the board to the parent. // Remove guess from the possible values in the saved cell. // Update parent so it remembers the guesses we have already tried. else { *this = parent; possible[saved.row][saved.col][guess] = false; parent = *this; } }while( !validGuess && saved.row != -1 && iter++ < 9 ); // Some redundancies in the while loop exit criteria // Do this while the last guess was bad and there are still // more guesses to make. // Also never loop more than 9 guesses. ( redundant, should never catch ) } // If we pass all of that then the board had all the guesses exhausted in a particular cell. // This means we have a cell with no possible values. // Revert to the parent board. // Exit and pass back up to the calling function. // If this was called recursively then the next level down will make the next appropriate guess in // the last cell where a guess was made. *this = original; return false; }