Issues with recursive backtracking - java

I am trying to implement a backtracking algorithm in Java, to solve a sudoku problem.
I'm 95% sure the problem is in solve method, but I included the two accesory methods in case.
Some of the strange-ish things I'm doing are just due to requirements/convenience, like the hard-coded initial values for the puzzle. I'm sure the issue lies near the bottom of my solve method, but I cannot figure it out...
My current problem is this: after working on the first row, and finding a potentially valid permutation of values, my program simply gives up. If I uncomment the line that prints "ROW IS DONE," it'll print that after ONE row, and no more output is given. Why is it giving up after the first row? Is there anything else about my implementation I should be worried about
EDIT: I made a lot of changes. It is getting very close. If I print when EXHAUST is true, I get a puzzle that has every row solved except the last one. It looks like it is undoing everything after it's solved/nearly solved it. I get the feeling that it might already reach point where the puzzle is fully solved, but I'm not passing back TRUE at the right time... What am I doing wrong now?
import java.util.ArrayList;
class Model
{
ArrayList<View> views = new ArrayList<View>();
int[][] grid =
{
{5,3,0,0,7,0,0,0,0},
{6,0,0,1,9,5,0,0,0},
{0,9,8,0,0,0,0,6,0},
{8,0,0,0,6,0,0,0,3},
{4,0,0,8,0,3,0,0,1},
{7,0,0,0,2,0,0,0,6},
{0,6,0,0,0,0,2,8,0},
{0,0,0,4,1,9,0,0,5},
{0,0,0,0,8,0,0,7,9}
};
/**
* Method solve
*
* Uses a backtracking algorithm to solve the puzzle.
*/
public boolean solve(int row, int col) //mutator
{
if(exhaust(row,col)) {printGrid(); return true;}
int rownext = row;
int colnext = col+1;
if(colnext>8)
{
colnext = 0;
rownext++;
}
if(grid[row][col] != 0) solve(rownext,colnext);
else //is == 0
{
for(int num = 1; num <= 9; num++)
{
if(!conflict(row,col,num)) //try a non-conflicting number
{
grid[row][col] = num;
if(solve(rownext,colnext)) return true;
grid[row][col] = 0;
}
}
}
return false;
}
/**
* Method exhaust
*
* Iteratively searches the rest of the puzzle for empty space
* using the parameters as the starting point.
*
* #return true if no 0's are found
* #return false if a 0 is found
*/
public boolean exhaust(int row, int col)
{
for(int i = row; i <= 8; i++)
{
for(int j = col; j <= 8; j++)
{
if(grid[i][j] == 0) return false;
}
}
System.out.printf("Exhausted.\n");
return true;
}
/**
* Method conflict
*
* Checks if the choice in question is valid by looking to see
* if the choice has already been made in the same row or col,
* or block.
*
* #return true if there IS a conflict
* #return false if there is NOT a conflict
*/
public boolean conflict(int row, int col, int num)
{
for(int j = 0; j <= 8; j++)
{
if(grid[row][j] == num) {
return true;
}
}
for(int i = 0; i <= 8; i++)
{
if(grid[i][col] == num) {
return true;
}
}
int rowstart = 0;
if(row>=3) rowstart = 3;
if(row>=6) rowstart = 6;
int colstart = 0;
if(col>=3) colstart = 3;
if(col>=6) colstart = 6;
for(int r = rowstart; r <= (rowstart + 2); r++)
{
for(int c = colstart; c <= (colstart + 2); c++)
{
if(grid[r][c] == num) {
return true;
}
}
}
return false;
}
}

Imagine you're moving forward smoothly, row by row, and haven't backtracked. Your next position is solve(1,1);. Pay attention to rownext as you trace through your code. You should see the problem quickly. If you aren't backtracking, rownext should hold its value of at least 1.

Related

Adding all solutions of N Queen Problem to an arrayList

