Confusion with string recursion base case (Java) - java

So for homework this weekend we're learning about recursion so that means the dreaded string reversal with recursion problems. I have a simple piece of code that is correctly performing the recursion (according to the debug mode in eclipse) but since (?? this is where I'm confused) I'm calling it from a a different area of the program, it just keeps going on infinitely until it crashes or overflows or whatever it's called.
public static void main(String[] args)
{
System.out.println(reversePrint("Hello"));
}
public static String reversePrint(String s)
{
if (s.length() <= 1)
return s;
return reversePrint(s.substring(1) + s.charAt(0));
}
I've been trying to Google-fu my way to figuring out why but I just can't, most sites explain recursion with pretty much the code I've written for the actual reversal of the string, but none seem to deal with any problems with getting it to print. I honestly don't know what I'm overlooking, been at this for a few hours, feels like I'm banging my head against a wall.

Try this:
public static String reversePrint(String s) {
if (s.length() <= 1)
return s;
return reversePrint(s.substring(1)) + s.charAt(0);
}
Here was the problem in your code:
reversePrint(s.substring(1) + s.charAt(0))
You kept calling the reversePrint() method with a string of the same size - and as you know, a recursion must "reduce" the problem at each step until it hits the base case, or else it will never end.

If you use reversePrint(s.substring(1) + s.charAt(0)), you always pass the full string into reversePrint.
You should make sure that the string passed to reversePrint is always getting smaller:
reversePrint(s.substring(1)) + s.charAt(0);
Notice how what I pass to reversePrint is one character smaller than s.

I Am Also Studying Recursion In Class Now, and The important Part Is To Remember Base Case And Proper Method Calls That Iterate Logically. Simple Syntax Errors Like Parentheses:
return reversePrint(s.substring(1) + s.charAt(0));
Won't Make Or Break It. Learning The Logic And Concept Of Recursion Is Much More Important. Stay Positive!

Related

How to unreverse this method in java?

I wrote some code:
public class digitShow {
public static void main(String[] args) {
System.out.println(digitShow(98198187));
}
public static int digitShow(int num) {
if (num != 0) {
System.out.print(num % 10);
return digitShow(num / 10);
} else
return num;
}
}
The code works perfectly fine, but I am trying to make it so instead of printing the numbers in reverse order one by one, the output rather would display each digit one by one in the order that they are entered in the parameter.
So in this case:
1
2
3
4
I've been trying to un-reverse it, but I've had no luck.
Ok, some people on comments are suggesting using arrays or similar. This is correct, however this seems like a question made by someone who is learning recursion (and, as a teacher, I can smell a homework question here).
I will not post the answer because I'd be doing your homework for you and we need good programmers in this world. If I (or anyone else) do your homework you'll never understand the basic concepts of programming, and never becoming a good programmer.
Now, building on top of smac89's comment:
Your code to reverse has an issue: it prints 0 after it reverses the digits. Why? because you are returning an integer and then printing it in your main function but you are not really using the return value anywhere else.
Try calling your method without the System.out.println in main and see what happens.
So, basically, evaluate if you really need to return an integer and, if you don't, you can now evaluate how you are calling the recursion (again, read smac89's comment).
I wish you the best in your studies!
You need to reduce the number by successive divisions first. Then process the values as they are unwound from the stack. This will print the most significant to least significant digit. Then return the starting number.
public static int digitShow(int num) {
if (num > 10) {
digitShow(num/10);
}
System.out.println(num%10);
return num; // returns the starting number.
}
prints
9
8
1
9
8
1
8
7
98198187

Why does the following recursive program give the following output

I am trying to understand the java recursion from beginning. I came through a following example
public static void main(String[] args) {
threeWays(1,4);
}
public static void threeWays(int id,int n) {
if (n >= 0) {
System.out.println(id + "=" + n);
threeWays(id+1,n-1);
threeWays(id+1,n-2);
}
}
gives the output
1=4
2=3
3=2
4=1
5=0
4=0
3=1
4=0
2=2
3=1
4=0
3=0
I understand up to 5=0 but why does the program run beyond that? Why doesn't it stop once n becomes -1? Where does 4=0 come from? I don't even know what to call this phenomenon so the question might look vague. Any help would be appreciated.
threeWays(id+1,n-1); // when this returns,
threeWays(id+1,n-2); // ... the program still does this
You are recursively calling the function twice. So after it reaches the end for the first call, it unwinds the stack a little and then goes into the second recursion.
And from that second call, it branches out twice again at each layer.
If this is confusing, it could be illustrative to step through the program in a debugger. You can see each frame in the call stack there, including the local variables and which line of code they are in right now.

