Convert String to Reverse String Using Recursion in Java - java

Today I am trying to convert String to reverse String e.g(Cat Is Running into Running Is Cat) word by word not Character
public class ReverseString_ {
public static void reverse(String str) {
String[] a = str.split(" ");
for (int i = a.length - 1; i >= 0; i--) {
System.out.println(a[i] + " ");
}
}
public static void main(String[] args) {
reverse("Cat Is Running");
}
}
The following output is shown:
Running Is Cat BUILD SUCCESSFUL (total time: 0 seconds)
I am trying to convert String into reverse String same as above but through Recursion method but it seems too confusing. and display more errors. Can someone please help me understanding it. Many thanks
public static String reverse_recursion(String str) {
if (str == null)
return null;
else {
String Arry[] = str.split(" ");
int n = Arry.length - 1;
System.out.println(Arry[n] + "");
return reverse_recursion(Arry[n - 1]);
}
}
public static void main(String[] args) {
reverse_recursion("Cat Is Running");
}
This code show following output:
Running
Is
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
This code do not print (0) index why? can someone help me to solve this error please

This solution might be helpful. The comments explain the code pretty much.
public static String reverse_recursion(String str) {
String[] arry = str.split(" ", 2); //Split into a maximum of 2 Strings
if (arry.length > 1) { //If there is more than 1 word in arry
//Return the reverse of the rest of the str (arry[1])
//and concatenate together with the first word (arry[0])
return reverse_recursion(arry[1]) + " " + arry[0];
}
return arry[0]; //If less than or equal to 1 word, just return that word
}

This should work:
public static String reverse(String s) {
int idx = s.indexOf(" ");
if (idx < 0) {
// no space char found, thus, s is just a single word, so return just s itself
return s;
} else {
// return at first the recursively reversed rest, followed by a space char and the first extracted word
return reverse(s.substring(idx + 1)) + " " + s.substring(0, idx);
}
}
public static void main(String[] args) {
System.out.println(reverse("Cat Is Running"));
}

You are sending the last element of the Array next time instead of the String without the previously printed String.
Replace your return statement with this it should work.
return reverse_recursion(n==0?null:str.substring(0,(str.length()-Arry[n].length())-1));

Related

Problem with infinitely looping text in a word generator

I'm making a Palindrome Generator. Basically the user inputs a word or sentence and the program outputs whether or not its a Palindrome, which is a word that is spelled the same forwards and backwards like "wow" or "racecar". My program works fine, however the output text will repeat itself like fifty times and I can't seem to figure out where the issue is without messing everything up. Help would be appreciated.
import javax.swing.JOptionPane;
public class palindromedectector {
public static void main(String[] args) {
String testStrings = "";
testStrings = JOptionPane.showInputDialog("Enter word: ");
for (int i = 0; i < testStrings.length(); i++)
{
System.out.print("\"" + testStrings + "\"");
if (isPalindrome(stripString(testStrings)))
System.out.println(" is a palindrome.");
else
System.out.println(" is not a palindrome.");
}
}
public static String stripString(String strip)
{
strip = strip.toUpperCase();
String stripped= "";
for (int i= 0; i< strip.length(); i++)
{
if (Character.isLetter(strip.charAt(i)))
stripped += strip.charAt(i);
}
return stripped;
}
public static boolean isPalindrome (String str)
{
boolean status = false;
if (str.length() <= 1)
status = true;
else if (str.charAt(0) == str.charAt(str.length()-1))
{
status = isPalindrome (str.substring(1, str.length()-1));
}
return status;
}
}
Main issue is that you run isPalindrome check for the same string in the loop, probably you wanted to run multiple checks
public static void main(String[] args) {
final int attempts = 5;
for (int i = 0; i < attempts; i++) {
String word = JOptionPane.showInputDialog("Enter word: ");
System.out.print("\"" + word + "\"");
if (isPalindrome(stripString(word))) {
System.out.println(" is a palindrome.");
} else {
System.out.println(" is not a palindrome.");
}
}
}
Also, the main functionality may be implemented in a shorter way:
// use regexp to get rid of non-letters
private static String stripString(String word) {
if (null == word || word.isEmpty()) {
return word;
}
return word.replaceAll("[^A-Za-z]", "").toUpperCase(); // remove all non-letters
}
// use Java Stream API to check letters using half of word length
private static boolean isPalindrome(String word) {
if (null == word) {
return false;
}
final int len = word.length();
if (len < 2) {
return true;
}
return IntStream.range(0, len/2)
.allMatch(i -> word.charAt(i) == word.charAt(len - 1 - i));
}
Basic problem: You are testing if the word is a palindrome testStrings.length() times, ie once for every letter in the word, rather than just once.
Remove the for loop in your main() method.

Java - Word Count True or False

