Sudoku Solving Algorithm - java

I have tried writing the algorithm by referring this.
But i am getting Error of StackOverFlow.
Help me out to find what is wrong in the program? Is it the recursion part?
public void beginSolving(int board[][],int x,int y){
int i = 1;
if(unassignedCell(board,x,y)){
board[x][y] = i;
if(isValidCell(board,y,x,i)){
board[x][y] = i;
}
if(!isValidCell(board,y,x,i)){
board[x][y] = 0;
i++;
}
} else {
while(x<9){
beginSolving(board,x++,y);
if(x==9){
x = 1;
beginSolving(board,x,y++);
if(y==9){
}
}
}
}
}

Look at the recursive calls: beginSolving(board,x++,y). The x and y parameters are the same as in the original call (remember that the value of x++ is the value before it is incremented). Thus it is likely that you enter a never ending recursion.
The while(x < 9) will never terminate since whenever x reaches 9 it is reset to 1.
The algorithm never tries to set a number other than 1 into the board.
There may be other problems with the code as well, I did not check it in detail.

Related

How do you return a zero if there is nothing in the grid where you checked?

To start things off, I am making a game. You fight on a 3x3 Grid (using a 2 Dimensional-Array), and if the "Lane#" (Lane# = Row + Col) ahead of you is blank then you get a -15% Damage Reduction, and this stacks for every blank lane.
This means if you are on [0][0] then you are in Lane# 0, and therefore, cannot possibly have anyone ahead of you, and you will always take 100% of Damage (this is of course without defense and yadda yadda else that modifies)
And if you are on [2][2] then you are in Lane# 4, and if every lane ahead of you has atleast one space in it taken, then you will take 15*4 = 60, 100-60 = 40% of actual damage.
Now that that is out of the way. I am having difficulty returning 0... I keep getting an Error that says that you cannot return a Void value...
'cannot return a value from method whose result type is void'
public Blanks(int l) { //l = Lane
int x = 0; //The Return
for (int i = 0; i < 6; i++) //The loop
if (l=0){ //Here I keep getting an error saying 'incompatible types'
x = 0;
return x; //Here is the 'cannot return a void value' error
break;
}
if (l>=1){
x++;
}
if (l>=2){
x++;
}
if (l>=3){
x++;
}
if (l>=4){
x++;
}
return x; //for some odd reason, this is also a void value
}
}
I still have yet to add the Checking the Array / Grid part as I am stumped about that one as well.. but another problem, another question.. the actual array itself..
you should modify the method header to public int Blanks(int l) {
and you should remove break; keyword because you return method value before it and will be unreached statement.
In order to return an integer value you have to mention a return type in the method. Also, in the first if statement you have used assignment operator instead of comparing.
Also why you have used break after return. I think you have to do first break and then return in the end.
One more thing to add. Your for loop should contain braces. Only the first if statement will get executed according to your code.
public int Blanks(int l) { //l = Lane
int x = 0; //The Return
for (int i = 0; i < 6; i++) //The loop
if (l==0){ //Here I keep getting an error saying 'incompatible types'
x = 0;
break;
}
if (l>=1){
x++;
}
if (l>=2){
x++;
}
if (l>=3){
x++;
}
if (l>=4){
x++;
}
return x; //for some odd reason, this is also a void value
}
}
I haven't stepped into your logic. Comment if you face any problem after this.
I don't understand why you are using the for loop here, but this is a way to do it:
public int Blanks(int l) {
int x = 0;
for (int i = 0; i < 6; i++)
if (l==0){
x = 0;
}else {
x++;
}
return x;
}
But in case that l==0 your method will return 5;
If you want to return 0 or 1 then you need to remove the for loop
public int Blanks(int l) {
if (l==0) return 0;
else return 1;
}
And the method with true-false:
public boolean Blanks(int l) {
if (l==0) return false;
else return true;
}

Variable keeps getting set to 1 at the end of recursion method

