#include <vector> #include <string> #include <iostream> bool possible(unsigned i, char n, std::string& grid) //check if is possible placing element 'n' in 'i' position of the string { //the controls must be done relative to columns and rows, so it's necessary converting 'i' to the relative col and row unsigned c = i % 9; unsigned r = i / 9; unsigned c0 = (c / 3) * 3, r0 = (r / 3) * 3; for(unsigned k = 0; k < 9; k++) if(grid[9 * r + k] == n || grid[9 * k + c] == n || grid[9 * (r0 + k / 3) + (c0 + k % 3)] == n) return false; return true; } bool backtrack(std::string& grid) //recursively try to fill the scheme with possible solutions, till it fills the whole scheme { for(unsigned i = 0; i < 81; i++) if(grid[i] == '0') { for(char n = '1'; n <= '9'; n++) if(possible(i, n, grid)) { grid[i] = n; if(backtrack(grid)) return true; grid[i] = '0'; } return false; } return true; } std::string solve_sudoku(std::string puzzleString) { backtrack(puzzleString); return puzzleString; }
- #include <vector>
- #include <string>
- #include <iostream>
/* Sudokus are good examples for backtracking* The algorithm try to place numbers in the empty spots untill it can or untill it solves the puzzle*//* The first function determine if, in the grid "grid" at position x and y an n is acceptable.* The k is used to iterate each subset: row, column and square, where x0 and y0 are the coordinates of the top left corner of the square*/bool possible(unsigned x, unsigned y, int n, std::vector<std::vector<int>>& grid)- bool possible(unsigned i, char n, std::string& grid) //check if is possible placing element 'n' in 'i' position of the string
- {
unsigned x0 = (x / 3) * 3, y0 = (y / 3) * 3;- //the controls must be done relative to columns and rows, so it's necessary converting 'i' to the relative col and row
- unsigned c = i % 9;
- unsigned r = i / 9;
- unsigned c0 = (c / 3) * 3, r0 = (r / 3) * 3;
- for(unsigned k = 0; k < 9; k++)
if(grid[y][k] == n || grid[k][x] == n || grid[y0 + k / 3][x0 + k % 3] == n)- if(grid[9 * r + k] == n || grid[9 * k + c] == n || grid[9 * (r0 + k / 3) + (c0 + k % 3)] == n)
- return false;
- return true;
- }
/* The backtracking function is a recursive function! each call keeps track of it's own x and y coordinates.* The function operates on a referenced grid. It scans each xy couple and, if it's zero, it tryes to put a number, checked with the "possible" funciton.* If the number is ok, then the function call itself.* Now, if the recursion find a solution then returns true so all the parent calls know the solution has been found. Otherwise, the parent function try to* go ahead and try another possible number.*/bool backtrack(std::vector<std::vector<int>>& grid)- bool backtrack(std::string& grid) //recursively try to fill the scheme with possible solutions, till it fills the whole scheme
- {
for(unsigned y = 0; y < 9; y++)for(unsigned x = 0; x < 9; x++)if(grid[y][x] == 0){for(unsigned n = 1; n <= 9; n++)if(possible(x, y, n, grid)){grid[y][x] = n;if(backtrack(grid)) return true;grid[y][x] = 0;}return false;}- for(unsigned i = 0; i < 81; i++)
- if(grid[i] == '0')
- {
- for(char n = '1'; n <= '9'; n++)
- if(possible(i, n, grid))
- {
- grid[i] = n;
- if(backtrack(grid)) return true;
- grid[i] = '0';
- }
- return false;
- }
- return true;
- }
/* The main function parses the string (Why the string tho?) and then parses the solution.* In this case, it won't check if a puzzle is impossible to solbe*/- std::string solve_sudoku(std::string puzzleString)
- {
std::vector<std::vector<int>> puzzle(9, std::vector<int>(9, 0));for(unsigned i = 0; i < 81; i++)puzzle[i / 9][i % 9] = puzzleString[i] - '0';backtrack(puzzle);std::string out = "";for(auto& i : puzzle)for(auto& j : i)out += std::to_string(j);return out;}- backtrack(puzzleString);
- return puzzleString;
- }
// TODO: Replace examples and use TDD by writing your own tests Describe(Solve_Sudoku) { It(Medium_Sudokus) { Assert::That(solve_sudoku("300000000050703008000028070700000043000000000003904105400300800100040000968000200"), Equals("387419526259763418641528379716285943594631782823974165472396851135842697968157234")); Assert::That(solve_sudoku("130400000705300000600020000000000027000900400000000085860500003059103000002004060"), Equals("138479652725316894694825731541638927283957416976241385867592143459163278312784569")); Assert::That(solve_sudoku("090035406001000000007000089070940050100200000006800700008004030000600040605000000"), Equals("892735416561489372437162589273946158184257963956813724728594631319678245645321897")); Assert::That(solve_sudoku("001230000004000000005000461000502007500040002100603000826000300000000800000096100"), Equals("961234785784165293235789461648512937573948612192673548826451379419327856357896124")); Assert::That(solve_sudoku("947001000000300800005020000010050000700800004603000010000930460070002000000005000"), Equals("947581236162397845835426791214659378759813624683274519521938467478162953396745182")); } };
- // TODO: Replace examples and use TDD by writing your own tests
- Describe(Solve_Sudoku)
- {
- It(Medium_Sudokus)
- {
- Assert::That(solve_sudoku("300000000050703008000028070700000043000000000003904105400300800100040000968000200"), Equals("387419526259763418641528379716285943594631782823974165472396851135842697968157234"));
- Assert::That(solve_sudoku("130400000705300000600020000000000027000900400000000085860500003059103000002004060"), Equals("138479652725316894694825731541638927283957416976241385867592143459163278312784569"));
- Assert::That(solve_sudoku("090035406001000000007000089070940050100200000006800700008004030000600040605000000"), Equals("892735416561489372437162589273946158184257963956813724728594631319678245645321897"));
- Assert::That(solve_sudoku("001230000004000000005000461000502007500040002100603000826000300000000800000096100"), Equals("961234785784165293235789461648512937573948612192673548826451379419327856357896124"));
- Assert::That(solve_sudoku("947001000000300800005020000010050000700800004603000010000930460070002000000005000"), Equals("947581236162397845835426791214659378759813624683274519521938467478162953396745182"));
- }
- };
#include <vector> #include <string> /* Sudokus are good examples for backtracking * The algorithm try to place numbers in the empty spots untill it can or untill it solves the puzzle */ /* The first function determine if, in the grid "grid" at position x and y an n is acceptable. * The k is used to iterate each subset: row, column and square, where x0 and y0 are the coordinates of the top left corner of the square */ bool possible(unsigned x, unsigned y, int n, std::vector<std::vector<int>>& grid) { unsigned x0 = (x / 3) * 3, y0 = (y / 3) * 3; for(unsigned k = 0; k < 9; k++) if(grid[y][k] == n || grid[k][x] == n || grid[y0 + k / 3][x0 + k % 3] == n) return false; return true; } /* The backtracking function is a recursive function! each call keeps track of it's own x and y coordinates. * The function operates on a referenced grid. It scans each xy couple and, if it's zero, it tryes to put a number, checked with the "possible" funciton. * If the number is ok, then the function call itself. * Now, if the recursion find a solution then returns true so all the parent calls know the solution has been found. Otherwise, the parent function try to * go ahead and try another possible number. */ bool backtrack(std::vector<std::vector<int>>& grid) { for(unsigned y = 0; y < 9; y++) for(unsigned x = 0; x < 9; x++) if(grid[y][x] == 0) { for(unsigned n = 1; n <= 9; n++) if(possible(x, y, n, grid)) { grid[y][x] = n; if(backtrack(grid)) return true; grid[y][x] = 0; } return false; } return true; } /* The main function parses the string (Why the string tho?) and then parses the solution. * In this case, it won't check if a puzzle is impossible to solbe */ std::string solve_sudoku(std::string puzzleString) { std::vector<std::vector<int>> puzzle(9, std::vector<int>(9, 0)); for(unsigned i = 0; i < 81; i++) puzzle[i / 9][i % 9] = puzzleString[i] - '0'; backtrack(puzzle); std::string out = ""; for(auto& i : puzzle) for(auto& j : i) out += std::to_string(j); return out; }
#import <vector>#import <unordered_set>- #include <vector>
- #include <string>
std::vector<std::vector<int>> puzzle;std::vector<int> get_row(int r){return puzzle[r];}std::vector<int> get_col(int c){std::vector<int> col;for (int r = 0; r < 9; r++){col.push_back(puzzle[r][c]);}return col;}std::vector<int> get_block(int r, int c){std::vector<int> block;r = r / 3 * 3; //this gives the top row for the block of the given r. by abusing that int floors numbers ex 5/3 = 1 *3 = 3;c = c / 3 * 3;for (int y = r; y < r + 3; y++){for (int x = c; x < c + 3; x++){block.push_back(puzzle[y][x]);}}return block;}std::unordered_set<int> get_options(int r, int c){if (puzzle[r][c] != 0)return {puzzle[r][c]};std::unordered_set<int> options = {1, 2, 3, 4, 5, 6, 7, 8, 9};std::vector<int> row = get_row(r);std::vector<int> col = get_col(c);std::vector<int> block = get_block(r, c);for (int i = 0; i < 9; i++){options.erase(row[i]);options.erase(col[i]);options.erase(block[i]);}return options;}bool backtrack(int r = 0, int c = 0){if (r == 9)return true; //returns true if you've finished the last rowint r2, c2;while (puzzle[r][c] != 0) //if the square is already set, try next ones until you find a 0{if (c == 8) //calculate the next piece{c = 0;r++;}elsec++;if (r > 8)return true; //if you find the end of the puzzle before a zero, return true.}if (c == 8) //calculate the next piece{c2 = 0;r2 = r + 1;}else{r2 = r;c2 = c + 1;}std::unordered_set<int> options = get_options(r, c);if (options.size() == 0)return false; //if there are no options something must have gone wrong before. return falsefor (int o : options){puzzle[r][c] = o; //set the square to one of the optionsif (backtrack(r2, c2) == true)return true;puzzle[r][c] = 0; //return the square to 0;}return false;}std::string toString(){std::string puzzle_string;for (int r = 0; r < 9; r++){for (int c = 0; c < 9; c++){puzzle_string += std::to_string(puzzle[r][c]);}}return puzzle_string;}void set_puzzle(std::string puzzleString)- /* Sudokus are good examples for backtracking
- * The algorithm try to place numbers in the empty spots untill it can or untill it solves the puzzle
- */
- /* The first function determine if, in the grid "grid" at position x and y an n is acceptable.
- * The k is used to iterate each subset: row, column and square, where x0 and y0 are the coordinates of the top left corner of the square
- */
- bool possible(unsigned x, unsigned y, int n, std::vector<std::vector<int>>& grid)
- {
- unsigned x0 = (x / 3) * 3, y0 = (y / 3) * 3;
- for(unsigned k = 0; k < 9; k++)
- if(grid[y][k] == n || grid[k][x] == n || grid[y0 + k / 3][x0 + k % 3] == n)
- return false;
- return true;
- }
- /* The backtracking function is a recursive function! each call keeps track of it's own x and y coordinates.
- * The function operates on a referenced grid. It scans each xy couple and, if it's zero, it tryes to put a number, checked with the "possible" funciton.
- * If the number is ok, then the function call itself.
- * Now, if the recursion find a solution then returns true so all the parent calls know the solution has been found. Otherwise, the parent function try to
- * go ahead and try another possible number.
- */
- bool backtrack(std::vector<std::vector<int>>& grid)
- {
- for(unsigned y = 0; y < 9; y++)
- for(unsigned x = 0; x < 9; x++)
- if(grid[y][x] == 0)
- {
- for(unsigned n = 1; n <= 9; n++)
- if(possible(x, y, n, grid))
- {
- grid[y][x] = n;
- if(backtrack(grid)) return true;
- grid[y][x] = 0;
- }
- return false;
- }
- return true;
- }
- /* The main function parses the string (Why the string tho?) and then parses the solution.
- * In this case, it won't check if a puzzle is impossible to solbe
- */
- std::string solve_sudoku(std::string puzzleString)
- {
std::vector<std::vector<int>> newPuzzle;for (int r = 0; r < 9; r++){std::vector<int> row;for (int c = 0; c < 9; c++){row.push_back((int)puzzleString[r * 9 + c] - '0'); //converts char to int and puts it in the row}newPuzzle.push_back(row);}puzzle = newPuzzle;}- std::vector<std::vector<int>> puzzle(9, std::vector<int>(9, 0));
std::string solve_sudoku(std::string puzzleString){set_puzzle(puzzleString);backtrack();return toString();}- for(unsigned i = 0; i < 81; i++)
- puzzle[i / 9][i % 9] = puzzleString[i] - '0';
- backtrack(puzzle);
- std::string out = "";
- for(auto& i : puzzle)
- for(auto& j : i)
- out += std::to_string(j);
- return out;
- }
// TODO: Replace examples and use TDD by writing your own tests Describe(Solve_Sudoku) { It(Medium_Sudokus) { Assert::That(solve_sudoku("300000000050703008000028070700000043000000000003904105400300800100040000968000200"), Equals("387419526259763418641528379716285943594631782823974165472396851135842697968157234")); Assert::That(solve_sudoku("130400000705300000600020000000000027000900400000000085860500003059103000002004060"), Equals("138479652725316894694825731541638927283957416976241385867592143459163278312784569")); Assert::That(solve_sudoku("090035406001000000007000089070940050100200000006800700008004030000600040605000000"), Equals("892735416561489372437162589273946158184257963956813724728594631319678245645321897")); Assert::That(solve_sudoku("001230000004000000005000461000502007500040002100603000826000300000000800000096100"), Equals("961234785784165293235789461648512937573948612192673548826451379419327856357896124")); } };
- // TODO: Replace examples and use TDD by writing your own tests
- Describe(Solve_Sudoku)
- {
- It(Medium_Sudokus)
- {
- Assert::That(solve_sudoku("300000000050703008000028070700000043000000000003904105400300800100040000968000200"), Equals("387419526259763418641528379716285943594631782823974165472396851135842697968157234"));
- Assert::That(solve_sudoku("130400000705300000600020000000000027000900400000000085860500003059103000002004060"), Equals("138479652725316894694825731541638927283957416976241385867592143459163278312784569"));
- Assert::That(solve_sudoku("090035406001000000007000089070940050100200000006800700008004030000600040605000000"), Equals("892735416561489372437162589273946158184257963956813724728594631319678245645321897"));
- Assert::That(solve_sudoku("001230000004000000005000461000502007500040002100603000826000300000000800000096100"), Equals("961234785784165293235789461648512937573948612192673548826451379419327856357896124"));
- }
- };