3

I'm working on a Sudoku solver program. The idea is that the user inputs the Sudoku puzzle and the program solves it for them.

The program works fine when entering any normal puzzle. However, there are some puzzles that are impossible to solve. Here is one example that I entered: https://i.stack.imgur.com/BnWc9.png

The input is perfectly legal, but top right square cannot be filled in since all numbers 1-9 have been used in that row and column. If I hit "Solve", my program freezes as it enters an infinite loop.

So my question here is, how can I prevent this from happening?

I tried implementing the "boolean flag" approach, but on second thought I realized that it's probably not feasible.

Here is my solver method:

public boolean solve(int i, int j) {
    for (int a = 0; a < 9; a++) {
        for (int b = 0; b < 9; b++) {
            if (sudokuArray[a][b] == 0) {
                for (int k = 1; k <= 9; k++) {
                    sudokuArray[a][b] = k;
                    if (checkNumber(a, b, k) && solve(a, b)) {
                        return true;
                    }else {
                        sudokuArray[a][b] = 0;
                    }
                }
                return false;
            }
        }
    }
    return true;
}

The checkNumber() method checks if number k can be legally inserted in row a, column b and returns true/false accordingly.

Ideas? Tips?

Thanks.

PS: Added checkNumber() as requested:

public boolean checkNumber(int i, int j, int num) {
    for (int a = 0; a < 9; a++) {
        if (a != i) {
            if (sudokuArray[a][j] == num) {
                return false;
            }
        }
        if (a != j) {
            if (sudokuArray[i][a] == num) {
                return false;
            }
        }
    }
    for (int a = (i / 3) * 3; a < (i / 3) * 3 + 3; a++) {
        for (int b = (j / 3) * 3; b < (j / 3) * 3 + 3; b++) {
            if ((a != i) && (b != j)) {
                if (sudokuArray[a][b] == num) {
                    return false;
                }
            }
        }
    }
    return true;
}
Chris
  • 57,622
  • 19
  • 111
  • 137
  • 2
    Is it really infinite? Not just taking too long while still making some progress? It's a pretty huge search tree after all. – harold Mar 09 '14 at 15:42
  • Yes, its infinite. Have a look at the screenshot - you'll see that it's impossible to enter a legal number at the top right square. – Chris Mar 09 '14 at 15:43
  • Please share code of method `checkNumber()`. Is this method taking more time? – Braj Mar 09 '14 at 15:44
  • Okay, although the problem is not there... – Chris Mar 09 '14 at 15:45
  • @Chris that usually just means that you'll exhaust all the options and prove infeasibility, instead of entering an infinite loop. – harold Mar 09 '14 at 15:46
  • @harold, not sure what you mean exactly. But what I am trying to do is have the program say "Unsolvable puzzle" when it is, instead of entering this loop. – Chris Mar 09 '14 at 15:48
  • @harold so I need to have the code detect this somehow... – Chris Mar 09 '14 at 15:49
  • 3
    Chris it is impossible to detect an infinite loop http://en.wikipedia.org/wiki/Halting_problem Try another approach. – NinjaStars Mar 09 '14 at 15:50
  • @Chris keep track of which values could *possibly* be assigned to every cell. That should *immediately* prove infeasibility in this case, and in general it would help. But still - exploring the entire search space, while taking exponential time, still takes a *finite* amount of time. – harold Mar 09 '14 at 15:50
  • @user2789433 doesn't apply here. – harold Mar 09 '14 at 15:57
  • @harold That's a good idea, and I have tried that but there are puzzles where illegal input is not so obvious. Here is another example: http://i.imgur.com/lvcbhCo.png – Chris Mar 09 '14 at 16:04
  • @Chris it should be able to prove infeasibility anyway, it would just take longer. But here's an other trick: look into the All-Different global constraint. It would notice here that there are 3 cells with only 2 possible values that must all be different, which is impossible. – harold Mar 09 '14 at 16:08
  • @harold, exactly like you said. 3 cells with only 2 possible unique values - impossible. So a method of checking each individual cell to determine if the puzzle is solvable or not would not help any. – Chris Mar 09 '14 at 16:16
  • The only thing I can think of would be to save some sort of trail for the program to look for in each iteration. In other words, check if it has already checked the same value for the same row/col before. The question is of course, how to do this? – Chris Mar 09 '14 at 16:18
  • @Chris yes it *would* help. It's not my intention that you just run that as a test before entering your search phase. You run it *all the time* to restrict how you search, so the search is done sooner. And look into the all-different constraint. Maybe you missed that part of my comment. It solves exactly the problem of "3 cells, 2 values". – harold Mar 09 '14 at 17:04

1 Answers1

2

This is just an idea (i would comment but this account is too new). Try making it so that if all numbers from 0-9 return false, then it returns an error of some sort. For example if it hasn't found an answer by 9, then move up to 10. If the program detects a 10, do some kind of System.out.println("Unsolvable") or something along those lines. Sorry if I'm confusing you by the way. I've been told I'm bad at explaining things.

Rakem
  • 36
  • 4