Search code examples
c++backtrackingsudoku

solve sudoku with backtracking - C++


So I am trying to solve sudoku with backtracking

And with this example : example_pic

I hard-coded some of the indexes in the two dimensional array with numbers on places given from webSudoku (picture above). It definitely has solutions but, my code prints "solution doesn't exist

Here is my code :

#include <stdio.h>
int a[10][10]= {{2,0,0,0,9,0,0,3,1},
            {0,0,3,5,0,6,0,2,0},
            {0,0,8,1,3,0,5,4,0},
            {7,2,0,0,0,9,0,0,4},
            {4,0,0,0,0,0,0,0,8},
            {3,0,0,6,0,0,0,9,5},
            {0,7,6,0,4,5,1,0,0},
            {0,1,0,9,0,7,4,0,0},
            {5,3,0,0,8,0,0,0,6}};

bool is_valid(int x, int y, int value){
    if(a[x][y] != 0) return false;

    //check_row and column
    for(int tmp=1; tmp<=9; tmp++){
        if(value == a[x][tmp]) return false;
    }
    for(int tmp=1; tmp<=9; tmp++){
        if(value == a[tmp][y]) return false;
    }
    //check in 3*3 block
    int x_s = (x-1)/3*3 + 1;
    int y_s = 3*((y+2)/3-1)+1;
    for(int ch_x = x_s; ch_x<x_s+3; ch_x++){
        for(int ch_y=y_s; ch_y<y_s+3; ch_y++){
            if(ch_x!=x && ch_y!=y){
                if(value==a[ch_x][ch_y]) return false;
            }
        }
    }
    return true;
}

bool find(int &x, int &y){
    // check if valid cells are exists
    for(x=1; x<=9; x++){
        for(y=1; y<=9; y++){
            if(a[x][y] == 0)
                return true;
        }
    } 
    return false;
}

bool solve(){
    int x,y;
    //base::case
    if(!find(x,y)) return true;
    for(int cand = 1; cand <=9; cand++){
        if(is_valid(x,y,cand)){
            a[x][y] = cand;
            if(solve()) return true;
            a[x][y] = 0;
        }
    }
    return false;
}

void print(){
    //print the sudoku plate
    for(int i=1;i<=9; i++){
        for(int j=1; j<=9; j++){
            printf("%2d",a[i][j]);
        }
        printf("\n");
    }
    return ;
}

int main(){
    //Fill in some empty grid with the known values
    /*for(int i=1; i<=9; i++){
        for(int j=1; j<=9; j++){
        scanf("%1d",&a[i][j]);
        }
    }*/

    if (solve()) print();
    else printf("No solution exists\n");
    return 0;
}

I guess my 'solve function' or 'is_valid' function is not working right.

In 'is_valid' function, if there is problem it would be

bool find(int &x, int &y){
// check if valid cells are exists
    for(x=1; x<=9; x++){
        for(y=1; y<=9; y++){
            if(a[x][y] == 0)
                return true;
        }
    }
    return false;
} 

But, I also hard-coded this part and in my scope it doesn't seem like have problem.

In 'solve function'

bool solve(){
    int x,y;
    //base::case
    if(!find(x,y)) return true;
    for(int cand = 1; cand <=9; cand++){
        if(is_valid(x,y,cand)){
            a[x][y] = cand;
            if(solve()) return true;
            a[x][y] = 0;
        }
    }
    return false;
}

I cant figure out where i got it wrong. If you find any other mistakes in the solve() function - let me know. Because I am not sure I understand the "backtracking" thing completely...

p.s. : reference I read (https://see.stanford.edu/materials/icspacs106b/H19-RecBacktrackExamples.pdf)


Solution

  • There are a few mistakes

    • You are mixing up (x, y) and (row, col) addressing (row is y, not x). Choose a representation and stick to it
    • There is a typo in is_valid because the check on (c, x) should be on (c, y) (or (y, c) depending on convention but surely using y and not x again)
    • The 3x3 sub-block computation is wrong... a correct formula could be for example int start_x = (x-1)/3*3 + 1, start_y = (y-1)/3*3 + 1;

    Fixing all that the code works on the given example