So I'm having a little trouble with the final part of my assignment on recursion. The method needs to use recursion to return a string that is formed from "weaving" together two strings taken in as parameters. For example:
weave("aaaa", "bbbb") // should return the string "abababab"
weave("hello", "world") // should return the string "hweolrllod"
weave("recurse", "NOW") // should return the string "rNeOcWurse"
Note that the extra characters from the first string—the characters in "urse"—come after the characters that have been woven together.
The important (and annoying) thing is that I'm not allowed to use any iteration loops (for, while, do while).
Here is my code thus far:
public static String weave(String str1, String str2)
{
String word = str1 + str2;
if(str1 == null || str1.equals("") || str2 == null || str2.equals(""))
{
return word;
}
String word1 = weave(str1.substring(0, str1.length() - 1), str2.substring(0, str2.length() - 1));
System.out.println(word1);
return word;
}
For (Hello, World), my output is:
HW
HeWo
HelWor
HellWorl
HelloWorld
Obviously my characters aren't weaving, so I'm not sure what to do! Also, as stated above, the method should do not printing. I just added in the println statement as a test to see where my program was at.
I think something like the following might work.
public String weave(String str1, String str2)
{
if(str1.isEmpty() || str2.isEmpty()) {
return str1 + str2;
}
return str1.substring(0, 1) + str2.substring(0, 1) + weave(str1.substring(1), str2.substring(1));
}
The idea is pretty simple: you only need to pop the first character from both input strings and concatenate both characters and the returned value from calling the function recursively with the stripped input strings until one of the input strings is empty in such case you should merely return the non-empty string.
weave("abcdef", "12"): "a" + "1" + weave("bcdef", "2")
|
+- weave("bcdef", "2"): "b" + "2" + weave("cdef", "")
|
+- weave("cdef", ""): "cdef"
Resulting in:
weave("abcdef", "12"): "a" + "1" + "b" + "2" + "cdef": "a1b2cdef"
The problem with your code is:
String word = str1 + str2;
//...
return word;
No matter how the recursive call, at the end it just return the result from the first method call when you pass in "hello", "world".
String word = str1 + str2; //hello + world
//... other things and the recursive call doesn't matter
//return word; //return the first word variable which is helloworld
Related
everyone. I am very new to java so I hope my question does not sound dumb, but I am encountering trouble with an online exercise.
Basically, I need to write a recursive method, in java, called reverse that accepts a String parameter and returns a string concatenated with its reverse. So, for example, if the string was "Java" it returns it as "JavaavaJ"
I worked out most of the code, but cannot figure out how to combine the two in the return method.
public static String reverse(String str) {
if ((null == str) || (str.length() <= 1)) {
return str;
}
return reverse(str.substring(1)) + str.charAt(0);
}
You'll want to prepend the string you're reversing with the first character as well. Something like this should work:
public String reverse(String str) {
if (null == str) {
return null;
}
if (str.length() <= 1) {
return str + str;
}
return str.charAt(0) + reverse(str.substring(1)) + str.charAt(0);
}
Without prepending the first character, the recursion would just produce a reverse of the string. Similarly, appending the whole string twice when you are at the last character is needed as well (e.g., "a" reversed using this logic seems like it should produce "aa")
In total there are 51 words in the string however my code returns to me 56 words which I don't understand why.
public class PartB
{
// instance variables - replace the example below with your own
public static int countWords(String str)
{
// Check if the string is null
// or empty then return zero
if (str == null || str.isEmpty())
return 0;
// Splitting the string around
// matches of the given regular
// expression
String[] words = str.split("[\\s+,'/]");
// Return number of words
// in the given string
return words.length;
}
public static void main(String args[])
{
// Given String str
String str = "Sing, sing a song/Let the world sing along/" +
"Sing of love there could be/Sing for you and for me/" +
"Sing, sing a song/Make it simple to last/" +
"Your whole life long/Don't worry that it's not/" +
"Good enough for anyone/Else to hear/" +
"Just sing, sing a song";
// Print the result
System.out.println("No of words : " +
countWords(str));
}
}
There are two errors in your [\s+,'/] regex:
The + plus should be outside the [ ] character class.
Reason: Without the +, text "Sing, sing" would have 2 separators, a comma and a space, with an empty token between them, and you're counting that empty token.
The ' apostrophe should not be there.
Reason: With the ', text Don't would be 2 words, not 1.
So the regex should be: [\s,/]+
Changing nothing but the split call to split("[\\s,/]+"), the result becomes:
No of words : 51
Why does this code work?
public static String reverse(String a) {
if(a.length() == 0) {
return a;
} else {
return reverse(a.substring(1)) + a.charAt(0);
}
}
And this doesn't?:
public static String reverse(String a) {
if(a.length() == 0) {
return a;
} else {
return reverse(a.substring(1)) + a.substring(0);
}
}
Also, how does the recursion work in case 1, what does adding a.charAt(0) do? And how does this method ever reach the base case?
Because a.charAt(0) returns the first character, while a.substring(0) returns the entire String (from index 0). Change
return reverse(a.substring(1)) + a.substring(0);
to something like
return reverse(a.substring(1)) + a.substring(0, 1);
And it will work as expected.
To get better understanding about recursive code, you can try to print the state for each method calls, e.g.
public static String reverse(String a) {
System.out.println("Calling reverse(\"" + a + "\")");
if(a.length() == 0) {
System.out.println("Base case encountered for string : \"" + a + "\"");
return a;
} else {
String b = reverse(a.substring(1));
String c = a.charAt(0);
System.out.println(reverse(\"" + a + "\") returning \"" + b + "\" + \"" + c + "\"");
return b + c;
}
}
When you try to call reverse("xyz"), then you can see the following text printed within standard output:
Calling reverse("xyz")
Calling reverse("yz")
Calling reverse("z")
Calling reverse("")
Base case encountered for string : ""
reverse("z") returning "" + "z" = "z"
reverse("yz") returning "z" + "y" = "zy"
reverse("xyz") returning "zy" + "x" = "zyx"
We can see several things:
You reduce the string recursively until reaching the base case where the string is empty (has zero length).
For each non base case, you split the string into two segment, namely b and c. Then you return reverse(b) + c.
Firstly, 'a.substring()' returns the substring starting from the index given as parameter, so while using 'a.substring(1)' as the parameter of the recursive method the first character always gets skipped and the length of the string given as parameter decreases gradually. Once no character remains it reaches the base case.
Secondly, 'a.charAt()' returns the character exists at the index of the string given as parameter. So 'a.charAt(0)' returns the first index of the string 'a' which is given as the parameter of the recursive method.
Finally, the first code works because each time it sends the entire string except the first character and it includes that first character at the end of the string that is returned reversed. So at the end, the entire string gets reversed.
On the other hand, the second code includes the entire substring starting from the first index of the string given as its parameter instead of the first character.
To make the code work you can either use 'charAt(0)' like the first code -
return reverse(a.substring(1)) + a.charAt(0);
or you can use 'a.substring(0, 1)' which considers only the first character as the substring and returns it -
return reverse(a.substring(1)) + a.substring(0, 1);
I believe that I have a decent understanding of recursion (factorial etc), however in the following example in reversing a string I do not understand the line. Can someone please explain what it does?
return reverseString(str.substring(1)) + str.charAt(0);
Full Code from method:
public static String reverseString(String str){
if(str.length()<2){
System.out.println("reached Base case");
return str;
}
return reverseString(str.substring(1)) + str.charAt(0);
}
The call substring(1) takes the first character off of the string. That is fed into the recursive call, which reverse all but the last character. Then, the first character is appended, completing the reversal.
Example:
reverseString("abc") =>
reverseString("bc") + 'a' =>
(reverseString("c") + 'b') + 'a' =>
("c" + 'b') + 'a' =>
"cb" + 'a' =>
"cba"
It takes everything after the first character and calls the recursive function. The first character is put at the end of the string. This results in a reversal.
return reverse(Everything after the first) + the first
return reverseString(str.substring(1)) + str.charAt(0);
For example, the String is HelloWorld
Then "HelloWorld".substring(1) returns "elloWorld"
and "HelloWorld".charAt(0) returns "H"
You take the first letter and add it to the end od the string. But before, you do it again with the first part. In the end, this algorithm reverses the string.
Let's take this string:
str = "Reverse";
The value of str.substring(1) is "everse".
The value of str.charAt(0) is "R".
I think you can take it from there if you understand recursion.
It inefficiently reverses the string by placing each successive sub-string on the stack until it reaches a length less then 2; it then reverses the characters by popping those results off the stack and appending the first character to the sub-string. It is inefficient because Java includes the StringBuilder class and that has a reverse method.
Try to think of reversing a string in this manner:
//reverse of a string can be expressed as the last character
//plus the reverse of everything remaining. For example, if we had
//"food", you would have "d" + reverse("foo"), which is "d" + "oof"
//which gives you "doof". So:
reverse(str) = str[str.length - 1] + reverse(str[0:str.length - 2]);
reverse(str[0]) = str[0] //reverse of a 1 character string is the character itself
So apply this to the string abcd:
You have:
reverse("abcd") = "d" + reverse("abc")
reverse("abc") = "c" + reverse("ab")
reverse("ab") = "b" + reverse("a")
reverse("a") = "a";
Now when you substitute you have:
reverse("ab") = "b" + "a" = "ba"
reverse("abc") = "c" + "ba" = "cba"
reverse("abcd") = "d" + "cba" = "dcba"
Think about how you can write code that mimics this behavior.
I have two simple examples to support my question. I can't figure out why (1) is working while (2) isn't. In my opinion I use them the same way.
(1)
public String frontBack(String str) {
if (str.length() <= 1) return str;
String mid = str.substring(1, str.length()-1);
// last + mid + first
return str.charAt(str.length()-1) + mid + str.charAt(0);
}
(2)
public String front22(String str) {
str = "test";
return str.charAt(0);
}
With the second one, I get an type mismatch error that says: Cannot convert from char to string. When I try to find an answer on internet I see the str declared as a var type in all examples. But it works with the first example.
What am I missing?
In the first example you return a String. In the second you (try to) return a char.
Since you do string concatenation in the first example the result of the expression is a string.
To return the first character as a String:
return str.substring(0,1);
You can fix it by typing
return "" + str.charAt(0);
Somehow that forces the character into a string.