I am building a Sudoku solver that use the Try and Fail technique to solve any problem. My algorithm is:
1)Update (method that remove any possible value that already given as a final value to element in the same Row, column or squar)
2)Get the minimum element that has minimum number of possible values
3)start solve assuming the first possible value is the final value
4)save the current sate into a stack
5)Try to solve
5-a)If solved, return
5-b)if not solved and with invalid Sudoku, then Pop previous state
6)Repeat step 3) for all possible vaues (9)
7)Repeat step 2) until the puzzel is solved
This is my code
Stack<Element[][]> myStack= new Stack<>();
private Element[][] mySudoku;
public void solve(){
update();//remove all final values from all possible values for each element
if(isSudokuSolved(mySudoku)){
return;
}
//find a cell that is not confirmed and has the minimal candidates
int celli=-1,cellj=-1, p=10;
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(mySudoku[i][j].getValue()==0){
if(mySudoku[i][j].getPossibleValues().size()<p){
celli=i;
cellj=j;
p=mySudoku[i][j].getPossibleValues().size();
}
}
}
}
try {
for (int c = 0; c < mySudoku[celli][cellj].getPossibleValues().size() - 1; c++) {
//save state
Element[][] copy=deepCopy(mySudoku);//copy the current state
myStack.push(copy);
//apply candidate to cell
mySudoku[celli][cellj].setValue(mySudoku[celli][cellj].getPossibleValues().get(c));
update();//check is solved
if(checkValidInputSudoku(mySudoku)){
solve();
}else{
try {
mySudoku = myStack.pop();
} catch (EmptyStackException est) {
//do nothing
}
}
}
} catch (Exception e) {
}
//if we have reached here then we are at the last possible value for the candidates so confirm candidate in cell
if(celli!=-1 && cellj!=-1 && p!=10) {//Some problems happen here "out of Boundry -1 Error"
mySudoku[celli][cellj].setValue(mySudoku[celli][cellj].getPossibleValues().get(mySudoku[celli][cellj].getPossibleValues().size()-1));
}
}//end of solve method
I have spent more than 6 hours trying to find out the problem. I have checked for the Update() method, deepCopy() method and checkValidInputSudoku() method. They all works fine. Thank you in Advance
I can see one problem in your code. You have a loop that is sawing off the branch it sits on:
for(int c = 0; c < mySudoku[celli][cellj].getPossibleValues().size() - 1; c++) {
...
mySudoku[celli][cellj].setValue(mySudoku[celli]cellj].getPossibleValues().get(c));
...
}
Apart from that, you are missing one of the values, it should be for(c=0; c!=size; ++c), i.e. not size - 1. Also, calling getPossibleValues() just once would make this code much more readable. Lastly, catching and ignoring a stack underflow is just stupid, because it hides errors in your algorithm, as far as I can tell. If you don't know how to handle an error, don't just silence it. Since java requires you to catch it, put it in the outermost place possible or at least abort or do something, but don't ignore it!
One more thing: You are recursing and passing the context data via mySodoku and myStack. This is completely missing the point of recursion (or at least the way it's typically used), because the function call stack is the only stack you need. Using these to pass parameters only makes things more complicated than necessary. Instead, the function should return a partial sodoku puzzle and return either the fully solved puzzle or null. Using is easier to distinguish than the exception you're using now, and it's a regular and expected thing, not really exceptional. Then, when trying different choices, you set the cell to the values in turn and recurse, until the call doesn't return null. If none of the choices returns a solution, you clear the cell and return null yourself.
solve(sodoku):
if sodoku is solved:
return true
if sodoku is invalid:
return false
c = some empty cell
for v in 1...9:
// set to a value and recurse
c = v
if solve(sodoku):
// found a solution
return true
// no solution found, clear cell and return failure
c = null
return false
BTW: This strategy is called "backtracking". Using a cell with the least amount of possible values is called "pruning", which allows you to cut off whole branches from the search tree. Actually determining the possible values also helps avoiding a few futile attempts.
Related
I'm trying to code the A* algorithm using a self implemented PQ and Vector. It has verticies as junctions and edges as roads. I was able to correctly code the dijkstra algorithm however I needed to improve the performance.
Currently my algorithm breaks throwing a null pointer exception as commented in the code. I've been researching the algorithm for the past 5+ hours whilst trying to implement it. I don't fully understand the method of comparing paths as well as I did for the dijkstra implementation.
Here is my current code:
private Vertex dijkstra (int start, int end)
{
Vertex current;
while (!(pqOpen.IsEmpty()))
{
current = pqOpen.GetNextItem();
else
{
for (int i = 0; i < current.neighbors.GetNoOfItems(); i++)
{
if (hold != null && hold.neighbors.GetItem(i).fromid != hold.city)
{
int x = 1;
if (hold2 == null || hold.getTentativeDistance() < hold2.getTentativeDistance())
{
hold2.from = hold; //throws null pointer here
hold2.setTentativeDistance(hold.getTentativeDistance());
hold2.setF(hold2.getTentativeDistance() + heuristic(hold2, endLoc));
System.out.println(hold2.from.city);
}
}
}
}
return null;
}
private double heuristic(Vertex goal, Vertex next)
{
return Math.sqrt(Math.pow((goal.x - next.x), 2) + Math.pow((goal.y - next.y), 2));
}
I've got a feeling that I've totally misunderstood the pseudo code about half way down the algorithm but as of yet I haven't found a representation that I can wrap my head around - so could someone possibly take a look at my code and point out where and what I'm doing wrong?
Here is a link to the website I used for reference: http://wiki.gamegardens.com/Path_Finding_Tutorial#Pseudo-code_A.2A
I also tried the wikipedia one, but their methods confused me even more: http://en.wikipedia.org/wiki/A*_search_algorithm
Currently it does loop round a few times and stores some nodes, however they are incorrect.
Edit:
I've reverted my code and attempted it a different way. I'm now using these pseudo-code examples to understand the algorithm. http://web.mit.edu/eranki/www/tutorials/search/ and http://www.redblobgames.com/pathfinding/a-star/introduction.html
On the first one, I think my code is correct until line 13 on the pseudo code. From that point I get confused about the term he uses 'position'.
The if statement that I commented out, is from my dijkstra algorithm. However I think the if statements in the pseudo code I meantioned earlier should be something similar to what the IF statements are.
Could anyone possibly help me understand line 13 in the pseudocode in relation to my code?
I did not read all the code, but this part is obviously bad :)
if (hold2 == null)
{
hold2.from = hold; //throws null pointer here
}
See? If the hold2 is null, you are trying to asign value to field from of hold2 which is null in this case, therefore it throws an exception.
This question is very specific to me, so I cannot find related questions on Stack Overflow. So, I'm coding a grep shown below. I am confused on the stringindextoutofboundexception. The reason for that is because I am checking whether it is equals to \0. That means I am handling the out of bound exception, no?
Example:
grep("hello","llo");
This will return 3. That is because its start matching at original[2] which is position 3. However, I am encountering an out of index error. I've spent hours and I can't figure it out.
public static int grep(String ori, String ma){
int toReturn = 0;
int oCounter = 0;
int i = 0;
while (i < ma.length()){
if (ori.charAt(toReturn) == ma.charAt(i)){
i++;
if (ma.charAt(i) == '\0'){ // error on this line
return toReturn;
}
toReturn++;
if (ori.charAt(toReturn) == '\0'){ // and this line if i delete the section above.
return -1;
}
} else {
i = 0;
toReturn++;
}
}
return -1;
}
You're getting an StringIndexOutOfBoundsException because you increment i inside the loop at a too early and wrong stage.
Checking for \0 is a C++ thing. Strings in java are not \0 terminated.
What you're writing is already done in the String class. There are several methods available.
System.out.println("hello".indexOf("llo"));
will print 2 because it's been found and starts at index 2. Feel free to add 1 if you dislike the starting at 0 for some reason.
You also ask "that means I'm handling the exception, no?". No, it doesn't. Exceptions are handled with a special syntax called try-catch statements. And example:
try {
// possibly more lines of code here
do_something_that_might_cause_exception();
// possibly more lines of code here
} catch (Exception e) {
// something did indeed cause an exception, and the variable e holds information about. We can do "exceptional" handling here, but for now we print some information.
e.printStackTrace();
}
Ok, so I have a 3 x 3 jig saw puzzle game that I am writing and I am stuck on the solution method.
public Piece[][] solve(int r, int c) {
if (isSolved())
return board;
board[r][c] = null;
for (Piece p : pieces) {
if (tryInsert(p, r, c)) {
pieces.remove(p);
break;
}
}
if (getPieceAt(r, c) != null)
return solve(nextLoc(r, c).x, nextLoc(r, c).y);
else {
pieces.add(getPieceAt(prevLoc(r, c).x, prevLoc(r, c).y));
return solve(prevLoc(r, c).x, prevLoc(r, c).y);
}
}
I know I haven't provided much info on the puzzle, but my algorithm should work regardless of the specifics. I've tested all helper methods, pieces is a List of all the unused Pieces, tryInsert attempts to insert the piece in all possible orientations, and if the piece can be inserted, it will be. Unfortunately, when I test it, I get StackOverflow Error.
Your DFS-style solution algorithm never re-adds Piece objects to the pieces variable. This is not sound, and can easily lead to infinite recursion.
Suppose, for example, that you have a simple 2-piece puzzle, a 2x1 grid, where the only valid arrangement of pieces is [2, 1]. This is what your algorithm does:
1) Put piece 1 in slot 1
2) It fits! Remove this piece, pieces now = {2}. Solve on nextLoc()
3) Now try to fit piece 2 in slot 2... doesn't work
4) Solve on prevLoc()
5) Put piece 2 in slot 1
6) It fits! Remove this piece, pieces is now empty. Solve on nextLoc()
7) No pieces to try, so we fail. Solve on prevLoc()
8) No pieces to try, so we fail. Solve on prevLoc()
9) No pieces to try, so we fail. Solve on prevLoc()
Repeat ad infinitum...
As commenters have mentioned, though, this may only be part of the issue. A lot of critical code is missing from your post, and their may be errors there as well.
I think you need to structure your recursion differently. I'm also not sure adding and removing pieces from different places of the list is safe; much as I'd rather avoid allocation in the recursion it might be safest to create a list copy, or scan the board
so far for instances of the same piece to avoid re-use.
public Piece[][] solve(int r, int c, List<Piece> piecesLeft) {
// Note that this check is equivalent to
// 'have r and c gone past the last square on the board?'
// or 'are there no pieces left?'
if (isSolved())
return board;
// Try each remaining piece in this square
for (Piece p : piecesLeft) {
// in each rotation
for(int orientation = 0; orientation < 4; ++orientation) {
if (tryInsert(p, r, c, orientation)) {
// It fits: recurse to try the next square
// Create the new list of pieces left
List<Piece> piecesLeft2 = new ArrayList<Piece>(piecesLeft);
piecesLeft2.remove(p);
// (can stop here and return success if piecesLeft2 is empty)
// Find the next point
Point next = nextLoc(r, c);
// (could also stop here if this is past end of board)
// Recurse to try next square
Piece[][] solution = solve(next.x, next.y, piecesLeft2);
if (solution != null) {
// This sequence worked - success!
return solution;
}
}
}
}
// no solution with this piece
return null;
}
StackOverflowError with recursive functions means that you're either lacking a valid recursion stop condition or you're trying to solve too big problem and should try an iterated algorithm instead. Puzzle containing 9 pieces isn't too big problem so the first thing must be the case.
The condition for ending recursion is board completion. You're only trying to insert a piece in the for loop, so the problem is probably either that the tryInsert() method doesn't insert the piece or it doesn't get invoked. As you're sure that this method works fine, I'd suggest removing break; from
if (p.equals(prev[r][c]))
{
System.out.println("Hello");
break;
}
because it's the only thing that may prevent the piece from being inserted. I'm still unsure if I understand the prev role though.
This is for a sudoku-solver and each square has this method. My idea is that if one instance of this method goes through the loop without finding any valid values, it will return to the previous method that called it and continue the loop - trying the next value from the for-loop. I was hoping that this would suffice for backtracking, but all my test fail and I am completely clueless as to how I'm going to solve this one. /end noob-lament
public boolean recursive() {
for(int i = 1; i <= boardSize; i++) {
if(!validValue(i)) {
continue;
} else {
setValue(i);
if(getNext() == null) // This signifies that I am at the end of the list
return true;
else
getNext().recursive(); // same method in the next sudoku square
}
}
return false;
}
Two correctness issues here:
You should check if the result from the recursive invokation was true - and if it is, you should stop the recursion - you have found a solution, don't override it!
You should bubble up the return value of the recursion, specifically - if getNext().recursive(); yields true - you should bubble this true up [and as said in (1) - stop the recursion, you have a solution!]
OK - so since a fellow peer of mine helped me out with this one and managed to get me to understand what was missing, I thought I'd like to share it here in case anyone would be interested to know what was missing.
After the loop is done, the method needs to reset its value. If not the old values that were previously tested before the backtrack would remain after the backtrack. That would mean that when the isValid() method would check the column, row and box that the given square belongs to, the isValid() method would find a lot of values set previously.
All that was needed was one line before 'return false;'
//(end of for-loop)
setValue(0);
return false;
//(method ends)
You're calling getNext() twice. If it doesn't return null in your if statement, you call it again. Are you sure you want to do that?
So I have what I think is pretty good code for a sudoku solver in java but I need some help with this method. It gives me a stack overflow when I embed it in a main method. The problem is that my method doesn't know how to turn around and fix its mistakes. I need a boolean flag (one that, unlike the one used in the code below, actually works preferably) or something to let it know when it should turn back and when it can again go forwards and continue solving the game. Thanks for any help you can give
public void play(int r, int c){//this method throws the StackOverflowError
if(needAtLoc(r,c).size()==9){
int num=1+generator.nextInt(9);
setCell(r,c,num,this);
if(c<8){
System.out.println(this);///////////////
play(r, c+1);
}
else{
play(r+1, 0);
}
}
else{
if(needAtLoc(r,c).size()==0){//no possible moves THIS IS THE PROBLEM LINE!!!
if(c>0){
play(r, c-1);//play last cell, in column to left
}
else{
if(r==0){
play(r,c);//first square, so must play again (can't go back)
}
else{
play(r-1, 8);/*first cell of row so must go to previous row and
the end column*/
}
}
}
else{//if there are possible moves
int num=needAtLoc(r,c).remove(generator.nextInt(needAtLoc(r,c).size()));
setCell(r,c,num,this);//set the value of the cell
System.out.println(this);//////////////
if(r==8 && c==8){//the end of the cell has been reached so must end recursive call
return;
}
else{
if(c<8){
play(r, c+1);//normal, next cell
}
else{
play(r+1, 0);/*last cell in row so we go to next one
in the first column ("return" button)*/
}
}
}
}
}
Rather than solve this for you I would make a few suggestions in how to tackle this. 9 hours is ample.
1) Your code is hard to read. Try to space it out a bit. Give your variables meaningful names that are clear (this helps you and other people read your code). You may have made a simple mistake and clean code will make these easier to spot. Try to break it into smaller methods since this will make it more readable and more maintainable.
2) Stack overflows are caused (generally I believe) when you make too many nested method calls and are typical in recursive code. Therefore make your recursion clear. Make sure you have a base case that will terminate.
Sorry to not give you "the answer" but since this sounds like homework I think there's more value in learning how to solve this yourself. Hope that seems fair.
I think your problem is where you have:
if(r==0)
{
play(r,c);//first square, so must play again (can't go back)
}
That's because you don't seem to modify any state here and you pass the same values in that made you come to this step in the first place. Seems like infinite recursion for me.
Also please align your code correctly as it is too hard to read when it is misaligned and maybe provide some clues what the other methods do. Good luck!
Your code is throwing stack over flow exception because you never reach a terminating condition that ends your recursion, or at least it is not obvious you to see you have a recursion terminating condition by reading your code.
Your code is not well structure, hence you will have a hard time debugging it. Try to restructure your code, it will help you rethink the problem. Also, please comment your code :)
You are recursively calling play without ever returning and it looks as if you are initialising a new set of variables each time at the top of the function.
Try splitting out the initialisation from the recursive part. You also need a clear end condition to end the recursion e.g. (if(isBoardFilled()==true)) return.
Also structure it so that you add a number to the board, test it against the contraints and if it passes add another number (recurse) or backtrack by removing the last number and try again.
I think u are calling play() recursively .Try to check if there is a stopping condition to ur recursive call.
I agree with Tom, but here is a hint.
There is no condition and return statement to end the recursive calls.
I've managed to be more concise and more clear but it still won't run... I just need a push over the edge and I'm home free. I've dumped so many wasted hours into this project:
public ArrayList<Integer> needAtLoc(int r, int c){
int bc=c/3;//the column within the SudokuBoard
int blc;
/*The two posibilities for the column within each SudokuBlock:*/
if(c>=0 && c<3) {
blc=c;
}
else {
blc=c%3;
}
int br=r/3; //the row within the SudokuBoard
int blr;
/*The two possiblities for the row within each SudokuBlock:*/
if(r>=0 && r<3) {
blr=r;
} else {
blr=r%3;
}
ArrayList<Integer> needR = new ArrayList<Integer>();
needR=checkR(r);//
needR.trimToSize();
System.out.println(needR);//////////////
ArrayList<Integer> needC=new ArrayList<Integer>();
needC=checkC(c);
needC.trimToSize();
System.out.println(needC);/////////////
ArrayList<Integer> needBl=new ArrayList<Integer>();
needBl=this.board[br][bc].updateMissing(); //that method updates and returns an ArrayList
needBl.trimToSize();
ArrayList<Integer> poss=new ArrayList<Integer>();
poss.clear();
for(Integer e: needBl){
if(needC.contains(e) && needR.contains(e)){
poss.add(e);
}
}
return poss;
}
//this method throws the StackOverflowError
public void play(int r, int c){
int bc=c/3; //the column within the SudokuBoard
int blc;
/*The two posibilities for the column within each SudokuBlock:*/
if(c>=0 && c<3) {
blc=c;
} else {
blc=c%3;
}
int br=r/3; //the row within the SudokuBoard
int blr;
/*The two possiblities for the row within each SudokuBlock:*/
if(r>=0 && r<3) {
blr=r;
} else {
blr=r%3;
}
if(needAtLoc(r,c).size()==9){
int num=1+generator.nextInt(9);
this.board[br][bc].setValue(blr, blc, num);
if(c<8){
System.out.println(this);///////////////
play(r, c+1);
} else{
play(r+1, 0);
}
} else{
if(needAtLoc(r,c).size()==0){ //no possible moves
if(c>0){
bc=(c-1)/3;
if(c>0 && c<4) {
blc=c-1;
} else {
blc = (c-1) % 3;
}
this.board[br][bc].setValue(blr, blc, 0);
play(r, c-1);
}
else{
blc=0;
bc=0;
if(r==0){
blr=0;
br=0;
this.board[br][bc].setValue(blr, blc, 0);
play(r,c);
}
else{
br=(r-1)/3;
if(r>0 && r<4) {blr=r-1;}
else {blr=(r-1)%3;}
this.board[br][bc].setValue(blr, blc, 0);
play(r-1, 8);
}
}
}
else{//if there are possible moves
int num=needAtLoc(r,c).remove(generator.nextInt(needAtLoc(r,c).size()));
this.board[br][bc].setValue(blr, blc, num);
System.out.println(this);//////////////
if(r==8 && c==8){
return;
}
else{
if(c<8){
play(r, c+1);
}
else{
play(r+1, 0);
}
}
}
}
}