-1

I am trying to implement the Sudoku puzzle solver using Java but below code is failing on second case (it should return false). From the output being printed, it looks like the code exits even before the entire grid is solved. What am I missing?

Can someone help check this quickly and hint in case you see a problem.

Question: Write the function sudokuSolve that checks whether a given sudoku board (i.e. 9x9 sudoku puzzle) is solvable. If so, the function will returns true. Otherwise (i.e. there is no valid solution to the given sudoku board), returns false.

code:

public class Sudoku {
    static boolean sudokuSolve(char[][] board) {
        int row = -1, col = -1;
        List<Integer> candidates = null; // store smallest possible candidates
        for (int r = 0; r < 9; r++) {
            for (int c = 0; c < 9; c++) {
                if (board[r][c] == '.') {
                    List<Integer> newCandidates = getCandidates(board, r, c);
                    if (candidates == null || newCandidates.size() < candidates.size()) {
                        candidates = newCandidates;
                        row = r;
                        col = c;
                    }
                }
            }
        }
        if (candidates == null || candidates.isEmpty())
            return true;
        for (Integer val : candidates) {

            board[row][col] = (char) (val.intValue() + '0');
            if (sudokuSolve(board))
                return true;
            else
                board[row][col] = '.';
        }
        printGrid(board);
        return false;
    }

    /**
     * For each empty cell, consider 'newCandidates', the set of possible candidate
     * values that can be placed into that cell.
     * 
     */
    public static List<Integer> getCandidates(char[][] board, int x, int y) {
        // filled row numbers
        boolean[] mask = new boolean[10];
        for (int row = 0; row < 9; row++) {
            char ch = board[row][y];
            if (ch != '.')
                mask[ch - '0'] = true;
        }
        // filled col numbers
        for (int col = 0; col < 9; col++) {
            char ch = board[x][col];
            if (ch != '.')
                mask[ch - '0'] = true;
        }
        // filled subgrid numbers
        // starts at row - row%3, col - col%3
        int subBoardRow = x - (x % 3);
        int subBoardCol = y - (y % 3);
        for (int row = 0; row < 3; row++) {
            for (int col = 0; col < 3; col++) {
                char ch = board[subBoardRow + row][subBoardCol + col];
                if (ch != '.')
                    mask[ch - '0'] = true;
            }
        }

        List<Integer> candidates = new ArrayList<Integer>();
        for (int i = 1; i <= 9; i++) {
            if (!mask[i])
                candidates.add(i);
        }
        return candidates;
    }

      public static void main(String[] args) {
          char[][] board = new char[][] {
              {'.','.','.','7','.','.','3','.','1'},
              {'3','.','.','9','.','.','.','.','.'},
              {'.','4','.','3','1','.','2','.','.'},
              {'.','6','.','4','.','.','5','.','.'},
              {'.','.','.','.','.','.','.','.','.'},
              {'.','.','1','.','.','8','.','4','.'},
              {'.','.','6','.','2','1','.','5','.'},
              {'.','.','.','.','.','9','.','.','8'},
              {'8','.','5','.','.','4','.','.','.'}};

          System.out.println(sudokuSolve(board));
          printGrid(board);

          System.out.println("***************************************");

          char[][] board2 = new char[][] {
              {'.','8','9','.','4','.','6','.','5'},
              {'.','7','.','.','.','8','.','4','1'},
              {'5','6','.','9','.','.','.','.','8'},
              {'.','.','.','7','.','5','.','9','.'},
              {'.','9','.','4','.','1','.','5','.'},
              {'.','3','.','9','.','6','.','1','.'},
              {'8','.','.','.','.','.','.','.','7'},
              {'.','2','.','8','.','.','.','6','.'},
              {'.','.','6','.','7','.','.','8','.'}};
          System.out.println(sudokuSolve(board2));
          printGrid(board2);
      }

      public static void printGrid(char[][] grid) {
            for (int r = 0; r < grid.length; r++) {
                for (int c = 0; c < grid[0].length; c++) {
                    System.out.print(grid[r][c] + " ");
                }
                System.out.print("\n");
            }
        }

}

Output:

true
6 5 8 7 4 2 3 9 1 
3 1 2 9 8 6 4 7 5 
7 4 9 3 1 5 2 8 6 
2 6 3 4 9 7 5 . . 
. . . 1 . . . . . 
. . 1 2 . 8 . 4 . 
. . 6 8 2 1 . 5 . 
. . . 5 . 9 . . 8 
8 . 5 6 . 4 . . . 

***************************************

true 1 8 9 2 4 3 6 7 5 2 7 3 5 6 8 9 4 1 5 6 4 9 1 7 2 3 8 4 1 2 7 3 5 8 9 6 6 9 8 4 2 1 7 5 3 7 3 5 9 8 6 4 1 2 8 4 1 . 5 9 . 2 7 . 2 7 8 . . . 6 . . . 6 . 7 . . 8 .

Sant
  • 31
  • 4
  • Welcome to Stack Overflow! Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a [mcve]. Use the [edit] link to improve your *question* - do not add more information via comments. Thanks! – GhostCat Feb 25 '18 at 18:17
  • Does not solve your problem, but you are processing the same grid two times. Change the second call to **board2** like this `System.out.println(sudokuSolve(board2));` and `printGrid(board2);` – Business Tomcat Feb 25 '18 at 18:43
  • also see https://stackoverflow.com/questions/4039594/brute-force-sudoku-solver-algorithm-in-java-problem and any other sudoku solving related answers on SO in case they help with (re)designing the algorithm (sometimes you just have to scrap your original design instead of trying to fix it) – George Birbilis Mar 04 '18 at 22:02

1 Answers1

0

You algorithm is a little bit strange.

You have recursion, which seems useless. For every tile on the board you calculate candidates, but overwrite it with the candidates for another tile. Perhaps I'm wrong, but the result is sometimes true, where it shouldn't.
sudokuSolve cannot work correctly in this way.


UPDATE

The second initial board is wrong. There are two 9 in the 4. column (from beginning). Your algorithm cannot handle this case.

Either the question is wrong, or the question is to (also) implement a checker for the initial board, or you made a typo ;)

Business Tomcat
  • 1,021
  • 9
  • 12
  • The Recursion is for backtracking. Choose one of the candidates. With this as candidate try to solve the board. If it does not help solve the board, then backtrack and choose the next candidate. The test case (having 2 9s) was obtained from the website where I found the question as well. Perhaps the solution should handle that. – Sant Feb 25 '18 at 22:23