-1

solveSudoku function is called from main() function.

I have written the following function for solving sudoku :

bool isFull(vector<vector<char>>& board){
        for(int i = 0 ; i < board.size(); i++){
            for(int j = 0 ; j < board[0].size(); j++){
                if(board[i][j] == '.') return false;
            }
        }  
        return true;
    }
    
    vector<int> poss(vector<vector<char>>& board, int x, int y){
        vector<int> ans;
        set<int> s;
        
        //check across columns
        for(int j = 0 ; j < board[0].size(); j++){
            if(board[x][j]!='.')  s.insert(board[x][j] -'0');
        }
        
        //check acroos rows
        for(int i = 0 ; i < board.size(); i++){
            if(board[i][y]!='.')   s.insert(board[i][y] - '0');
        }
        
        //check in square
        int r, c;
        if(x>=0 && x<=2) r = 0;
        if(x>=3 && x<=5) r = 3;
        if(x>=6 && x<=8) r = 6;
        
        if(y>=0 && y<=2) c = 0;
        if(y>=3 && y<=5) c = 3;
        if(y>=6 && y<=8) c = 6;
        
        for(int i = r; i <= r + 2; i++){
            for(int j = c; j <= c + 2; j++){
                if(board[i][j]!='.') s.insert(board[i][j]-'0');
            }
        }
        
        for(int n = 1; n <=9 ; n++){
            if(s.find(n) == s.end()){
                ans.push_back(n);
            }
        }
        
        
        return ans;
    }
    
    vector<int> Fempty(vector<vector<char>>& board){
        vector<int> ans;
        
        for(int i = 0; i < board.size(); i++){
            for(int j = 0; j < board[0].size(); j++){
                if(board[i][j] == '.'){
                    ans.push_back(i);
                    ans.push_back(j);
                    return ans;
                }
            }
        }
        
        return ans;
    }
    
    void solveSudoku(vector<vector<char>>& board) {
        
        if(isFull(board))  return;
        
        //not full
        //Fempty returns first empty cell coordinate
        vector<int> empty = Fempty(board);
        int xe = empty[0], ye = empty[1];
        
        //poss returns the vector of possible values
        vector<int> pos = poss(board, xe, ye);
        
        if(!pos.empty()){
        for(int i = 0; i < pos.size(); i++){
            board[xe][ye] = pos[i] + '0';
            solveSudoku(board);
        }}
        board[xe][ye] = '.';
        
        return;
        
        
    }

Input sudoku is given as argument when solveSudoku is called in the main() function. It consists of characters from 1 to 9 and . which represents empty character. solveSudoku function's job is to fill all the elements in sudoku correctly(change values in board in place).

When I run this program my output shows no change.

If I comment out board[xe][ye] = '.', my output shows some changes but it remains same after a cell runs out of possible values.

Edit : It is known that board has a solution.

What I am doing wrong?

Dark Night
  • 33
  • 1
  • 6
  • `When I run this program my output shows no change.` where do you output ? if in *main* of course you see no change because by definition at the end *solveSudoku* returns *board* unchanged. You must output the board when `if(isFull(board))`before to `return` rather than to just `return;`. Of course you need `board[xe][ye] = '.';` – bruno Aug 07 '20 at 19:38
  • Print the board when `isFull` returns true. – john Aug 07 '20 at 19:42
  • Recommendation: Add `main`. Bonus points alter `main` it you feeds in a canned set of inputs that exposes the behaviour you want dealt with. – user4581301 Aug 07 '20 at 19:44
  • @bruno I have printed `board` after calling `solveSudoku`. Why will `board` remain unchanged at end of `SolveSudoku`? It is passed by reference. `isFull(board)` returns `true` only when I have no empty cells. If all cells all filled, I return `solveSudoku` and output its values. – Dark Night Aug 07 '20 at 19:45
  • 1
    However I just see `board[xe][ye] = '.';` must be moved inside `if(!pos.empty()){`after the `for` rather than after the `if` – bruno Aug 07 '20 at 19:54
  • 1
    Your `solveSudoku` function needs to stop when it finds a solution. Your base case is when the board is already full (solved). Then keep setting the first empty cell to a different value and calling `solveSudoku` until it returns `true` (solved) or you're out of values (not possible in current configuration). – Kevin Aug 07 '20 at 20:11
  • @Kevin it is possible if the input is a board with no solutions. – n. m. could be an AI Aug 07 '20 at 20:47
  • @n.'pronouns'm. In which case `solveSudoku` will try all possible combinations but still return `false`, and leave the board in the original state. – Kevin Aug 07 '20 at 20:53
  • @Kevin It is known that board has a solution – Dark Night Aug 07 '20 at 20:57

1 Answers1

0

Imagine board contains a full sodoku, with only one cell blank ('.') SolveSudoku will identify the cell, pos would have a single value, the for loop will do only one step (and do some weird thing to board !) Then in the loop SolveSudoku is called recursively, as the board is full now, this recursive call will return at first if statement. Program will continue in the previous call juste after the for loop. And the last instruction puts a '.' char again in the empty cell... This is the instruction just after the for loop ...

Ben
  • 149
  • 1
  • 6
  • Thank you. I added `break` and `board[xe][ye] = '.'` in the `for` loop and it works! There was no problem in calling by reference. – Dark Night Aug 07 '20 at 21:10
  • I got it. Your code is quite a nightmare. In the for loop, after the recursive call add if(isfull(board)) break; sorry for formatting, writing on phone... – Ben Aug 07 '20 at 21:38
  • Just seen you already solved it. Nice. – Ben Aug 07 '20 at 21:42