The n-queens puzzle is the problem of placing n queens on a (n×n) chessboard such that no two queens can attack each other.
I used backtracking to solve the problem. But I ran in a strange issue.
Below is the code I wrote:
import java.util.ArrayList;
public class NQueenProblem {
static ArrayList<ArrayList<Integer>> ans = new ArrayList<ArrayList<Integer>>();
static ArrayList<ArrayList<Integer>> nQueen(int n) {
ArrayList<Integer> positions = new ArrayList<Integer>();
//boolean[][] placed = new boolean[n][n];
solveNQueenRec(n, 0, new boolean[n][n], positions);
//for dubugging purpose. This prints empty arrays. not able to understand why?
for (ArrayList<Integer> list : ans)
System.out.println(list);
return ans;
}
static void solveNQueenRec(int n, int col, boolean[][] placed, ArrayList<Integer> positions) {
if (col == n) {
//for debugging process
System.out.println("Adding " + positions);
ans.add(positions);
System.out.println("Added " + positions);
}
for (int row = 0; row < n && col < n; row++) {
if (isSafe(row, col, placed, n)) {
placed[row][col] = true;
positions.add(row + 1);
solveNQueenRec(n, col + 1, placed, positions);
placed[row][col] = false;
positions.remove(positions.size() - 1);
}
}
// return null;
}
private static boolean isSafe(int row, int col, boolean[][] placed, int n) {
boolean safe = true;
// checking if exists in same row
for (int i = 0; i < col; i++) {
if (placed[row][i])
safe = false;
}
// checking for upper diagonal
for (int i = row, j = col; i >= 0 && j >= 0; i--, j--) {
if (placed[i][j])
safe = false;
}
// checking for lower diagonal
for (int i = row, j = col; i < n && j >= 0; i++, j--) {
if (placed[i][j])
safe = false;
}
return safe;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
nQueen(4);
}
}
What I am not able to understand is why my ans is empty when I could see in logs list being added to my ans. Am I doing some silly mistake. Please help me with the issue. If possible please help me with links to understand the issue and how could I avoid these issues in future.
I think you believe that when the JVM executes
ans.add(positions);
that it is taking a copy of the current state of positions and adding it to the list. It isn't, it is doing exactly what the code says: adding a reference to an ArrayList to ans.
All the items in ans are references to the same ArrayList, and that array list is empty when you print out ans.
ans.add(positions);
is your "problem". You are just adding to ans a reference to the list positions. Thus ans is full of references to the same positions list. As you modify positions several time after insertion, until emptied it, at the end ans is full of n references (n being the number of solutions found) the same positions list that is empty at the end.
What you need is to insert a copy of the current positions list at the time a solution is found:
ans.add(new ArrayList<Integer>(positions));
copy is obtained by constructing a new list with the exact content of the original one.
Add this checking make sure it is greater than zero, then print out the answer. Moreover, add the print queen function, your will see the answer clearly. If this solve your problem, please make as answer.
for (ArrayList<Integer> list : ans) {
if (list.size() > 0)
System.out.println(list);
}
static void solveNQueenRec(int n, int col, boolean[][] placed, ArrayList<Integer> positions) {
if (col == n)
printQueens(positions);
for (int row = 0; row < n && col < n; row++) {
if (isSafe(row, col, placed, n)) {
placed[row][col] = true;
positions.add(row + 1);
solveNQueenRec(n, col + 1, placed, positions);
placed[row][col] = false;
positions.remove(positions.size() - 1);
}
}
// return null;
}
public static void printQueens(ArrayList<Integer> q) {
int n = q.size();
for (int i = 0; i < n; i++) {
for (int j = 1; j <= n; j++) {
if (q.get(i) == j)
System.out.print("Q ");
else
System.out.print("* ");
}
System.out.println();
}
System.out.println();
}
solution to 4-queens sample:
* Q * *
* * * Q
Q * * *
* * Q *
* * Q *
Q * * *
* * * Q
* Q * *

How to return new array of type different from the original array in java

