i need to write a method that takes in a string as a parameter and prints the word in mirrored form. for example, "hello" should return "helloolleh". I have to use recursion and cannot use for loops. Here is my code so far:
public static String printMirrored(String str)
{
if(str == null || str.equals(""))
{
return str;
}
else
{
return str + printMirrored(str.substring(1)) + str.charAt(0);
}
}
My output is "helloellollolooolleh" which obviously has some extra things in there. Any pointers would be greatly appreciated!
Try using str.charAt(0) at the beginning instead of str.
Wrote this real quick. Should do exactly what you want but if you have any questions please let me know.
String word = "hello";
System.out.println(reverseWord(word, word.length()));
public static String reverseWord(String word, int length) {
if(length == 0)
return word;
else
return reverseWord(word + word.charAt(length - 1), length - 1);
}
Recursion is about being the utmost lazy person delegating the rest to a recursive clone.
So on "Hello", take only the "H", get the mirrored result of "ello" and surround it on both ends with an "H".
use StringBuilder.reverse()
Related
I am trying to learn Java, and now I'm trying algorithms. So, I'm stucked on recursion. I have a code that I don't understand.
public static String reverseString(String text){
// base case
if (text.length() == 0) {
return text;
}
else {
// recursive call
return reverseString(text.substring(1)) + text.charAt(0);
}
}
public static void main(String[] args) {
String str = new String("howdy");
// calling recursive function
String reverse = reverseString(str);
System.out.println(reverse); // Prints: ydwoh
}
Problem is that for me recursive call in this code for me is:
for the first time it retuns owdyh,
second time wdyo and so on.
I can't understand how the string ydwoh borns. I suspect that somewhere chars concotanating in the right order, and stored somewhere, but where is this place I also don't know.
UPDATE
I tried it with paper, what I got:
first recursive call:
return value owdyh = "owdy" + "h"
second call:
return value wdyo = "wdy" + "o"
and so on
The difficulty is the processing after the call. The first letter is added to the end of the result of reverseString of the rest.
reverseString "howdy"
reverseString "owdy"
reverseString "wdy"
reverseString "dy"
reverseString "y"
reverseString ""
return ""
return "" + "y"
returns "y" + "d"
returns "yd" + "w"
returns "ydw" + "o"
returns "ydwo" + "h"
returns "ydwoh"
It is like a mathematical proof by induction:
The empty string is reversed (result empty string).
When the recursive call works on a smaller string,
placing the first char at the end, also reverses the string.
So reverseString works for all length of strings.
Thanks for the answers! They helped me to figure out my misunderstanding!
What I couldn't understand is where all the chars from the text.charAt(0) are stored! The trick is that they are stored in the stack without any links. It's LIFO(Last-In-First-Out) approach in work.
I currently have a method that is supposed to take two strings and then check if one string exists as a substring in other. It doesn't check both ways so the way in which I pass my strings to the method determines what string is looked for in the other.
Currently I am getting a stackoverflow error.
public boolean checkMatch(String text, String regex, int i){
int regexL = regex.length();
if(i == regexL){
return true;
}
System.out.println(text.charAt(i) + " " + regex.charAt(i));
if(text.charAt(i) == regex.charAt(i)){
return checkMatch(text, regex, i++);
}
else if(text.charAt(i) != regex.charAt(i)){
if(text.substring(1) == ""){
return false;
}
else if(text.substring(1) != ""){
return checkMatch(text.substring(1), regex, 0);
}
}
return false;
}
I am running a test using my first name as an example.
#Test public void test_52() {
assertEquals(true, checkMatch("Samual", "mu", 0));
}
the console looks like this after it overflows.
S m
a m
m m
m m
m m
etc
Where am I going wrong? Am I iterating wrong? The stack trace shows that it seems to be getting caught on this line.
return checkMatch(text, regex, i++);
But the defect point is rarely the point of failure. Sorry for the wall of text and code.
I don't know if the rest is correct, but here is one error: i++increments i after it was evaluated. You call your function with the same value every time. You probably mean ++i.
You have:
return checkMatch(text, regex, i++);
You mean:
return checkMatch(text, regex, ++i);
Or:
return checkMatch(text, regex, i + 1);
The problem with i++ there is post-increment evaluates to i before the increment, so you're just getting stuck without advancing i, and eventually the recursion overflows the stack.
Had you printed i in your debugging output, the problem may have been clearer.
You can just use the indexOf method:
System.out.println("Samual".indexOf("mu") > 0);
Output:
true
I'm using codingbat.com to get some java practice in. One of the String problems, 'withoutString' is as follows:
Given two strings, base and remove, return a version of the base string where all instances of the remove string have been removed (not case sensitive).
You may assume that the remove string is length 1 or more. Remove only non-overlapping instances, so with "xxx" removing "xx" leaves "x".
This problem can be found at: http://codingbat.com/prob/p192570
As you can see from the the dropbox-linked screenshot below, all of the runs pass except for three and a final one called "other tests." The thing is, even though they are marked as incorrect, my output matches exactly the expected output for the correct answer.
Here's a screenshot of my output:
And here's the code I'm using:
public String withoutString(String base, String remove) {
String result = "";
int i = 0;
for(; i < base.length()-remove.length();){
if(!(base.substring(i,i+remove.length()).equalsIgnoreCase(remove))){
result = result + base.substring(i,i+1);
i++;
}
else{
i = i + remove.length();
}
if(result.startsWith(" ")) result = result.substring(1);
if(result.endsWith(" ") && base.substring(i,i+1).equals(" ")) result = result.substring(0,result.length()-1);
}
if(base.length()-i <= remove.length() && !(base.substring(i).equalsIgnoreCase(remove))){
result = result + base.substring(i);
}
return result;
}
Your solution IS failing AND there is a display bug in coding bat.
The correct output should be:
withoutString("This is a FISH", "IS") -> "Th a FH"
Yours is:
withoutString("This is a FISH", "IS") -> "Th a FH"
Yours fails because it is removing spaces, but also, coding bat does not display the correct expected and run output string due to HTML removing extra spaces.
This recursive solution passes all tests:
public String withoutString(String base, String remove) {
int remIdx = base.toLowerCase().indexOf(remove.toLowerCase());
if (remIdx == -1)
return base;
return base.substring(0, remIdx ) +
withoutString(base.substring(remIdx + remove.length()) , remove);
}
Here is an example of an optimal iterative solution. It has more code than the recursive solution but is faster since far fewer function calls are made.
public String withoutString(String base, String remove) {
int remIdx = 0;
int remLen = remove.length();
remove = remove.toLowerCase();
while (true) {
remIdx = base.toLowerCase().indexOf(remove);
if (remIdx == -1)
break;
base = base.substring(0, remIdx) + base.substring(remIdx + remLen);
}
return base;
}
I just ran your code in an IDE. It compiles correctly and matches all tests shown on codingbat. There must be some bug with codingbat's test cases.
If you are curious, this problem can be solved with a single line of code:
public String withoutString(String base, String remove) {
return base.replaceAll("(?i)" + remove, ""); //String#replaceAll(String, String) with case insensitive regex.
}
Regex explaination:
The first argument taken by String#replaceAll(String, String) is what is known as a Regular Expression or "regex" for short.
Regex is a powerful tool to perform pattern matching within Strings. In this case, the regular expression being used is (assuming that remove is equal to IS):
(?i)IS
This particular expression has two parts: (?i) and IS.
IS matches the string "IS" exactly, nothing more, nothing less.
(?i) is simply a flag to tell the regex engine to ignore case.
With (?i)IS, all of: IS, Is, iS and is will be matched.
As an addition, this is (almost) equivalent to the regular expressions: (IS|Is|iS|is), (I|i)(S|s) and [Ii][Ss].
EDIT
Turns out that your output is not correct and is failing as expected. See: dansalmo's answer.
public String withoutString(String base, String remove) {
String temp = base.replaceAll(remove, "");
String temp2 = temp.replaceAll(remove.toLowerCase(), "");
return temp2.replaceAll(remove.toUpperCase(), "");
}
Please find below my solution
public String withoutString(String base, String remove) {
final int rLen=remove.length();
final int bLen=base.length();
String op="";
for(int i = 0; i < bLen;)
{
if(!(i + rLen > bLen) && base.substring(i, i + rLen).equalsIgnoreCase(remove))
{
i +=rLen;
continue;
}
op += base.substring(i, i + 1);
i++;
}
return op;
}
Something things go really weird on codingBat this is just one of them.
I am adding to a previous solution, but using a StringBuilder for better practice. Most credit goes to Anirudh.
public String withoutString(String base, String remove) {
//create a constant integer the size of remove.length();
final int rLen=remove.length();
//create a constant integer the size of base.length();
final int bLen=base.length();
//Create an empty string;
StringBuilder op = new StringBuilder();
//Create the for loop.
for(int i = 0; i < bLen;)
{
//if the remove string lenght we are looking for is not less than the base length
// and the base substring equals the remove string.
if(!(i + rLen > bLen) && base.substring(i, i + rLen).equalsIgnoreCase(remove))
{
//Increment by the remove length, and skip adding it to the string.
i +=rLen;
continue;
}
//else, we add the character at i to the string builder.
op.append(base.charAt(i));
//and increment by one.
i++;
}
//We return the string.
return op.toString();
}
Taylor's solution is the most efficient one, however I have another solution that is a naive one and it works.
public String withoutString(String base, String remove) {
String returnString = base;
while(returnString.toLowerCase().indexOf(remove.toLowerCase())!=-1){
int start = returnString.toLowerCase().indexOf(remove.toLowerCase());
int end = remove.length();
returnString = returnString.substring(0, start) + returnString.substring(start+end);
}
return returnString;
}
#Daemon
your code works. Thanks for the regex explanation. Though dansalmo pointed out that codingbat is displaying the intended output incorrectly, I through in some extra lines to your code to unnecessarily account for the double spaces with the following:
public String withoutString(String base, String remove){
String result = base.replaceAll("(?i)" + remove, "");
for(int i = 0; i < result.length()-1;){
if(result.substring(i,i+2).equals(" ")){
result = result.replace(result.substring(i,i+2), " ");
}
else i++;
}
if(result.startsWith(" ")) result = result.substring(1);
return result;
}
public String withoutString(String base, String remove){
return base.replace(remove,"");
}
Hey I could use a little bit of help to figure out why my program isn't working. The question is to make a program using recursion that figures if it the text given is a palindrome or not after all the punctuation and white spaces are removed. While the program so far compiles, it returns every value as false. We are only allowed to change the isSymmetrical method. I could use whatever help possible trying to figure out how to make this work. Thank you.
public class StringSymmetry {
public static boolean isSymmetrical(String inputText)
{
if(inputText.length() == 0 || inputText.length() ==1)
return true;
if(inputText.charAt(0) == inputText.charAt(inputText.length()-1))
return isSymmetrical(inputText.substring(1,inputText.length()-1));
return false;
}
public static void main(String[] args) {
String[] sampleData =
{ "Don't nod",
"Dogma: I am God",
"Too bad - I hid a boot",
"Rats live on no evil star",
"No trace; not one carton",
"Was it Eliot's toilet I saw?",
"Murder for a jar of red rum",
"May a moody baby doom a yam?",
"Go hang a salami; I'm a lasagna hog!",
"Name is Bond, James Bond"
};
for (String s : sampleData)
{
System.out.println("isSymmetrical (" + s + ") returns " + isSymmetrical(s));
}
}
}
The problem is that you didn't include any checks for case or punctuation and white space.
One way you could do it is something like this. The specifics depend on what you're allowed to use for the assignment, but you're probably intended to do something along these lines.
Also, note that toLowerCase is problematic if you have the default locale set to something unusual like Turkey. For proper robustness, you need to specify a locale, but this isn't something you'll have to worry about in a homework assignment.
public static boolean isSymmetrical(String inputText)
{
inputText = inputText.toLowerCase();
if(inputText.length() == 0 || inputText.length() ==1)
return true;
if(!Character.isLetter(inputText.charAt(0)))
return isSymmetrical(inputText.substring(1,inputText.length()));
if(!Character.isLetter(inputText.charAt(inputText.length()-1)))
return isSymmetrical(inputText.substring(0,inputText.length()-1));
if(inputText.charAt(0) == inputText.charAt(inputText.length()-1))
return isSymmetrical(inputText.substring(1,inputText.length()-1));
return false;
}
Check the following function:
public static boolean isPalindrome(String str, int x) {
if(x == 0) return true;
if(str.charAt(0) == str.charAt((str.length() - 1)))
return isPalindrome(str.substring(1, str.length() - 1), x - 1);
return false;
}
Explanation:
A recursive function with the following parameter's:
str - a String object which will be tested for symmetry.
x - Integer that represent's the recursive tester parameter and decides for how far you want to iterate and check for two sided symmetry.
The base case is set to zero and return's true when you finished the desired iteration number.
The second if-condition statement is used to check the corner's of the string that is given, and its return statement will recursively enter another testing loop with shorter corner's of the original String( . . . corner's will be shorter by one).
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Programming java to determine a symmetrical word
am new here, but I am having hard time figuring out how to write a code to determine an input of word and see if the first is matching with the end of the word. You may input abba and get answer it's evenly symmetric and aba is oddly symmetric.
Please show me how:(
Just two main things.
first I want to know if it's oddly or evenly amount of letter(number of letter divided by 2,if it's ending with 0.5, it's oddly symmetric, if is an integer it's evenly symmetric.
second I want to get (i.e 1=n,2=n-1,3=n-2...) position of the letter in the word to be the main idea of the execution.If there is a last letter in the oddly symmetric word, ignore the last remaining letter.
I appreciate any headstart or idea:) Thanks!
Thanks KDiTraglia, I made the code and compiled and here is what I put. I am not getting any further.
Reported problem:
Exception in thread "main" java.lang.Error: Unresolved compilation problems: reverse cannot be resolved or is not a field reverse cannot be resolved or is not a field Syntax error, insert ") Statement" to complete IfStatement
This is what i got from, KDiTraglia's help
public class WordSymmetric {
public static void main(String[] args) {
String word = "abccdccba";
if ( (word.length() % 2) == 1 ) {
System.out.println("They are oddly symmetric");
//odd
}
else {
System.out.println("They are evenly symmetric");
//even
}
int halfLength = word.length() / 2;
String firstHalf = word.substring(0, halfLength);
String secondHalf = word.substring(halfLength, word.length());
System.out.println(secondHalf.reverse());
if (firstHalf.equals(secondHalf.reverse()) {
System.out.println("They match");
//they match
}
} }
String does not have a reverse method. You could use the apache commons lang library for this purpose:
http://commons.apache.org/lang/api-release/org/apache/commons/lang3/StringUtils.html#reverse%28java.lang.String%29
The reverse() approach is very clean and readable. Unfortunately there is no reverse() method for Strings. So you would either have to take an external library (StringUtils from the appache common lang3 library has a reverse method) or code it yourself.
public static String reverse(String inputString) {
StringBuilder reverseString = new StringBuilder();
for(int i = inputString.length(); i > 0; --i) {
char result = inputString.charAt(i-1);
reverseString.append(result);
}
return reverseString.toString();
}
(This only works for characters that can fit into a char. So if you need something more general, you would have to expand it.)
Then you can just have a method like this:
enum ePalindromResult { NO_PALINDROM, PALINDROM_ODD, PALINDROM_EVEN };
public static ePalindromResult checkForPalindrom(String inputStr) {
// this uses the org.apache.commons.lang3.StringUtils class:
if (inputStr.equals(StringUtils.reverse(inputStr)) {
if (inputStr.length % 2 == 0) return PALINDROM_EVEN;
else return PALINDROM_ODD;
} else return NO_PALINDROM;
}
System.out.println(secondHalf.reverse());
There is no reverse() method defined fro String
I would probably loop over word from index 0 to the half (word.length() / 2) and compare the character at the current index (word.charAt(i)) with the correspoding from the other half (word.charAt(word.length() - i).
This is just a rough draft, you probably need to think about the loop end index, depending on oddly or evenly symmetry.
You can adapt this :
final char[] word = "abccdccba".toCharArray(); // work also with "abccccba"
final int t = word.length;
boolean ok = true;
for (int i = t / 2; i > 0; i--) {
if (word[i - 1] != word[t - i]) {
ok = false;
break;
}
System.out.println(word[i - 1] + "\t" + word[word.length - i]);
}
System.out.println(ok);
Console :
c c
c c
b b
a a
true
Use class StringBuffer instead of String