I have been given the following question:
Consider the following method. What should it return if n == 3?
public static String recEx(int n) {
if (n <= 0)
return "";
return recEx(n - 3) + n + recEx(n - 2) + n;
}
The answer is 3113. How and what do you do to achieve this answer?
Simply put a System.out.println(n) at the top of the method and you will see.
recEx(3) calls
recEx(0)+3+recEx(1)+3
where recEx(1) is
""+1+""+1
The best approach is using a pencil and a paper and start drawing things.
_recEx(3)_
/ \
/ recEx(1)
recEx(0) / \
/ recEx(-2) recEx(-1)
""
When the value is <= 0, an empty String is returned, this value is pushed back to the caller... and that's the recursion! It's good to begin with smaller example, say n = 2, or even n = 1, try to understand it and then apply it on bigger numbers.
A good practice is debugging your code and carefully following the debugger, step by step, see all the values and trying to understand them.
recEx(3) = recEx(0) + 3 + recEx(1) + 3
recEx(0) = ""
recEx(1) = recEx(-2) + 1 + recEx(-1) + 1
recEx(-2) = ""
recEx(-1) = ""
So the answer is:
recEx(3) = recEx(0) + 3 + recEx(1) + 3
recEx(3) = "" + 3 + recEx(-2) + 1 + recEx(-1) + 1 + 3
recEx(3) = "" + 3 + "" + 1 + "" + 1 + 3
recEx(3) = "3113"
Start with the base case: n <= 0
recEx(0) ; ==> ""
When you look at the default case it will always reduce n on each recursion. Thus you should try n == 1 and use the knowledge that when n <= 0 it can be replaced with "".
recEx(1); ==>
recEx(-2) + 1 + recEx(-1) + 1; ==>
"" + 1 + "" + 1; ==>
"11"
Then you try n == 2
recEx(2); ==>
recEx(-1) + 2 + recEx(0) + 2; ==>
"" + 2 + "" + 2; ==>
"22"
Then you try n == 3. Here you use you prior knowledge of recEc(1)
recEx(3); ==>
recEx(0) + 3 + recEx(1) + 3; ==>
"" + 3 + "11" + 3; ==>
"3113"
There you go.. As you can see I go from the simplest and go backwards. I'm using substitution rules saying you can replace the result of a known result with a method call. As long as the method is functional (doesn't rely on enything else than arguments) you can do this.
For fun whats recEx(5) ? Well it must be like this:
recEx(5); ==>
recEx(2) + 5 + recEx(3) + 5; ==>
"22" + 5 + "3113" + 5 ==>
"22531135"
It's quite simple when you already know the answers for recEx(2) and recEx(3).
Calculating recEx(3) starting with the default case works the same except you need to stop what you are doing at each level to calculate the result of the recursive call. Remember to keep track of which n you have calculated and it's result so you don't need to do same n several times like the computer actually does.
I find doing it the way I presented here much easier since you don't need to do several things in the same time.
You have to trace it:
when n=3
will call again for:
recEx(0) + 3 + recEc(1) + 3
recEx(0) // will return empty string
and if you call for recEx(1)
recEx(-2) + 1 + recEx(-1) + 1
recEx(-2) // will return empty string
recEx(-1) // will return empty string
so first will retun to calculate
recEx(-2) + 1 + recEx(-1) + 1 = "" + 1 + "" + 1 = "11"
and this result will back to the first caller
recEx(0) + 3 + recEc(1) + 3 = "" + 3 + "11" + 3 = "3113"
and to print the result to console:
System.out.println(recEx(3));
Related
I'm new to recursion and don't understand how it works.
This was a classwork problem that had the answer 18, but I don't understand how. From what I know, this should return 6 + 5 + 4 + 3 (3 + m-1 on the recursive line)?
Are the subtraction signs not indicative of subtraction? (assuming that m = 5)
public int test(int m)
{
int value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
return value;
}
6 + 5 + 4 + 3 (3 + m-1 on the recursive line)? Are the subtraction
signs not indicative of subtraction?
No the +3 will happen for every one of the recursive calls, actually what your function is doing is given the value of (m times 3) + 3.
So for m=5 the recursive calls will be like:
Is m = 0 ? No so let us called recursively:
test(4) + 3
m = 4; then test(3) + 3 + 3
m = 3; then test(2) + 3 + 3 + 3
m = 2; then test(1) + 3 + 3 + 3 + 3
m = 1; then test(0) + 3 + 3 + 3 + 3 + 3
m = 0; then exit with 3 + 3 + 3 + 3 + 3 + 3
Hence, for m=5 you get 18.
A side-note you can use the ternary operator to simplify your method to:
static public int test(int m) {
return (m == 0) ? 3 : test(m - 1) + 3;
}
For visualizing what happens, scatter the code with messages:
public int test(int m)
{
System.out.println("entering test("+m+")");
int value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
System.out.println("returning "+value+" from test("+m+")");
return value;
}
Of course this is just the minimal program, you could also show which branch of the if was taken, m-1, and so on.
JavaScript equivalent, so it can run here in the browser:
function test(m) {
console.log("entering test(" + m + ")");
var value;
if (m == 0)
value = 3;
else
value = test(m - 1) + 3;
console.log("returning " + value + " from test(" + m + ")");
return value;
}
console.log("result: "+test(3));
On the longer run it is a good idea to learn using the debugger of the environment you are using. Among other things, debuggers can step through code line-by-line.
I am trying to understand this recursive method but even with a debugger I couldn't come up to something that makes sense to me so i hope someone here is motivated to explain me what is going on here. I know how recursion works basically but the way this method is written down troubles me.
I know the conditional operator in java and I worked out a new code but still I don't understand it, so what I expect here is.
What is the result for m(5) AND m(15). How did you calculate it? Thanks
Edit after the answers. I made a table with my results for future readers
m(n)::|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|...
result|0|0|1|1|1|2|3|4|6|9|13|19|28|41|60|88|...
I checked only the result of 15 with my program.
public class practice {
/**
* Try to understand the way this works
* #param n
* #return
*/
static long m(long n) {
return n <= 1 ? 0 : n == 2 ? 1 : m(n - 1) + m(n - 3);
}
/**
* This is what i tried so far.
* #param n
* #return
*/
static long ma(long n) {
System.out.println("Method called");
System.out.println("N is: " + n);
if (n <= 1) {
System.out.println("N<=1: " + n);
System.out.println("0 is returned");
return 0;
} else if (n == 2) {
System.out.println("N==2: " + n);
System.out.println("1 is returned");
return 1;
} else {
System.out.println("Inside ELSE, N is: " + n);
return ma(n - 1) + ma(n - 3);
}
}
public static void main(String[] args) {
ma(15);
}
}
Wrote it this way to make it more understandable:
m(0) = 0
m(1) = 0
m(2) = 1
m(n) = m(n - 1) + m(n - 3) // n >= 3
When we know the values for m(0), m(1) and m(2), we can calculate any m(n), where n >= 3, using m(n - 1) + m(n - 3). For any negative input, the result is 0.
For example:
m(3) = m(3 - 1) + m(3 - 3) = m(2) + m(0) = 1 + 0 = 1
m(4) = m(4 - 1) + m(4 - 3) = m(3) + m(1) = 1 + 0 = 1
m(5) = m(5 - 1) + m(5 - 3) = m(4) + m(2) = 1 + 1 = 2
And so on...
Pencil and paper are you friends.
There are 3 cases (two of them are base conditions)
if n <= 1 then return 0
if n == 2 then return 1
else recursive call to m(n-1) + m(n-3)
So you know that on every recursive call we are approaching one of the base conditions.
Here is a stack trace of what happens on m(5)
m(5)
m(4) + m(2)
m(3) + m(1) return 1
m(2) + m(0) return 0
return 1 return 0
Adding all the returns gives 1 + 0 + 0 + 1 which is 2
So
m(5) == 2
Method m in pseudo code. (this is some kind of scala/python mash up)
def m (number n)
if (n <= 1) 0
else if (n == 2) 1
else m(n - 1) + m(n - 3)
Looking at this you can see that anything <= 2 is a terminal operation, returning 0 or 1 based on the input. If n is > 2, the fun begins. Take for example n=3. Since 3 is greater than 2, we need to run the third if. When we look at that line we see that we nee to return m(n - 1) + m(n - 3). Plugging n = 3 in, it looks like this: m(3 - 1) + m(3 - 3), or, more simplified, like this: m(2) + m(0). This will now terminate with 1 because neither 2 or 0 for n will result in more calling of m.
So now we have something we understand we can now workout what m(15) and m(5) will return.
I will only work it out for 5 since the call stack for 15 would be way to long
m(5)
/ \
m(5-1) + m(5-3)
/ \ |
m(4-1) + m(4-3) |
/ \ | |
m(3-1) + m(3-3) | |
| | | |
1 + 0 + 0 + 1
2
Hope it helps!
m(5) = m(4)+m(2) // 5>2, so the third condition
m(4) + m(2) = m(3)+m(1) + 1 // 4>2, so the third condition
m(3) + m(1) + 1 = m(2)+m(0) + 0 + 1 // 3>2, so the third condition
m(2) + m(0) + 0 + 1 = 1 + 0 + 0 + 1 = 2
Now, between transformations, m(2) s instantly replaced with 1, and m(n<=1) is instantly replaced with 0. This is how you can analyze this on paper. Computer, however, would wirst calculate m(4) before calculating m(2) and adding the results in the first line - this happens because of order of poerations within the recursive functions.
System.out.println(7 + 5 + " ");
This prints out 12, but in another order
System.out.println(" " + 5 + 7);
it prints out 57. Why is this?
Firstly, this has nothing to do with System.out.println. You'll see exactly the same effect if you use:
String x = 7 + 5 + "";
String y = " " + 5 + 7;
It's got everything to do with associativity. The + operator is left-associative, so the above two statements are equivalent to:
String x = (7 + 5) + "";
String y = (" " + 5) + 7;
Now look at the results of the first expression in each case: 7 + 5 is just 12, as int... whereas " " + 5 is "5" (a string).
Or to break it down further:
int x1 = 7 + 5; // 12 (integer addition)
String x = x1 + ""; // "12" (conversion to string, then string concatenation)
String y1 = " " + 5; // "5" (conversion to string, then string concatenation)
String y = y1 + 7; // "57" (conversion to string, then string concatenation)
Justification: JLS 15.18 (additive operators):
The additive operators have the same precedence and are syntactically left-associative (they group left-to-right).
Easy. System.out.println(7 + 5 + " ") is viewed as a mathematical equation, whereas System.out.println(" " + 5 + 7) whereas having the space beforehand, Java (I'm assuming) views it as a string. Thus 'concatenating' the two.
I was doing java assignment and I ran into this code.
int x=3, y=5;
System.out.println(x + y + " = " + y + x);
and the output is "8=53". Why does the first x+y gets evaluated and the last y and x expression gets printed? Left me wondering. Thanx in advance guys.
Remember that in Java, an operator (like +) can be overloaded. That means it will do different things, depending on its operands. For +, there are (at least) two choices: integer addition and string concatenation.
Which overload is chosen depends more so on the left-hand-side operand. Also, string concatenation with a non-string operand can cause automatic conversion to a string.
The whole thing will be evaluated left-to-right like this:
x + y + " = " + y + x
3 + 5 + " = " + 3 + 5 // 3+5 chooses the integer addition overload of +
8 + " = " + 3 + 5 // 8 + " = " chooses string concatenation
"8" + " = " + 3 + 5 // so 8 is converted to "8" first
"8 = " + 3 + 5 // and then concatenated with " = "
"8 = " + "3" + 5 // now 3 is converted to "3"
"8 = 3" + 5 // and concatenated with "8 ="
"8 = 3" + "5" // finally 5 is converted to "5"
"8 = 35" // and concatenated with the rest
FWIW, it's ambiguity like this that leads me to dislike implicit conversions1.
1 - In C#. I love it in Python :-)
output is "8=53". Why does the first x+y gets evaluated and the last
y and x expression gets printed?
Because first x + y are not appended with a string so integer calculation is done. Second ones are appended to a string because of " = " + and hence they are printed as individual values.
To prove this just do:
System.out.println("" + x + y + " = " + x + y);
and the output will be:
35 = 35
The first part is getting interpreted as integer addition, but in the second part (as you have introduced a string) it is getting interpreted and string concatenation.
Assuming you want 8 = 8
try
System.out.println(x + y + " = " + (y + x));
if you want 3 + 5 = 5 + 3
then I would use String.format as
in
System.out.println (String.format ("%d + %d = %d + %d", x, y, y, x));
The reason the output is "8 = 53" is because:
x + y + " = " + y + x
Is calculated from left to right so, if we break it down piece by piece:
x + y = 8
8 + " = " = "8 = "
"8 = " + y = "8 = 5"
"8 = 5" + x = "8 = 53"
That is how the compiler gets your answer :)
The first + is between two numbers so the result is eight. The 2nd have strings on either side of them so numbers get converted to strings and concatenated together. The plus operator binds tightest to the left, and gets evaluated left to right. If you wanted the last addition to be numerical then the expression should be in brackets ( ).
I'm dealing with a problem in my Go Game project.
I have a board (goban), represented by 2D Array of chars. Before every next move, I would like to check for 'bubbles' in the array. Bubble should be an 4-connected area of identical chars surrounded in 4 directions by another group of specific identical chars.
If this 'bubble' exists, the characters inside should be replaced by some others. But there could be more areas and not all of them are enclosed.
For example, I have this board:
1 2 3 4 5 6 7 8 9 10 11 12 13
- - - - - - - - - - - - - - -
A | + + + + + + + + + + + + + |
B | + + + + + + + + + + + + + |
C | + + + + + + + + + + + + + |
D | + + + + + + + + + + + + + |
E | + + + + + + + + + + + + + |
F | + + O O O O + + + + + + + |
G | + O X X X X O + + + + + + |
H | + + O O X X O + + + + + + |
I | + + + + O X X O + + + + + |
J | + + + + O X O + + + + + + |
K | + + + + + O + + + + + + + |
L | + + + + + + + + + + + + + |
M | + + + + + + + + + + + + + |
- - - - - - - - - - - - - - -
And I would like to find the bubble of Xs, count them and replace them with 'Z's.
I've googled it and I think that some Connected-component labeling algorithm or FloodFill can do the job, but I'm not sure how to implement it. Is this the way or something less complicated could solve it?
Thank you
Edit:
I tried to find some pattern which could find the areas of specific character and count their liberties, but it always failed when the location was multilayered.
Changing the data structure might be the solution, but if it is possible, I would like to do it as it is now.
My current solution idea:
public void solve(){
if (boardContainsEnclosedAreas(goban, onMovePlayerStone, oppositePlayerStone){
onMovePlayerScore += countElementsInAreaAndReplaceThem(onMovePlayerStone, 'Z');
}
}
public boolean boardContainsEnclosedAreas(char[][] playingBoard, char searchedChar, char surroundingChar){
// this method should find the bubble in the playingBoard array
}
public int countElementsInAreaAndReplaceThem(char searchedChar, char replacingChar){
// the method should go through the bubble and replace all inner chars
// returns amount of replaced chars
}
You can do that with a recursive method, indeed using the FloodFill theory.
Basically, run through your grid, and each time you find an X, replace it with a Z, as well as its 4 neighbours (if applicable). But the trick is: instead of just replacing them and having to loop again each time, call the same (calling) method again to do it. The recursivity will do the rest.
Here is a (quickly done) pseudo-code version of it:
(assuming your grid is indexed from 0 to xmax, from 0 to ymax)
int numberOfBubbles = 0;
for (x = 0 to xmax) {
for (y = 0 to ymax) {
if (getCharAt(x, y) == "X") { // this if is needed because you want to count the bubbles. If not, you could just do handleBubble(x, y);
numberOfBubbles++;
handleBubble(x, y);
}
}
}
// Recursive method
void handleBubble(int x, int y) {
if (getCharAt(x, y) != "X") {
return; // exit condition
}
getCharAt(x, y) = "Z";
if (x > 0) handleBubble(x-1, y);
if (x < xmax) handleBubble(x+1, y);
if (y > 0) handleBubble(x, y-1);
if (y < ymax) handleBubble(x, y+1);
}
As far as I know, this is the only solution for this problem, which works whatever weird shape your bubble is. The complexity is not bad either.
This can be optimised further, as it currently checks for chars that are obviously not containing an X any more (because they've just been replaced with Z). This is left as an exercise to the reader :)
(NB: The minesweeper game, among other, is based on that solution)
Here's an algorithm (in pseudocode) that I've used for similar image analysis needs:
regions = Collection<Set<Point>>
foreach (Point p : allBoardLocations)
if (charAtLocation(p) != 'X') continue
foundInRegion = false
for (Set<Point> s : regions)
if (s.contains(p))
foundInRegion=true
break;
if (!foundInRegion)
newRegion = new Set<Point>()
stack = new Stack<Point>()
stack.push(p)
while (!stack.empty())
foreach (Point n : neighboringPoints(stack.pop()))
if (charAtLocation(n) == 'X')
if (!newRegion.contains(n))
newRegion.add(n);
stack.push(n);
Bascially, you maintain a collection of sets of points where each set represents a "bubble" of contiguous points on the board. Scan each location on the board and if it's an 'X' and it is not already in a region then create a new region and a stack containing the location and while there is any item on the stack, visit its neighbors searching for unvisited 'X's, adding them to the new region and stack as discovered.
At the end the you'll have a collection of sets of points, each representing a "bubble".