EDIT: Got it working. Still not sure what the weird issue was, but I think it had to do with the fact that I had a loop and recursion.
I don't fully understand the question. but you don't need both, a while loop and recursion. Recursion alone is sufficient here. Use a simple if statement to stop recursion when the number is fully printed.
Note that recursion simplifies putting the digits in the right order here -- with a while loop, you'd need to reverse them somehow...
public static void printInBinary (int num) {
int div = num % 2;
int rem = num / 2;
if (rem > 0) {
printInBinary(rem);
}
System.out.print(div);
}
Your while loop is continuously going because your num-- isn't in the loop, so the number never changes.
public static void printInBinary (int num)
{
int div = (Integer)num%2;
int rem = (Integer)num/2;
while (num >= 1)
{
System.out.print(div);
printInBinary(rem);
num--;//Moved here
}
//removed from here
}

Sudoku backtracking algorithm (Java)

I've created a Sudoku solver that will solve a Sudoku as a human might- by checking possibilities + definite values in squares corresponding to the square being checked.
(Source: http://pastebin.com/KVrXUDBF)
However, I would like to create a random Sudoku generator (from a blank grid), and so have decided to use a backtracking algorithm. I understand the concept of backtracking, but am confused about one thing:
How do I know which previous node to return to (and change) once I know a certain solution is not allowed?
Should I simply return to the previous node and cycle through all possibilities? (And then if this yields no correct answers, return to the value before, etc.). This seems like a viable method, but also quite inefficient. Is this the correct way of implementing a backtracking method or is there a better way to go about it?
Thanks in advance.
More can be found about backtracking here: http://en.wikipedia.org/wiki/Backtracking
Sudoku Puzzle can be reduced to graph coloring problem which can be solved using simple backtracking like assigning colors to node (1-9) till the there is no violation that all directly connected nodes have no same color.
Constructing Graph from Sudoku : -
There is an direct edge between two grid points if they are in same
row or column or square.
Backtracking :-
Assign one color (1-9) to node
Check if there is no other directly connected node with same color
If valid color move to next node.
else change the color and recheck.
If all color exhausted backtrack to previous node.
Do recursion till all nodes are color.
Once You are done with it you can start removing numbers from the grid at random till you think the problem is unsolvable if any more numbers are removed.
A simple way to generate random Sudoku is that
1) generate a random completing Sudoku, that is, generate random Sudoku no square is blank.
2) Remove numbers from squares of 1).
3) Solve Sudoku of 2). If there are many solutions, then add a number removed at 2).
If there are still many solutions, then repeat 3).
1) sample source code:
public int[][] generateRandomCompleteSudoku() {
int[][] sudoku = new int[10];
for(int i = 1; i <= 9; i++) {
sudoku[i] = new int[10];
Arrays.fill(sudoku[i], 0);
}
generateRandomCompleteSudoku(sudoku, 1, 1);
return sudoku;
}
private boolean generateRandomCompleteSudoku(int[][] sudoku, int x, int y) {
if(x > 9) {
x = 1;
y++;
}
//sudoku of the argument is completing sudoku.
//so return true
if(y > 9) {
return true;
}
// enumerate the possible numbers of the pos(x,y).
List<Integer> possibleNumbers = new ArrayList<Integer>();
for(int i = 1; i <= 9; i++) {
boolean possible = true;
//check i is a possible number.
//check there isn't i in the raw of y .
for(int j = 1; j <= x - 1; j++) {
if(sudoku[j][y] == i) {
possible = false;
break;
}
}
//check there isn't i in the column of x(omitted).
//check there isn't i in the group of x,y(omitted).
if(possible) {
possibleNumbers.add(i);
}
}
//sudoku is wrong so return false.(There is no solution of sudoku)
if(possibleNumbers.size() <= 0) {
return false;
}
Collections.shuffle(possibleNumbers);// This gives sudoku randomness.
for(Integer possibleNumber : possibleNumbers) {
sudoku[x][y] = possibleNumber;
// a sudoku is generated, so return true
if(generateRandomCompleteSudoku(sudoku, x + 1, y)) {
return true;
}
}
// No sudoku is generated, so return false
return false;
}
For a backtracking solution, the first step is to define the state. So for this problem, I think the most straightforward way is (x,y, blank , num) with x , y is the position of the current state, blank is the number of blank position left, and num is the value you want to fill in that position (from 0 to 9 and 0 means blank).
And the return type should be boolean, which determine whether the move is valid or not (which means is there any valid solution for this move).
So, the state transition is column by column, row by row: x, y to x , (y + 1) or x , y to (x + 1), 0.
Similarly, the blank will be from a -> a - 1-> ... 0.
We have a draft solution here:
public boolean move(int x, int y, int blank, int num, int[][]sudoku){
sudoku[x][y] = num;
//checking condition and return if x,y is the last position, code omitted
if(y == sudoku[x].length){
x++;
y = 0;
}else{
y++;
}
for(int i = 1; i < 10; i++){
if(move(x,y,blank,i,sudoku){//Backtrack here
return true;
}
}
if(blank > 0){
if(move(x,y,blank - 1, 0, sudoku){//Backtrack here
return true;
}
}
return false;
}
So when ever there is a false return from the current state, it will backtrack to the last state , and the last state will continue to check for the next num until it find a correct solution (or return false).

Can anyone see where the infinite loop in my program is?

The purpose of this program is to find the smallest number evenly divisible by all integers 1 through 20. I know it could be made more efficient, but I'm not interested in optimizing it right now. When I execute the program, it seems to hang forever, which leads me to believe that there's an infinite loop somewhere. I can't seem to find it though. I'm not sure what part of the code is causing the problem and it's relatively concise, so I'll post it all here.
public class Problem5{
public static void main(String[]args){
boolean notFound = true;
while(notFound){
int n = 20;
if(testDivide(n)){
System.out.println(n);
notFound = false;
}
else
n++;
}
}
private static boolean testDivide(int target){
for(int i = 20; i > 0; i--){
if(target % i != 0)
return false;
}
return true;
}
}
If anyone can help me out with this, I'd appreciate it a lot.
Additional Information: The program also never outputs any numbers, which leads me to believe that if(testDivide(n)) is never evaluating to true.
You are initializing the value of n inside your while loop to 20, since n is always 20 for testDivide(20), which will always return false since 20 % 19 != 0 returns false. Hence remove int n = 20 from your while loop.
boolean notFound = true;
while(notFound){
int n = 20;
should be
boolean notFound = true;
int n = 20;
while(notFound) {
your for loop makes sure you return false, and then your while loop always sets i to 20 this is your infinite loop.
See the while loop:
while(notFound){
int n = 20;
if(testDivide(n)){
System.out.println(n);
notFound = false;
}
else
n++;
}
When the while loop is executed first, the value of n is set to 20.
the test divide returns false.
The value of n is decremented to 19.
The loop executes again
The value of of n is reinitialized to 20.
This is the problem initialize n outside the while loop.

Loop stops running java

For the code below, it stops running when "n" gets around 100,000. I need it to run until 1 million. I dont know where its going wrong, I am still learning Java so there might be simple mistakes in the code as well.
public class Problem14{
public static void main(String[] args) {
int chainLength;
int longestChain = 0;
int startingNumber = 0;
for(int n =2; n<=1000000; n++)
{
chainLength = getChain(n);
if(chainLength > longestChain)
{
System.out.println("chainLength: "+chainLength+" start: "+n);
longestChain = chainLength;
startingNumber = n;
}
}
System.out.println("longest:"+longestChain +" "+"start:"+startingNumber);
}
public static int getChain(int y)
{
int count = 0;
while(y != 1)
{
if((y%2) == 0)
{
y = y/2;
}
else{
y = (3*y) + 1;
}
count = count + 1;
}
return count;
}
}
Please use long as the data type instead of int
I will want this to come into light, that the number does flung higher than 1000000, so variable y needs long to hold it.
It's the datatype for y. It should be long. Otherwise it wraps round to -2 billion.
I thought I recognised this - it's Euler problem 14. I've done this myself.
getChain() method is causing problem it gets to negative and then it hangs forever in the loop.

Categories

Resources