Hello Everyone I'm having toughest time in my career figuring this out.
Here I have commented on the code so the problem could be easily spotted.
I wish someone can rescue me, thanks to that rescuer in advance.
Code below
public class Marathon {
/** The whole point here is: how can I return a new arr which is of type Marathon */
static int [][] raceValues;
public Marathon(int aValue){
this.raceValues = [aValue][aValue]; // (Problem no.1) Erroneously accessing a static variable nonstatically
for (int i = 1; i <= aValue; i++) {
for (int j = 1; j <= aValue; j++) {
this.raceValues[i-1][j-1] = (aValue * (i - (aValue - (aValue - 1)))) + j;
}
}
}
Marathon alterAnyValue(int a){
/*
* If I could write something like next line, then my problem would be solved. But eclipse will grizzle
* "Cannot convert from int to Marathon"
* Marathon arr[][] = raceValues;
*/
int arr[][] = raceValues;
for (int i = 0; i < aValue; i++) {
for (int j = 0; j < aValue; j++) {
int c = arr[i][j] % 3; // Divisible by three
int d = arr[i][j] % 5; // Divisible by five
if(c == 0){
arr[i][j] = 3;
}
if(d == 0){
arr[i][j] == 5;
}
}
}
/*
* Here I don't know how to return new arr
* I must return a new arr and it must be of type Maraton
* At this point the whole world just ended. I don't know what to do
*/
//return new Marathon()
//return arr
}
}
For your first Problem: The static accessing: You can do Marathon.raceValues = new int[aValue][aValue]; This would solve your Static Access "error"
For your second problem I don't see a possibility in Java as you can't make new "Integer" classes as they are final. You COULD make your own Integer but I couldn't imagin WHY. So the other possibility could be that you return an Integer Array.
This would be what I would try to do. If you want something different please specify the question a bit better :)

Sudoku generator algorithm optimization welcome