i have a programming task using java...
public class CountWords{
public static void main(String[] args) {
String sentence = "Papa beauty lies in the eyes of beholder";
int wordcount = 0;
for(int i = 0; i < sentence.length()-1; i++) {
if(sentence.charAt(i) == ' ' && Character.isLetter(sentence.charAt(i+1)) && (i > 0)) {
wordcount++;
}
}
wordcount++;
System.out.println("Total number of words: " + wordcount);
System.out.println(sentence.startsWith("P"));
}}
My question is how can i define the String sentence based on this condition:
If more than 3 words, it will be True.
If less than 4 words, it becomes False.
Thankyou so much for helping..
If I understand your question correctly...
/* returns string array of tokens (words in the sentence) after splitting by space */
String[] tokens = sentence.split(" ");
if(tokens.length() > 3) {
// true
} else {
// fasle
}
Let's have a look at the steps we should take in order to achieve your goal in a easier way;
First , let's count the number of words in your input string via
count function
Call the function by sending our input sentence
Function returns number of words Check the number of words for any
condition you desire
Therefore your code will work better like this;
public class CountWords{
public static void main(String[] args) {
String sentence = "Papa beauty lies in the eyes of beholder";
private bool coniditon;
int wordcount = count(sentencte);
if (wordcount<4) {
condition=False;
}
else if (wordcount>3) {
condition=True;
}
System.out.println("Total number of words: " + wordcount);
System.out.println(sentence.startsWith("P"));
}
public static int count(String sentence){
if(sentence == null || sentence.isEmpty()){
return 0; }
String[] words = sentence.split("\\s+");
return words.length; }
}
}
Good luck!

Juint actual and expected the same but test fails

I am trying to learn Junit4 and do tests for some of my code. Basically, I am reversing the string and keeps the special symbols in place. During the testing, I found this fail that I can't understand.
My unit test fails although the actual value and expected are the same.
Thank you in advance!
Error:
org.junit.ComparisonFailure:
Expected :d1cba hgf!e
Actual :d1cba hgf!e
Code
public final class AnagramsMaker {
public static String reverseWord(String stringToReverse) {
char[] stringToChar = stringToReverse.toCharArray();
int arrayStart = 0;
int arrayEnd = stringToChar.length - 1;
while (arrayStart < arrayEnd) {
if (Character.isLetter(stringToChar[arrayStart]) && Character.isLetter(stringToChar[arrayEnd])) {
char temp = stringToChar[arrayStart];
stringToChar[arrayStart] = stringToChar[arrayEnd];
stringToChar[arrayEnd] = temp;
arrayStart++;
arrayEnd--;
}
else if (Character.isLetter(stringToChar[arrayStart]) && !Character.isLetter(stringToChar[arrayEnd])) {
arrayEnd--;
}
else if (!Character.isLetter(stringToChar[arrayStart]) && Character.isLetter(stringToChar[arrayEnd])) {
arrayStart++;
}
else {
arrayStart++;
arrayEnd--;
}
}
return String.valueOf(stringToChar);
}
public static String createAnagram(String inputString) {
String anagram = "";
String [] arr = inputString.split(" ");
for (String s : arr) {
anagram += reverseWord(s) + " ";
}
return anagram;
}
}
Junit:
#Test
public void createAnagram() {
assertEquals("d1cba hgf!e", AnagramsMaker.createAnagram("a1bcd efg!h"));
}
I tried reproducing it and got this: expected: <d1cba hgf!e> but was: <d1cba hgf!e >. Notice the extra space in the end.
There is a bug in createAnagram method. You are adding extra space after every string but for the last iteration, extra space is getting appended in the end that's causing this issue.
As fix, trim the value before returning as shown below
public static String createAnagram(String inputString) {
String anagram = "";
String [] arr = inputString.split(" ");
for (String s : arr) {
anagram += reverseWord(s) + " ";
}
return anagram.trim();
}
If you are comfortable with java8 & streams, better approach would be to use Collectors.joining method as shown below
public static String createAnagram(String inputString) {
String[] arr = inputString.split(" ");
return Stream.of(arr)
.map(AnagramsMaker::reverseWord)
.collect(Collectors.joining(" "));
}

Reversing a String of words with recursion

I am trying to reverse a full string in java
For example, Good morning so the output should return morning good.
I am tried the below function
public static String reverse(String s)
{
if (s.isEmpty())
return s;
//int n = 0;
return reverse(s.substring(1)) + s.charAt(0);
}
But the above function is converting good morning into gninrom doog. My code working on each character, how I make it work on words. Any hint or guide/explanation will be appreciated.
I already been to this question but not solving my problem
Updated:
Trying the below code with the help of #snr answer and #NathanHughes comments
public static String reverse(String s)
{
int s1 = s.indexOf(" ");
if (s1 != -1)
{
return reverse(s.substring(s1+1)) + s.substring(0,s1);
}
else
{
return "-1";
}
}
But output is
-1good
At first, you need to know where spaces are.
public static String reverse(String str) {
int space = str.indexOf(" ");
return space == -1 ? str : reverse(str.substring(space + 1)) + " " + str.substring(0, space);
}
This may not be the most efficient way of doing it, but it works:
public static String reverse(String s) {
String[] wordList;
wordList = s.split(" ");
String reverseWordList = "";
for (int i = 1; i <= wordList.length; i++) {
reverseWordList += wordList[wordList.length - i] + " ";
}
reverseWordList = reverseWordList.trim();
return reverseWordList;
}