How does loop in recursion work?

I'm learning recursion now, and I thought I quite understood how recursion works, and then I saw this code, and my head is about to explode.
I know this simple recursion works like
public void recursivePrint(int number){
if(number == 0{
return;
}
System.out.println(number + " ");
recursivePrint(number - 1);
}
If the parameter "number"'s value is 2.
public void recursivePrint(2){
if(number == 0{
return;
}
System.out.print(2 + " ");
recursivePrint(2 - 1);
}
public void recursivePrint(1){
if(number == 0{
return;
}
System.out.print(1 + " ");
recursivePrint(1 - 1);
}
and then stops because it meets its base case.
What about this print all permutations of a string function?
private void permute(String str, int l, int r)
{
if (l == r)
System.out.println(str);
else
{
for (int i = l; i <= r; i++)
{
str = swap(str,l,i);
permute(str, l+1, r);
str = swap(str,l,i);
}
}
}
There is a recursive call inside a for loop. If the input value is "ab", how does this recursion function work? Can you explain as I wrote above?
I got this code form geeksforgeeks, and there's a video for this, but I can't understand this since I don't know how loop works in recursion.
Using permute function you are generating strings where lth char is being replaced by one of the char following it. With the for loop inside it, you are touching onto each of those following characters one at a time.
With several call to permute, you are able to advance till the end position of the string, and that end is checked by if (l == r)
Take the case of abc.
abc
/ | \
Level 1 a(bc) b(ac) c(ba) (Here three new call to permute are made out of permute with l=1)
Goes on...
FYI, permutation isn't that simple to understand if you are new to recursion or programming. For easy understanding use pen-paper.
Recursion occurs when a method calls itself. Such a method is called recursive. A recursive method may be more concise than an equivalent non-recursive approach. However, for deep recursion, sometimes an iterative solution can consume less of a thread's finite stack space.
What is recursion:
In general, recursion is when a function invokes itself, either directly or indirectly. For example:
// This method calls itself "infinitely"
public void useless() {
useless(); // method calls itself (directly)
}
Conditions for applying recursion to a problem:
There are two preconditions for using recursive functions to solving a specific problem:
There must be a base condition for the problem, which will be the endpoint for the recursion. When a
recursive function reaches the base condition, it makes no further (deeper) recursive calls.
Each level of recursion should be attempting a smaller problem. The recursive function thus divides the problem into smaller and smaller parts. Assuming that the problem is finite, this will ensure that the recursion terminates.
In Java there is a third precondition: it should not be necessary to recurse too deeply to solve the problem;
The following function calculates factorials using recursion. Notice how the method factorial calls itself within the function. Each time it calls itself, it reduces the parameter n by 1. When n reaches 1 (the base condition) the function will recurse no deeper.
public int factorial(int n) {
if (n <= 1) { // the base condition
return 1;
} else {
return n * factorial(n - 1);
}
}

Java Recursion - Did I do this right? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
My job is to write a recursive version to this method. From what I understand Recursion is starting with a base call (if something then return) followed by an else which unwinds back to the original base. Like starting with a deck, adding on to the deck then removing cards from the deck until you are back to the original deck.
With that in mind here it is.
public static long fact(int n)
{
long result = 1;
while(n > 0)
{
result = result * n;
n = n - 1;
}
return result;
}
//my recursive version:
public static void recFact(int n)
{
if(n==0)
{
return n; // ir 0 it really doesn't matter right?
}
else
{
return recFact(n-1);
}
}
This is just an example test problem for an exam I have coming up, just want to make sure I have a handle on recursion. Did I do this right? If not what am I missing? please no answers in questions, just tell me what I did wrong and maybe some advice on better ways to understand it.
Thanks.
No, this recursive solution is not correct.
For every positive n, you're just return rectFact(n-1), which will recourse until you reach 0, at which point it will return. In other words, your function will always return 0. You're missing the part where you multiply the current n with rectFact(n-1). Additionally, note that 0! is 1, not 0:
public static int recFact(int n)
{
if(n==0)
{
return 1;
}
else
{
return n * recFact(n-1);
}
}
And finally, since the if clause returns, the else is somewhat redundant. This doesn't affect the method's correctness, of course, but IMHO the code looks cleaner without it:
public static int recFact(int n)
{
if(n==0)
{
return 1;
}
return n * recFact(n-1);
}
Your recursive version does no multiplication, and it will return zero for any input. So no, you didn't do it right.
But, the recursive version DOES recurse, so you have that going for you! To understand what's going wrong, walk through a very simple case.
Client calls recFact(3)
This will return to client recFact(2)
Which will return to above recFact(1)
Which will return to above recFact(0)
Which will return to above 0.
There are two major things going wrong:
Your base case is wrong (zero is too low)
You're not doing any multiplication
Good attitude about not wanting the solution handed to you! Hopefully these pointers wil help you figure it out.
EDIT: Apparently I misunderstood your grammar and you did want the solution.
Any recursive function needs three things:
The terminating condition: This tells the function when to stop calling itself. This is very important to avoid infinite recursion and avoid stack overflow exceptions.
The actual processing: You need to run the actual processing within each function. In your non recursive case, this was result = result * n. This is missing from your recursive version!
A collector/agggregator variable: You need some way to store the partial result of the recursive calls below you. So you need some way to return the result of recFact so that you can include it in processing higher up in the call chain. Note that you say return recFact(n - 1) but in the definition recFact returns void. That should probably be an int.
Based from your example you are missing the return type of your recFact which is int
Also recFact will always return 0 because you are not multiplying n each time to the recursion call of the method.
There are two ways to write recursive routines. One is the "standard" way that we all are taught. This is one entry point that must first check to see if the recursive chain is at an end (the escape clause). If so, it returns the "end of chain" value and ends the recursion. If not at the end, it performs whatever calculation it needs to get a partial value according to the level and then calls itself passing a value the next increment closer to the end of the chain.
private final int InitialValue = 15;
System.out.println( "Fact(" + InitialValue + ") = " + recFact( InitialValue ) );
public int recFact( int val ){
if( val < 2 ){
return 1;
}
else{
return recFact( val - 1 ) * val; // recursive call
}
}
//Output: "Fact(15) = 2004310016"
In regular recursion, a partial answer is maintained at each level which is used to supplement the answer from the next level. In the code above, the partial answer is val. When first called, this value is 15. It takes this value and multiplies it by the answer from Fact(14) to supply the complete answer to Fact(15). Fact(14) got its answer by multiplying 14 by the answer it got from Fact(13) and so on.
There is another type of recursion called tail recursion. This differs in that partial answers are passed to the next level instead of maintained at each level. This sounds complicated but in actuality, make the recursion process much simpler. Another difference is that there are two routines, one is non recursive and sets up the recursive routine. This is to maintain the standard API to users who only want to see (and should only have to see)
answer = routine( parameter );
The non-recursive routines provides this. It is also a convenient place to put one-time code such as error checking. Notice in the standard routine above, if the user passed in -15 instead of 15, the routine could bomb out. That means that in production code, such a test must be made. But this test will be performed every time the routine is entered which means the test will be made needlessly for all but the very first time. Also, as this must return an integer value, it cannot handle an initial value greater than 19 as that will result in a value that will overflow the 32-bit integer container.
public static final int MaxFactorialSeq = 20;
private final int InitialValue = 15;
System.out.println( "Fact(" + InitialValue + ") = " + recFact( InitialValue ) );
public int recFact( int value ){
if( value < 0 || value > MaxFactorialSeq ){
throw new IllegalArgumentException(
"Factorial sequence value " + value + " is out of range." );
}
return recFact( value, 1 ); // initial invocation
}
private int recFact( int val, int acc ){
if( val < 2 ){
return acc;
}
else{
return recFact( val - 1, acc * val ); // recursive call
}
}
//Output: "Fact(15) = 2004310016"
Notice the public entry point contains range checking code. This is executed only once and the recursive routine does not have to make this check. It then calls the recursive version with an initial "seed" of 1.
The recursive routine, as before, checks to see if it is at the end of the chain. If so, it returns, not 1 as before, but the accumulator which at this point has the complete answer. The call chain then just rewinds back to the initial entry point in the non-recursive routine. There are no further calculations to be made as the answer is calculated on the way down rather than on the way up.
If you walk though it, the answer with standard recursion was reached by the sequence 15*14*13*...*2*1. With tail recursion, the answer was reached by the sequence 1*15*14*...*3*2. The final answer is, of course, the same. However, in my test with an initial value of 15, the standard recursion method took an average of 0.044 msecs and the tail recursion method took an average of 0.030 msecs. However, almost all that time difference is accounted for by the fact that I have the bounds checking in my standard recursion routine. Without it, the timing is much closer (0.036 to 0.030) but, of course, then you don't have error checking.
Not all recursive routines can use tail recursion. But then, not all recursive routines should be. It is a truism that any recursive function can be written using a loop. And generally should be. But a Factorial function like the ones above can never exceed 19 levels so they can be added to the lucky few.
The problem with recursion is that to understand recursion you must first understand recursion.
A recursive function is a function which calls itself, or calls a function which ultimately calls the first function again.
You have the recursion part right, since your function calls itself, and you have an "escape" clause so you don't get infinite recursion (a reason for the function not to call itself).
What you are lacking from your example though is the actual operation you are performing.
Also, instead of passing a counter, you need to pass your counter and the value you are multiplying, and then you need to return said multiplied value.
public static long recFact(int n, long val)
{
if(n==1)
{
return val;
}
else
{
return recFact(n-1, val) * n;
}
}

Javabat substring counting

public boolean catDog(String str)
{
int count = 0;
for (int i = 0; i < str.length(); i++)
{
String sub = str.substring(i, i+1);
if (sub.equals("cat") && sub.equals("dog"))
count++;
}
return count == 0;
}
There's my code for catDog, have been working on it for a while and just cannot find out what's wrong. Help would be much appreciated!*/
EDIT- I want to Return true if the string "cat" and "dog" appear the same number of times in the given string.
One problem is that this will never be true:
if (sub.equals("cat") && sub.equals("dog"))
&& means and. || means or.
However, another problem is that your code looks like your are flailing around randomly trying to get it to work. Everyone does this to some extent in their first programming class, but it's a bad habit. Try to come up with a clear mental picture of how to solve the problem before you write any code, then write the code, then verify that the code actually does what you think it should do and that your initial solution was correct.
EDIT: What I said goes double now that you've clarified what your function is supposed to do. Your approach to solving the problem is not correct, so you need to rethink how to solve the problem, not futz with the implementation.
Here's a critique since I don't believe in giving code for homework. But you have at least tried which is better than most of the clowns posting homework here.
you need two variables, one for storing cat occurrences, one for dog, or a way of telling the difference.
your substring isn't getting enough characters.
a string can never be both cat and dog, you need to check them independently and update the right count.
your return statement should return true if catcount is equal to dogcount, although your version would work if you stored the differences between cats and dogs.
Other than those, I'd be using string searches rather than checking every position but that may be your next assignment. The method you've chosen is perfectly adequate for CS101-type homework.
It should be reasonably easy to get yours working if you address the points I gave above. One thing you may want to try is inserting debugging statements at important places in your code such as:
System.out.println(
"i = " + Integer.toString (i) +
", sub = ["+sub+"]" +
", count = " + Integer.toString(count));
immediately before the closing brace of the for loop. This is invaluable in figuring out what your code is doing wrong.
Here's my ROT13 version if you run into too much trouble and want something to compare it to, but please don't use it without getting yours working first. That doesn't help you in the long run. And, it's almost certain that your educators are tracking StackOverflow to detect plagiarism anyway, so it wouldn't even help you in the short term.
Not that I really care, the more dumb coders in the employment pool, the better it is for me :-)
choyvp obbyrna pngQbt(Fgevat fge) {
vag qvssrerapr = 0;
sbe (vag v = 0; v < fge.yratgu() - 2; v++) {
Fgevat fho = fge.fhofgevat(v, v+3);
vs (fho.rdhnyf("png")) {
qvssrerapr++;
} ryfr {
vs (fho.rdhnyf("qbt")) {
qvssrerapr--;
}
}
}
erghea qvssrerapr == 0;
}
Another thing to note here is that substring in Java's built-in String class is exclusive on the upper bound.
That is, for String str = "abcdefg", str.substring( 0, 2 ) retrieves "ab" rather than "abc." To match 3 characters, you need to get the substring from i to i+3.
My code for do this:
public boolean catDog(String str) {
if ((new StringTokenizer(str, "cat")).countTokens() ==
(new StringTokenizer(str, "dog")).countTokens()) {
return true;
}
return false;
}
Hope this will help you
EDIT: Sorry this code will not work since you can have 2 tokens side by side in your string. Best if you use countMatches from StringUtils Apache commons library.
String sub = str.substring(i, i+1);
The above line is only getting a 2-character substring so instead of getting "cat" you'll get "ca" and it will never match. Fix this by changing 'i+1' to 'i+2'.
Edit: Now that you've clarified your question in the comments: You should have two counter variables, one to count the 'dog's and one to count the 'cat's. Then at the end return true if count_cats == count_dogs.

Categories

Resources