I created a recursive DFS algorithm to generate/solve sudoku boards in Java, but it's taking forever to terminate, and an explanation/optimization would be welcome. I can't imagine that generating a sudoku board would be so time-consuming, especially with all the apps around (although they might have a database.)
Basically, I traverse all cells, seeing whether any of [1-9] would satisfy the sudoku constraints, and backtrack on dead-end branches. To conserve memory and avoid copying the 2D array that serves as the board with each invocation of the recursive method (and there are potentially 81*9! leaves in that tree, if I'm not mistaken...), I created a 2D matrix of integer stacks, in which an element is pushed every time a branch is explored, and popped if it's a dead-end.
Below is the implementation. Any advice on speedup would be welcome. I'm doing this as a personal excercise, and I'm wondering if something asymptotically better exists.
Hope it's not a terrible read below.. Thank you!
1) The algorithm implementation: (note that values are in a "jumbled" array of [1-9] to create unique boards.)
/**
* Provides one solution to a board with an initial configuration, or <code>null</code> if there is none.
* The search is randomized, s.t. the algorithm can serve to populate an empty board.
*
* #param initial The initial board given to solve.
* #return The fully solved board, or null if no solution found.
*/
public static int[][] solveBoard (int[][] initial){
return solveBoard(new StackedBoard(initial), 0, 0);
}
private static int[][] solveBoard (StackedBoard board, int xPos, int yPos){
// base case - success
int remaining = 81;
for (int x = 0; x < 9; x++){
for (int y = 0; y < 9; y++){
if (board.peekAt(x, y) != Board.EMPTY){
remaining--;
}
}
}
if (remaining == 0){
return board.flatView();// the only creation of an array.
}
// recursive case
for (int x = 0; x < 9; x++){
for (int y = 0; y < 9; y++){
if (board.peekAt(x, y) == Board.EMPTY){
for (int val : getJumbledRandomVals()){
if (isMoveLegal(board, x, y, val)){
board.pushAt(x, y, val);
int[][] leafBoard = solveBoard(board, x, y);
if (leafBoard != null) {
return leafBoard;
}
}
}
}
}
}
// base case - dead branch
board.popAt(xPos, yPos);
return null;
}
2) The StackedBoard implementation:
/**
* Represents square boards with stacked int elements.
*/
class StackedBoard {
ArrayList<ArrayList<Stack<Integer>>> xaxis = new ArrayList<ArrayList<Stack<Integer>>>();
/**
*
* #param init A square array - both dimensions of equal length, or <code>null</code> if no initialization.
*/
public StackedBoard (int[][] init) {
for (int i = 0; i < 9; i++){
ArrayList<Stack<Integer>> yaxis = new ArrayList<Stack<Integer>>();
xaxis.add(yaxis);
for (int j = 0; j < 9; j++){
Stack<Integer> stack = new Stack<Integer>();
yaxis.add(stack);
}
}
if (init != null){
for (int x = 0; x < init.length; x++){
for (int y = 0; y < init.length; y++){
getStackAt(x, y).push(init[x][y]);
}
}
}
}
public Stack<Integer> getStackAt (int x, int y){
return xaxis.get(x).get(y);
}
public int peekAt (int x, int y){
return getStackAt(x, y).peek();
}
public void pushAt (int x, int y, int value){
getStackAt(x, y).push(value);
}
public Integer popAt (int x, int y){
try {
return getStackAt(x, y).pop();
} catch (EmptyStackException e){
// shhhhh!
return Board.EMPTY;
}
}
/**
* Flat view of the stacked-board; peek of the top elements.
*/
public int[][] flatView (){
int[][] view = new int[xaxis.size()][xaxis.size()];
for (int x = 0; x < xaxis.size(); x++){
for (int y = 0; y < xaxis.size(); y++){
view[x][y] = getStackAt(x, y).peek();
}
}
return view;
}
}
3) The constraints function implementation:
/**
* Is the move legal on the suggested board?
*
* #param board The board.
* #param x The X coordinate, starts with 0.
* #param y The Y coordinate, starts with 0.
* #param value The value.
* #return <code>true</code> iff the move is legal.
*/
private static boolean isMoveLegal (StackedBoard board, int x, int y, int value){
// by value
if (1 > value || value > 9){
return false;
}
// by column
for (int i = 0; i < 9; i++){
if (board.peekAt(i, y) == value){
return false;
}
}
// by row
for (int i = 0; i < 9; i++){
if (board.peekAt(x, i) == value){
return false;
}
}
// by lil square
int lowerX = x < 3 ? 0 : (x < 6 ? 3 : 6);
int upperX = lowerX + 2;
int lowerY = y < 3 ? 0 : (y < 6 ? 3 : 6);
int upperY = lowerY + 2;
for (int i = lowerX; i <= upperX; i++){
for (int j = lowerY; j <= upperY; j++){
if (board.peekAt(i, j) == value){
return false;
}
}
}
return true;
}
If you are willing to make a complete left turn, there are much better algorithms for generating / solving Sudokus. Don Knuth's dancing links algorithm is known to be extremely good at rapidly enumerating all Sudoku solutions (once they're phrased as instances of the exact cover problem) and is commonly used as the main algorithm in Sudoku solvers, and it's worth looking into. It requires a lot of pointer/reference gymnastics, but it relatively short to code up.
If you want to stick with your existing approach, one useful optimization would be to always choose the most constrained cell as the next value to fill in. This will likely cause a cascade of "forced moves" that will help you reduce the size of your search space, though it's only a heuristic.
Hope this helps!

Sudoku Checker 2d array Java