Using Recursion to Reverse a String

I am trying to reverse a String word by word using recursion. (Ex: "Hello my friend" is reversed to "friend my Hello") This is the code I have attempted to write for this method. I have tried multiple similar variations but the output is only ever the first or last word of the String. I believe the part that is "broken" is the first if statement, but I am not quite sure.
public static String reverse (String words) {
Scanner sc = new Scanner(words);
String backwards = "";
if (sc.hasNext()) {
String currentWord = sc.next();
reverse(sc.nextLine());
backwards = backwards + " " + currentWord;
} //end if
else {
backwards = words;
} //end else
return backwards;
}
I am aware that a few similar questions exist, but their answers have not seemed to help me understand my mistake(s).
Thanks!
Instead of using a Scanner, you can make use of an overload of String.split to split words around the first space:
public static String reverse(String words) {
String[] wordArr = words.split(" ", 2); // split into a maximum of 2 Strings
if (wordArr.length > 1) { // If there is more than 1 word
// return the first word (wordArr[0]),
// behind the reverse of the rest of the String (wordArr[1])
return reverse(wordArr[1]) + " " + wordArr[0];
}
return wordArr[0]; // else, just return the one word
}
You shouldn't call nextLine() because your input is all on one line. Your logic is much clearer if you begin by creating a simple helper method, it should take an array of words and a position; from there you can recursively build your desired output with something like
private static String reverse(String[] words, int p) {
if (p + 1 < words.length) {
return reverse(words, p + 1) + " " + words[p];
} else if (p < words.length) {
return words[p];
}
return "";
}
Then your public method is easy to implement, just split the original input on white space and call reverse starting at 0 (remembering to return the result). Like,
public static String reverse(String words) {
return reverse(words.split("\\s+"), 0);
}
And then, I tested it like
public static void main(String[] args) {
System.out.println(reverse("Hello my friend"));
}
Which outputs (as requested)
friend my Hello
Alternatively, you could make that helper take your Scanner instead like
private static String reverse(Scanner sc) {
if (sc.hasNext()) {
String currentWord = sc.next();
if (sc.hasNext()) {
return reverse(sc) + " " + currentWord;
}
return currentWord;
}
return "";
}
And then your public method is
public static String reverse(String words) {
return reverse(new Scanner(words));
}
public static String reverseSentence(String sentence) {
StringBuilder sb = new StringBuilder();
int firstSpace = sentence.indexOf(' ');
if (firstSpace == -1) {
return sb.append(sentence.strip()).append(" ").toString();
}
String secondPart = sentence.substring(firstSpace + 1);
String firstPart = sentence.substring(0, firstSpace);//similar to merger sort
return sb.append(reverseSentence(secondPart)).append(reverseSentence(firstPart)).toString();
}
You throw away the recursion results:
reverse(sc.nextLine());
backwards = backwards + " " + currentWord;
Instead, use this:
backwards = reverse(sc.nextLine());
backwards = backwards + " " + currentWord;
Better yet:
backwards = reverse(sc.nextLine()) + " " + currentWord;
As stated in the comments, you could use a StringBuilder instead of Scanner class.
This example sends the same words, splits them by spaces each time you enter the method and you send the index of the word to be added in the next iteration.
For example:
public class RecursiveReverse {
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) {
String stringToReverse = "Hello my friend!";
System.out.println(reverse(stringToReverse, stringToReverse.split(" ").length - 1));
}
public static String reverse(String words, int i) {
if (i >= 0) { //If the index of the words is greater or equals the first word
sb.append(words.split(" ")[i]); //We split it and append it to our StringBuilder
sb.append(" "); //We append a space
reverse(words, --i); //We do this again
}
return sb.toString(); //When the above condition doesn't match we return the StringBuilder object as a String (which contains the words reversed)
}
}
Which produces this output:
friend! my Hello
A better method would be passing a String array as parameter so you split only once (when sending the words as an array to the method) the String.
public class RecursiveReverse {
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) {
String stringToReverse = "Hello my friend!";
String words[] = stringToReverse.split(" ");
System.out.println(reverse(words, words.length - 1));
}
public static String reverse(String words[], int i) {
if (i >= 0) {
sb.append(words[i]);
sb.append(" ");
reverse(words, --i);
}
return sb.toString();
}
}
Do you must use recursion? You can do that without it.
public static String reverse(String words) {
String[] list = words.split(" ");
Collections.reverse(list);
String reversed = String.join(" ", list);
return reversed;
}
You must keep hold of the extracted words between calls in an accumulator. Here is an example.
public static String reverse(String words, String acc){
Scanner sc = new Scanner(words);
if(!sc.hasNext()){
return acc;
}
return reverse(sc.nextLine(), acc) + " " + sc.next();
}
You would call it like this.
reverse("Hello my friend", "");
It's not the most efficient implementation in the world, but yeah... It must work!
If you want a more efficient one, use a StringBuilder as the accumulator.

Categories