recently I've been trying to teach myself a bit of recursion to understand the process better. While I understand basic recursion techniques, I still struggle quite a bit with the idea of recursive backtracking. In order to help this, I've attempted to program a method that solves a sudoku solver when given a 2D array and and two ints, r and c, which are meant to represent the current column and row.
I have everything set up properly I believe, yet I can't quite figure out how to handle the "unraveling", or what happens after my initial method calls reach the eventual base case.
As of right now, when I run this method, it just returns a board that's empty, (unless there was previously a value there before, in which case it remains unchanged). I feel like the "board[r][c] = 0" that I have at the end of the method might have something to do with that.
The method "digitsValid" corresponds to a method that checks to make sure the current location on the board is a valid move within the row, column, and 3x3 subgrid.
Any help would be much appreciated.
private boolean sudokuSolver(int[][] board, int r, int c) {
if(c > 8) {
c = 0;
r = r + 1;
}
if(r > 8) {
return true;
}
if(board[r][c] != 0) {
sudokuSolver(board, r, c + 1);
} else {
for(int i = 1; i <= 9; i++) {
if(digitsValid(board, r, c)) {
board[r][c] = i;
if(sudokuSolver(board, r, c + 1)) {
return true;
}
}
}
}
board[r][c] = 0;
return false;
}
I think your original assessment is correct. Recursive methods sound confusing but think of them like this:
public class RecursiveTest{
public static void main(String[] args){
int x = 5;
recursiveMethod(x);
}
public static void recursiveMethod(int i){
System.out.println("Method just started for i = " + i);
if(i > 0)
recursiveMethod(i - 1);
System.out.println("Method just ended for i = " + i);
}
}
Yields the following output:
Method just started for i = 5
Method just started for i = 4
Method just started for i = 3
Method just started for i = 2
Method just started for i = 1
Method just started for i = 0
Method just ended for i = 0
Method just ended for i = 1
Method just ended for i = 2
Method just ended for i = 3
Method just ended for i = 4
Method just ended for i = 5
Explanation
A recursive method is not all that different from any other method. It executes some code, at some point calls a method, runs that method and then continues running the rest of the code and finishes where any other method would finish.
The only difference is that method call is a call to itself. This would work the same as if you had copy-pasted that same method 5 times and named it all something different and then "daisy chained" them together.
In the example above, the original value is 5, it prints out that it started the for i=5, then ran the same method with the value of 4. Printed that, then ran 3 etc. Once it reached the final value where i = 0 the if statement failed and therefore it stopped the recursive calls. The method we are currently in (i = 0) finishes by writing Method just ended for i = 0 then it returns to the calling method when i = 1 and back tracks the same way it went in.
Your Code
I'm not quite sure what you have going on here. Does your example work? I'd like to see the isValid() method, but the following code you have:
for(int i = 1; i <= 9; i++) { // Runs the following code 9 times.
if(digitsValid(board, r, c)) { // if true once, true every time
board[r][c] = i;
if(sudokuSolver(board, r, c + 1)) { // this is a totally separate method
return true;
}
}
}
Your loop runs 9 times. The if statement following it never changes. The values within are not edited within the loop, so if it evaluates to true when i = 1 then it's going to evaluate to true on all 9 iterations of the for loop. This means the value at board[r][c] is going to end on 9.
From the looks of it, the only way this will ever return false, is if there is an invalid digit already stored in the array at the time of calling the method.
Related
public int max1020(int a, int b) {
// First make it so the bigger value is in a
if (b > a) {
int temp = a;
a = b;
b = temp;
}
// Knowing a is bigger, just check a first
if (a >= 10 && a <= 20) return a;
if (b >= 10 && b <= 20) return b;
return 0;
}
so if both a and b are within the range [10,20], would it just return a, and stop excuting the next two lines of code?
so if both a and b are within the range [10,20], would it just return a, and stop executing the next two lines of code?
It first checks a, if it matches the first condition then the function is returned with the value of a. The next two lines of code will not be executed as the function has returned.
Does the program stop executing once it returns something?
No, the value is not returned by the whole program it is just returned by the particular function. Let me give you an example.
public class Main {
public static void main(String[] args) {
int result;
// The method max1020 returns the value of 'a' here
result = max1020(11,14);
System.out.println(result);
// The method max1020 returns the value of 'b' here
result = max1020(31,11);
System.out.println(result);
// The method max1020 returns the value of '0' here
result = max1020(50,60);
System.out.println(result);
}
private static int max1020(int a, int b) {
// First make it so the bigger value is in a
if (b > a) {
int temp = a;
a = b;
b = temp;
}
// Knowing a is bigger, just check a first
if (a >= 10 && a <= 20) return a;
if (b >= 10 && b <= 20) return b;
return 0;
}
}
The return keyword just gets you out of the function you are in, it does not get you out of your whole program. When you call the max1020() for the first time it returns a. See it returns the value of a but the program will still execute the other lines. It will print the value of the variable result then it'll again call the max1020() on another pair of values.
If both a and b are within the range [10,20] it will always return a.
You are correct, once a return statement is reached, it will not execute any further code.
You are correct in the assumption that the program checks if a is withing the range, and given that the result of the evaluation is true it will return the value bond to variable a.
In Java the keyword return means that the program will return the value associated with it and stops further execution.
As for your question about the void method. In Java and many other languages you have something called "state" which means that there exists some values outside of the current scope of execution, e.g in pseudocode
int a = 0
public void inc (){
a++
}
Method inc does not take any arguments (it has an arity of 0) but increments the variable a that is defined outside the scope of the function it self. Any method that has other return type than void returns the defined type.
I hope that my answer was helpful.
You seem to be mixing method return and program exit (which can also be called "program return code").
In a method, whenever the line return is reached, the method stops right there and will not execute further instructions.
When that method is the main method, it also is the entry-point of the program. Therefore, when the main calls return, the program will effectively stop, returning code 0 (which means "success").
In Java, you can also stop a program execution by calling System.exit(ret). In that particular case, the JVM process (which is "your program") will stop executing further instructions, even if return is not explicitly called (though some IDE will give you errors or warnings). The return code (seen by the caller process) will be the one you specified with ret.
I'm trying to learn Java, I studied Pascal in high school and it has the repeat until..; instruction.
I want to solve an exercise where I'm supposed to keep entering numbers until the penultimate + antepenultimate numbers equal the last number I entered.(a[i-2]+a[i-1] = a[i]); I'm doing it without arrays but that doesn't really matter.
In Pascal it would be easy because repeat until is more easier to use
For ex it would be
repeat
...
until ((a[i-2]+a[i-1] = a[i]) and (n=3));
n is the number of values I entered
I can't figure out how to introduce it in Java, so far I did this but it doesn't work if I enter 2 2 4. It should stop but it keeps asking for numbers
int pen = 0, ant = 0, s = 0, n = 1;
int ult = input.nextInt();
s = s + ult;
do {
do {
ant = pen;
pen = ult;
ult = input.nextInt();
n++;
s = s + ult;
} while (ant + pen != ult);
System.out.println(n);
} while ((n == 3) || (n < 4));
ult is the last number I enter, s is the sum of the numbers entered.
Could anyone tell me how to set the conditions so it will stop if I enter the values 2 2 4?
A Do-While loop runs the code in the loop first. It evaluates the logic last, and then if it's true it repeats the code inside the loop, and so on until the logic is false.
The way to solve tricky problems like this is to get out a sheet of paper and record what each variable does. Step through each line like a debugger and record what's being stored in each variable as the program progresses.
It's the best way to do it. You'll find that you'll gain a deeper understanding of how your programs are working.
Java isn't any more magic than Pascal, the issue might be you've had a long break from programming :). Anyway, its been a while since I wrote anything in Java, but the issue I could spot in your code is just that n equals three after you've entered three ints, and so the outer loop continues.
int pen = 0, ant = 0, ult = 0, n = 0;
do {
ant = pen;
pen = ult;
ult = input.nextInt();
} while (++n < 3 || ant + pen != ult );
assert n >= 3;
assert ant + pen == ult;
Note that ever since Pascal everything has been zero indexed instead of one indexed.
Pascal uses the form:
repeat
doStuff();
until (boleanValue);
Java is basically the same, except for one important point:
do
doStuff();
while (~boleanValue);
The important difference is that "~" before booleanValue. The Pascal repeat ... until keeps running until the boolean evaluates to true. In Java the do ... while keeps running until the boolean evaluates to false. When converting from Pascal to Java you need to switch the boolean to work the other way.
The primary difference between while loop and a do-while loop is that while loop does eager condition check where as do-while loop does lazy condition check
while: Expression is evaluated at the top of the loop
syntax:
while (expression) {
statement(s)
}
(taken from http://www.w3resource.com/c-programming/c-while-loop.php)
Example:
public class WhileDemo{
public static void main(String args[]) {
boolean isSunday = false;
while(isSunday) {
System.out.println("Yayy.. Its Sunday!!");
}
}
}
Output: (nothing is printed on console)
Reason: Since isSunday is false, the body of loop is not executed
do-while: Expression is evaluated at the bottom of the loop. Therefore, the statements within the do block are always executed at least once.
syntax:
do {
statement(s)
} while (expression);
(taken from http://www.w3resource.com/c-programming/c-do-while-loop.php)
Example:
public class DoWhileDemo{
public static void main(String args[]) {
boolean isSunday = false;
do {
System.out.println("Yayy.. Its Sunday!!");
} while(isSunday);
}
}
Output: Yayy.. Its Sunday!!
Reason: The body of do is executed first, there by printing Yayy.. Its Sunday!! and then the condition while(isSunday); evaluates to false since isSunday is false and the loop terminates
You're only missing one thing from your problem. Your explanation of the Pascal code is almost correct, but wouldn't work without some modification.
In Java, use short-circuit logical operators to do the check.
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
Not tested:
int n = 0;
int a[] = new a[3];
do {
n++;
a[0] = a[1];
a[1] = a[2];
a[2] = input.nextInt();
} while ((n < 3) || (a[0]+a[1] != a[2]));
System.out.println(a[2]);
I was trying to implement the coin change problem using recursion. I have written the following code and am facing a problem with the static class variable. 'answer' is a class variable and i am trying to add the return value to it in the loop. This works fine within the while loop but after the while loop ends the answer is reset to 0;
while (i * currentCoin <= sum) {
System.out.println("inside while; answer is " + answer);
answer = answer
+ findCombinations(
sum - i * currentCoin,
new ArrayList<Integer>(denominations.subList(1,
denominations.size())));
i++;
}
Below is all the code that I have written. You can copy and run it to check.
import java.util.ArrayList;
import java.util.Collections;
public class CoinChangeHashMap {
static int answer = 0;
public static void main(String[] args) {
int[] array = new int[] { 7, 3, 2 };
ArrayList<Integer> input = new ArrayList<Integer>();
getList(array, input);
findCombinations(12, input);
System.out.println(answer);
}
private static void getList(int[] array, ArrayList<Integer> input) {
for (int i : array) {
input.add(i);
}
}
public static int findCombinations(int sum, ArrayList<Integer> denominations) {
if (denominations.size() == 1) {
if (sum % denominations.get(0) == 0) {
return 1;
}
return 0;
}
int i = 0;
int currentCoin = denominations.get(0);
while (i * currentCoin <= sum) {
System.out.println("inside while; answer is " + answer);
answer = answer
+ findCombinations(
sum - i * currentCoin,
new ArrayList<Integer>(denominations.subList(1,
denominations.size())));
i++;
}
return 0;
}}
**The output that I get is 0. but the expected output is 4. While debugging the output that I got is **
inside while; answer is 0
inside while; answer is 0
inside while; answer is 1
inside while; answer is 1
inside while; answer is 2
inside while; answer is 2
inside while; answer is 0
inside while; answer is 0
inside while; answer is 0
0
Any Help is appreciated.
The problem is related to your odd code structure, in which you convey the outcome of your recursive call sometimes by modifying static variable answer, and sometimes via the method's return value.
If you analyzed the problem more closely, you would discover that it is not upon exit from the loop that the partial results are lost, but rather some time after return from the method. Therefore, consider carefully the way you update the answer:
answer = answer + findCombinations( /* ... */ );
At the top-most level of your recursion, answer is initially 0. When Java evaluates the above expression, it evaluates first the left operand and then the right operand, then it adds them. That is, it evaluates answer, getting the result 0, before it performs the recursive call. The value of answer may be updated in the course of the recursive call, but those changes come too late. Only the bottom-most level of the recursion ever returns a value different from zero, so if the recursive call itself recurses at least one level deeper then it will return zero. In that case, the sum is computed as 0 + 0, and assigned to answer, clobbering any update the method performed.
You could resolve the problem by swapping the order of the operands in your sum, but it would be better, and not much harder, to get rid of the static variable altogether. Use a local variable within the method to accumulate results, and in all cases convey the total back to the caller via the method's return value.
So I made this simple code with some help of a tutorial. Going through it i am not quite sure what happens at return faktor(tall-1)*tall.
in the return statement the method calls itself and returns a value. What happens first? Does it call itself first, or does it first return the values, or do they both happen at the same time?
When it returns the values what happens then?
package enkelrekursjon1;
public class Enkelrekursjon1 {
public static void main(String[] args) {
System.out.print(faktor(3));
}
private static int faktor(int tall){
System.out.print(tall);
if (tall != 1){
return faktor(tall - 1)*tall;
}
return 1;
}
}
It works the same way a return statement returning a value always works:
The expression is evaluated (in this case faktor(tall - 1) * tall)
The value is returned to the caller
It can't possibly return before evaluating the expression, because there'd be no value to return.
So in your case, if you have call faktor(5) you'll end up with a call stack of:
faktor(5)
-> calls faktor(4)
-> calls faktor(3)
-> calls faktor(2)
-> calls faktor(1)
-> returns 1
-> returns 1 * 2 (i.e. 2)
-> returns 2 * 3 (i.e. 6)
-> returns 6 * 4 (i.e. 24)
-> returns 24 * 5 (i.e. 120)
I have wondered about it myself and the best way to know it is by letting the program find it out, so I modified your code to see what actually happens. Here is the code that I modified (I commented and written it in your native tongue and I think we live in the same country. Er ikke norsk dog. lol.)
public class EnkelRekursjon1 {
private static String funksjonNavn= "";
private static int resultat=0;
public static void main(String[] args) {
int tall = 3;
System.out.print(tall+"! = "+faktor(3)); // resultat printes etter rekursjon
}
private static int faktor(int tall){
funksjonNavn="Faktor("+tall+")";
System.out.println(tall);
//finn hvilken funksjon vi er.
System.out.println("Funksjonen kaller "+ funksjonNavn);
if (tall != 1){
resultat= faktor(tall - 1)*tall;
System.out.println("Reusltatet er "+ resultat);
return resultat;
}
System.out.println("-------------------------------");
//finn resultat for hver "rekursjon"
System.out.println("Reusltatet er "+ (resultat+1));
//blir 1* 0 her tror jeg, så funksjonen returnerer 1 istedenfor 0
return 1;
}
}
and here is the result:
If you want to evaluate it manually, it will look like this .
faktor(5) = faktor(4)*5
we'll get the value of faktor(4), and it's like this:
faktor(4) = faktor(3)*4
we'll do the same to the rest of the "faktor(int tall)" until the condition is false.
faktor(3) = faktor(2)*3
faktor(2) = faktor(1)*2
faktor(1) will return 1 since tall is equal to 1 (hence, the condition is false). substituting faktor(1) with 1,
we get:
faktor(2) = 1*2 =2
substitute faktor(2) with 2, we get
faktor(3)= 2 * 3 = 6
substituting faktor(3) with 6, we get
faktor(4)= 6*4 = 24
finally, we get:
faktor(5) = 24*5 = 120
I hope it's clear enough this time
I hope I have answered your question. Please don't hesitate to ask if you have further questions. Ha ein fin dag :)
This is a recursive structure. It uses the condition
if(tall != 1)
as the base case. So this method will go through and do some work, check if tall is equal to one, if not it will go through and operate on the data again. So on and so forth until the base case is satisfied (tall==1)
Hope this helps
First, if the condition is true, the method calls itself. The method will only return when tall reaches 1.
I am trying to understand the working of return statement in JAVA.
My doubt is if inside a method with a Non void return type, I have a decision block which also has a return statement of its own, Still I have to return some value .
For understanding here is a sample code I have written :-
public int bunnyEars(int bunnies) {
//int count=0;
if (bunnies >=1) {
count = count + 2;
bunnyEars(bunnies -1);
return count1;
}
return count2 ;
}
In the mentioned code I just want to return the no. of bunnies which I am being able to do from inside the bunnyEars method count1. But still JAVA wont allow to have a non-void method without a return type which is totally understood and I have to add count2 return also. Now I am suspecting that I am having a conceptual understanding failure here. Kindly let me know if I am missing something? Kindly let me know If I am missing some more info here.
[Edited] Full code:
public class Test5 {
//public int ears=1;
public int count=0;
public int bunnyEars(int bunnies) {
//int count=0;
if (bunnies >=1) {
count = count + 2;
bunnyEars(bunnies -1);
return count;
}
return count ;
}
public static void main(String args[]){
Test5 test5= new Test5();
System.out.println(test5.bunnyEars(90));
}
}
Yes you need to return count2 which should be zero. Which means if there are no bunnies then there are no ears. So which returning you should be returning some value irrespective of the conditional block.
So in this case
return count1;
represents the number of ears if the bunnies are represent, while
return count2;
represents the number of ears when there are no bunnies, which should be 0.
I hope that gives you some clarification
I think your conceptual misunderstanding lies with understanding the flow of the program.
Supposed you were to use this method by calling:
bunnyEars(2)
Then, once you enter the method, the first thing the program does is check if 3 >= 1. Since this is true, you proceed into the code inside the {..} (called a 'block'). Inside this block, you increment count by 2. I am assuming count is defined elsewhere in the class, but suppose the current value for count is 10. Then, the new value of count will be 12.
After this, the program executes the line:
bunnyEars(bunnies - 1)
Which translates to:
bunnyEars(1)
Now, basically, you are calling the same method again, but passing in 1 instead of 2.
Once again, the program checks to see that 1 >= 1, which is true. So it goes into the
if-block which, again, increments count by 2. So now, count = 14. Then it calls the
same method again but this time passing in 0.
bunnyEars(0)
Since 0 >= 1 evaluates to false, you the program skips the if-block and continues
execution after the block. So know, you are in the method bunnyEars(), but you have
completely skipped over your "return" statement. But, alas, bunnyEars MUST return an int.
So this is why you must have a return after the block. In your case, bunnyEars(0) returns count2 and the program-execution returns to where you called bunnyEars(0).
Read up on recursive calls. The basic idea of a recursive method is that, inside the recursive method, you must have some case that terminates the recursion (otherwise you will loop forever).
For example, the following code will go on forever:
public int sum(int in)
{
return in + sum(in - 1);
}
This will keep going on forever, because sum(1) will call sum(0) which calls sum(-1).
So, I must have a condition that terminates the recursion:
public int sum(int in)
{
if(in == 0) return 0;
return in + sum(in - 1);
}
Now, I have a terminating-case. So if I call sum(1), it will call sum(0) which returns 0. So my result is 1 + 0 = 1.
Similarily,
sum(2) = 2 + sum(1) = 2 + 1 + sum(0) = 2 + 1 + 0
sum(3) = 3 + sum(2) = 3 + 2 + sum(1) = 3 + 2 + 1 + sum(0) = 3 + 2 + 1 + 0 = 6
Hope this helps!
So as I understand it, your question is why you still need to return count2 if you return count1. The answer is basically 'what happens if you don't enter the if block?'. In that case, without return count2, you wouldn't have a return value, which is what Java is complaining about. If you really don't want two return statements, you could probably do something like:
public int bunnyEars(int bunnies) {
int count=0;
if (bunnies >=1) {
count = count + 2;
bunnyEars(bunnies -1);
}
return count ;
}
On a side note, this and the code you posted in your question won't work for regression purposes, but the one in your comment does, and there it looks like you have a static variable for count, in which case you could set the return type to void and just print count.