So im having a bit of problem with my code.. It's suppose to cross check rows and columns for same integers.
this is what i have so far.. but when i run it, it only seems to check the first integer only. (for example the first line of the sudoku board reads. 1 2 2 2 2 2 2 2 2 2) it wont detect the obvious multiple 2's but if i change the input to 1 1 2 2 2 2 2 2 2 the error will come up of multiple 1's in this case. the multiple any suggestions to tweak my loops to make it go through the columns?
public static void validate(final int[][] sudokuBoard) {
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for (int i = 0; i < width; i++) {
int j = i;
int reference = sudokuBoard[i][j];
while (true) {
if ((j >= width) || (j >= depth)) {
break;
}
else if (i == j){
// do nothing
}
else if (j < width) {
int current = sudokuBoard[i][j];
if (current == reference) {
System.out.print("Invalid entry found (width)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
} else if (j < depth) {
// note reversed indexes
int current = sudokuBoard[j][i];
if (current == reference) {
System.out.print("Invalid entry found (depth)" + "\n");
System.out.print(current + "\n");
// invalid entry found do something
}
}
j++;
}
Your code is more complex than it should be. Why put everything in one single function when you could split in several different functions?
public static void Validate(final int[][] sudokuBoard)
{
int width = sudokuBoard[0].length;
int depth = sudokuBoard.length;
for(int i = 0; i < width; i++)
if(!IsValidRow(sudokuBoard, i, width))
{
//Do something - The row has repetitions
}
for(int j = 0; j < height; j++)
if(!IsValidColumn(sudokuBoard, j, width))
{
//Do something - The columns has repetitions
}
}
static bool IsValidRow(int[][] sudokuBoard, int referenceRow, int width)
{
//Compare each value in the row to each other
for(int i = 0; i < width; i++)
{
for(int j = i + 1; j < width; j++)
{
if(sudokuBoard[referenceRow][i] == sudokuBoard[referenceRow][j])
return false
}
}
return true;
}
static bool IsValidColumn(int[][] sudokuBoard, int referenceColumn, int height)
{
//Compare each value in the column to each other
for(int i = 0; i < height; i++)
{
for(int j = i + 1; j < height; j++)
{
if(sudokuBoard[i][referenceColumn] == sudokuBoard[j][referenceColumn])
return false
}
}
return true;
}
That way, your code is much more easily maintainable/readable. This code above hasn't been tested, but it should be about right.
I suggest debugging this code step by step to really understand what's going on, if that's not clear for you.
Given the constraints of sudoku (a row of n cells must contain the numbers 1-n only) you don't need an order n^2 search (per row or column), you can do it order n by keeping a bit array indicating which numbers you've seen. Here's the pseudo-code for checking rows, do the same for columns:
for i in 0 to depth-1 // rows
boolean seen[] = new seen[width];
for j in 0 to width-1 // columns
if seen[board[i][j]-1] == true
duplicate number
else
seen[board[i][j]-1] = true
I would break the functionality into smaller boolean checks. This way, you can validate row by row, column by column, and square by square. For instance
private boolean isValidRow(int[] row) {
// Code here to check for valid row (ie, check for duplicate numbers)
}
private boolean isValidColumn(int[] column) {
// Code here to check for valid column
}
private boolean isValidSquare(int[][] square) {
// Code here to check for valid square
}
Note that rows and columns only need to be passed a 1 dimensional array. Squares are a 2 dimensional array as you need to check a 3x3 area. You can also treat these methods as static as their functionality is independent of the Sudoku board instance.
Edit: A suggestion on row/column/square validation is to use a HashSet. Sets can only have 1 element of a certain value, so you can add elements and look for a failure. For example:
HashSet<Integer> hs = new HashSet<Integer>();
for(int i = 0; i < 9; i++) {
if(!hs.add(integerArray[i])) // HashSet.add returns 'false' if the add fails
// (ie, if the element exists)
return false;
}
return true;

Getting StackOverflow Error

I'm trying to write a program that takes a Sudoku puzzle and solves it.
However, I'm running into a StackOverflow error at this line:
Move nMove = new Move(current.nextMove(current, sboard).i, current.nextMove(current, sboard).j);
It has a method isLegal that checks for whether the move is valid. If move is valid and the next move is also valid, it adds it to a stack. If it is valid but the next move is not, it should keep searching for a valid number.
Not sure what's causing it.
import java.util.Stack;
public class Board {
Stack<Move> stack = new Stack<Move>();
int boardSize = 9;
public int[][] sboard = {{2,0,0,3,9,5,7,1,6},
{5,7,1,0,2,8,3,0,9},
{9,3,0,7,0,1,0,8,2},
{6,8,2,0,3,9,1,0,4},
{3,5,9,1,7,4,6,2,8},
{7,1,0,8,6,0,9,0,3},
{8,6,0,4,1,7,2,9,5},
{1,9,5,2,8,6,4,3,7},
{4,2,0,0,0,0,8,6,1}};
public Board() {
//for every cell in board:
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
//get the value of each cell
int temp = getCell(i,j);
//if cell is empty:
if (temp == 0) {
//print out location of cell
System.out.print ("("+i+", "+j+") ");
//guess values for that cell
solve(i, j);
}
}
}
}
//places a value into specified cell
public void setCell(int value, int row, int col) {
sboard[row][col] = value;
}
//returns value contained at specified cell
public int getCell(int row, int col) {
return sboard[row][col];
}
//if value is legal, continue
public boolean isLegal(int value, int row, int col) {
int r = (row / boardSize) * boardSize;
int c = (col / boardSize) * boardSize;
for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
if (value == getCell(i, col) || value == getCell(row, j)) {
return false;
}
}
}
return true;
}
//guesses values for empty cells
public boolean solve(int i, int j) {
//set location as current
Move current = new Move(i, j);
Move nMove = new Move(current.nextMove(current, sboard).i, current.nextMove(current, sboard).j);
//guesses values 1 through 9 that are legal
for (int k = 1; k <= 9; k++) {
//if a legal value is found and the next move is possible:
if(isLegal(k, i, j) && solve(nMove.i, nMove.j)) {
//add current to stack
stack.push(current);
//enter the value k into the cell
setCell(k, i, j);
//print new value
System.out.print(sboard[i][j]+"\n");
//return as true
return true;
}
else if (stack.empty()){
}
//if next move is not possible
else if(!solve(nMove.i, nMove.j)){
//remove last "solved" location from stack
stack.pop();
//solve last location again
solve(stack.peek());
}
}
return false;
}
public void solve(Move m) {
solve(m.i, m.j);
}
public static void main(String[] args) {
Board b = new Board();
}
};
class Move {
int i, j;
public Move(int i, int j) {
this.i = i;
this.j = j;
}
public int i() { return i;}
public int j() { return j;}
public Move nextMove(Move current, int[][] sboard){
for (int i = current.i; i < 9; i++) {
for (int j = current.j; j < 9; j++) {
//get the value of each cell
int temp = sboard[i][j];
if (temp == 0) {
return new Move(i, j);
}
}
}
return current;
}
};
For one, it seems redundant to me to have this function in the form current.nextMove(current, board). You can either make this function static, or remove the Move current parameter.
But taking a look at your solve(i, j) function, you essentially have this:
Assume sboard[i][j] = 0 (which it clearly does, in some cases, from your input).
Assume you call solve(i, j).
current will be new Move(i, j).
nMove will then also be new Move(i, j) (since in Move#nextMove,
you essentially say if sboard[i][j] == 0, which it does from step
1).
You will end up calling solve(nMove.i, nMove.j)
Since nMove.i == i and nMove.j == j, you are essentially calling solve(i, j) over again.
Since you're calling the same function with the same parameter, and you're not reaching any base case, you will end up with a stack overflow.
As you have defined an (explicit) stack, you should not call solve() recursively.
Just loop, pop a board, generate all valid next moves, see if one of them is a solution, and if not, push them on the stack.
(I couldn't find where you verify that the board is complete, but I am probably tired.)
Btw, the stack should probably be a Dequeue. I believe a stack is synchronized which slows down the code.

Categories