how to uncompress a given string in java recursively? - java

this is very easy using iteration but i have to do this using recursion. I tried to keep a count of how many times a char occurs in a string, the position and the rest of the string and output.
public static String uncompress(String compressedText) {
return uncompress(compressedText, 1, 0, "");
}
public static String uncompress(String text, int count, int pos, String output) {
if (text.equals("")) {
return "";
}
if (Character.isLetter(text.charAt(pos))) {
output += text.charAt(0);
pos++;
}
else if(Character.isDigit(text.charAt(pos))) {
count = text.charAt(pos) - '0';
output += text.charAt(pos + 1);
count++;
pos++;
}
text = text.substring(pos + 1);
uncompress(text, count, pos, output);
return output;
}

There are multiple errors in your code such as:
you are substringing but also passing in a position, you should do one or the other
your base case is returning "" but instead it should return the accrued string 'output'
where you recurse you disregard the output from the returning method and just return the output in the current method so nothing is built up by the recursion
Below is code which uses only recursion both to parse the string and build up the output. I have added comments to show what is happening in the code. Note that, particularly in recursion, it is useful to have a printout of the current state so you can see what is happening at each stage so I have added this too.
Note that the getMultiple() method is in itself a very simple example of how recursion should work - that you call the same method but either A) pass in some work done in the current call so that it can be accrued by the base case or B) take the output of the method and add something to it / modify it before returning the modified output.
public class Recursion {
public static void main(String[] args) {
System.out.println(uncompress("10a2b"));
}
public static String uncompress(String compressedText) {
return uncompress(compressedText, "", "");
}
public static String getMultiple(char x, int N) {
if (N == 0) return "";
return ""+x+getMultiple(x,N-1);
}
public static String uncompress(String text, String count, String output) {
System.out.println("----");
System.out.println("TEXT:"+text);
System.out.println("COUNT:"+count);
System.out.println("OUTPUT:"+output);
if (text.equals("")) {
//base case - no text left to parse
return output;
}
if (Character.isLetter(text.charAt(0))) {
//letter case - need to take the count we have accrued, parse it into an integer and add to output
System.out.println(count);// * text.charAt(0);
output += getMultiple(text.charAt(0),Integer.parseInt(count));
count = "";
}
else if(Character.isDigit(text.charAt(0))) {
//digit case - need to add to the count but keep as a string because must be parsed later
count += (""+text.charAt(0));
}
//parse the *remainder* of the string, one character at a time, so pass in the substring(1)
return uncompress(text.substring(1), count, output);
}
}

Assuming that the input String has a correct format, try this:
public static String uncompress(String compressedText) {
if (compressedText.length() == 0)
return "";
return uncompress(compressedText, charToInt(compressedText, 0), 0);
}
public static String uncompress(String text, int count, int pos) {
if (pos == text.length() || (pos == text.length()-2 && count == 0))
return "";
else if (count == 0)
return uncompress(text, charToInt(text, pos+2), pos+2);
return text.charAt(pos+1) + uncompress(text, count-1, pos);
}
public static int charToInt(String str, int idx) {
return str.charAt(idx) - '0';
}

Related

Backtracking bruteforce Java password cracker

I have this homework assignment to make a recursive method to crack a password of a given length, n (unlimited and unknown!) made of small English letters, a-z ONLY.
Here's the class "Password" that creates a random password:
import java.util.Random;
public class Password {
private String _password = "";
public Password(int length) {
Random generator = new Random();
for (int i = 0; i < length; ++i) {
this._password = this._password + (char) (generator.nextInt(26) + 97);
}
}
public boolean isPassword(String st) {
return st.equals(this._password);
}
public String getPassword() {
return this._password;
}
}
And here is the question in detail:
"You must write a static recursive method,
public static String findPassword(Password p, int length) that "cracks" the code.
Here's an example of a main method:
public class Main {
public static void main(String[] args) {
Password p = new Password(5);
System.out.println(p.getPassword());
System.out.println(Ex14.findPassword(p, 5));
}
}
Important notes:
The method MUST be recursive, without using ANY loops.
You may not use the getPassword method.
If you would like to use a method of the String class, you may only use the following: charAt, substring, equals, length.
You MAY use overloading, but you MAY NOT use other methods. (You cannot use String.replace/String.replaceall)
You MAY NOT use static(global) variables.
You MAY NOT use any Array. "
Here's what I have until now, which clearly doesn't work; :\
public static String findPassword(Password p, int length) {
return findPassword(p, length, "", 'a');
}
public static String findPassword(Password p, int length, String testPass, char charToChange) {
int currDig = testPass.length() - 1;
if (p.isPassword(testPass))
return testPass;
if (length == 0) // There is no password.
return ""; // Returns null and not 0 because 0 is a password.
if (length > testPass.length())
return findPassword(p, length, testPass + charToChange, charToChange);
if (testPass.length() == length) {
//TODO if charToChange is 'z', then make it the one before it '++', and reset everything else to a.
//if (charToChange == 'z') {
// charToChange = 'a';
// String newString = testPass.substring(0, currDig-1) +
// (charToChange++)
// +testPass.substring(currDig+1,testPass.length()-1);
System.out.println("it's z");
// TODO currDig --;
// String newerString = testPass.substring(0, currDig - 1)
// + (char) (testPass.charAt(testPass.length() - 1) - 25);
// currDig--;
}
return "";
}
Thank you very much! much appreciated!
- TripleS

Recursive Method to find number of occurrences of UpperCase letters in string- Using helper method

I'm trying to create a recursive method to find the number of occurrences of an UpperCase letter in a String. My code below:
public class findUppercase {
public static int searchUppercase(String s, int high) {
if (s.length() == 1) {
if (Character.isUpperCase(s.charAt(0)))
return 1;
else
return 0;
} else if (Character.isUpperCase(s.charAt(high - 1)) )
return 1 + searchUppercase(s, s.length() - 1);
else
return searchUppercase(s, s.length() - 1);
}
public static int searchUppercase(String s) {
return searchUppercase(s, s.length());
}
public static void main(String[] args) {
String a = "ABCmdsaA";
System.out.println(searchUppercase(a));
}
}
I get the error:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.Character.getType(Character.java:6924)
at java.lang.Character.isUpperCase(Character.java:5518)
at java.lang.Character.isUpperCase(Character.java:5488)
at findUppercase.searchUppercase(findUppercase.java:9)
As your String is never changing, its length will never change, so
if (s.length() == 1) {
will never be true unless you originally pass in a one char String
Change the value of the String s by using String.substring
Although personally I would just use a for loop and not a recursive method.
You don't need a recursive method at all, nor a for loop.
Just do:
public static long searchUppercase(String s) {
return s.chars()
.filter(i -> Character.isUpperCase(i))
.count();
}
But if you insist on using a recursive method, you only need a single uppercase check and a single recursive call:
public static long searchUppercase(String s, long count) {
if (s.length() == 0) {
return count;
}
if (Character.isUpperCase(s.charAt(0))) ++count;
String tail = s.substring(1);
return searchUppercase(tail, count);
}
public static long searchUppercase(String s) {
return searchUppercase(s, 0);
}

recursive expand of strings

I want to create a method which recursively expands the input string with another string.
public class StringTest {
public static String addZeichenkette(String out, int i) {
out += "bla";
if (i > 0) {
i--;
addZeichenkette(out, i);
}
return out;
}
public static void main(String[] args) {
String out = "Hello";
out = addZeichenkette(out, 7);
System.out.println(out);
}
}
The output should be :
Helloblablablablablablabla
instead it is
Hellobla
The main method has to be untouched (except the method calling).
You're ignoring the return from the recursive call.
public static String addZeichenkette(String out, int i)
{
if (i > 0)
{
out += "bla";
i--;
out = addZeichenkette(out, i);
}
return out;
}
Alternatively, you could just return the result addZeichenkette(out, i);, but both ways are fine.
As you pointed out, you would need to modify it to avoid adding i+1 bla's. Since when i = 0, we don't want any bla's to be added, we instead need to check for this.
To do this, I moved the concatenation of the bla into the condition.
You need to return the accumulated (recursed) string:
return addZeichenkette(out, i);
not just the one where i == 0.
public static String addZeichenkette(String out, int i) {
return i > 0 ? addZeichenkette(out + "bla", --i ) : out;
}

Error in my Word program in Java

This is my code and it compiles fine but when I try to create a string it says
Error: cannot find symbol - variable racer
public class Word {
private String original;
public Word(String s) {
original = s;
}
public String reverse () {
String reverse= "";
int x = 1;
int length = original.length();
while (length - x >= 0) {
reverse = reverse + original.substring(length -x);
x++;
}
return reverse;
}
public boolean isPalindrome() {
if(original.equals(reverse()))
return true;
else
return false;
}
}
The stated problem is not in the code posted - my guess is irrelephant's comment is correct, ie change new Word(racer) --> new Word("racer").
But I offer this to eliminate any chance of any errors in your code by basically eliminating your code:
public class Word {
private String original;
public Word(String s) {
original = s;
}
public boolean isPalindrome()
return new StringBuilder(original).reverse().toString().equals(original);
}
}
or if you must expose a reverse() method:
public class Word {
private String original;
public Word(String s) {
original = s;
}
public String reverse () {
return new StringBuilder(original).reverse().toString();
}
public boolean isPalindrome()
return reverse().equals(original);
}
}
I don't see the variable racer anywhere, but since you're using reverse inside a method, I'd recommend making it
Most likely, racer was never defined
Either that or the method was called w/o quotes
isPalindrome(racer)//note the lack of quotes
change reverse() to this
private() String reverse () {
String reverse= "";
int x = 1;
int length = original.length();
while (length - x >= 0) {
reverse = reverse + original.substring(length -x);
x++;
}
return reverse;

how to use recursion for converting String to int

I want to convert String input into int using recursion. This is the code I came up with but if my input is 123456 it only returns 124. If I enter 1234567, it gives an error.
import java.util.*;
public class Problem1 {
static int x =0;
static int counter = 0;
//input
public static void main(String[] args) {
Scanner scan = new Scanner (System.in);
String s= scan.nextLine();
System.out.println(recursive(s));
}
//recursive method
public static int recursive(String s){
if(s.length()==1){
x=(x*10)+ Integer.parseInt(s.substring(0,1));
return x;
}
else{
x = (x*10)+Integer.parseInt(s.substring(0,1));
counter++;
return recursive(s.substring(counter,s.length()-1));
}
}
}
import java.util.Scanner;
public class Problem1 {
static int x = 0;
static int counter = 0;
// input
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String s = scan.nextLine();
System.out.println(recursive(s));
}
// recursive method
public static int recursive(String s) {
if (s.length() == 1) {
x = (x * 10) + Integer.parseInt(s.substring(0, 1));
return x;
} else {
x = (x * 10) + Integer.parseInt(s.substring(0, 1));
counter++;
return recursive(s.substring(1, s.length()));
}
}
}
Look at your static counter variable. You are incrementing it every time. But you only want to have the substring starting at 1 (so cut off the first "letter").
So instead of using:
counter++;
return recursive(s.substring(counter,s.length()-1));
consider using:
return recursive(s.substring(1)); // you even don't really need the length
Because the String s parameter is as follows:
1st call: 1234567
2nd call: 234567
3rd call: 34567
4th call: 4567
...
So, you only have to cut off the first letter.
Btw: your sample "project" is a really funny one ;)
A few notes to start:
If you're doing recursion, you probably don't want to use a member variable. It's not wrong to do so, but not really typical of the pattern (your x variable).
It's often handy to pass in state through the recursion, although you wouldn't have to (that is, current value of x).
Your case is a little odd because you have to change your current parse value for every sub-parse (shifting by 10 each time); makes it a little more complicated.
If you are going to keep x as a member variable (which does seem to make sense in this case), you don't need to return anything from recursive.
Can you really not just use Integer.parseInt()?
Code could be much more simple, something like:
void recursive (String s)
{
if (s.length() == 0) return 0;
x = x * 10 + Integer.parseInt(s.substring(0, 1));
recursive(s.substring(1));
}
recursion("1234567", 0, 1)
The above code will turn the string "1234567" into an int using recursion. You must pass the string you want to convert, and then 0 and 1.
public static int recursion(String s, int result, int place) {
result += place * Integer.parseInt(s.charAt(s.length() - 1) + "");
if(s.length() == 1) {
return result;
}
else {
return recursion(s.substring(0, s.length() - 1), result, place * 10);
}
}
public static int computeStr(String str) {
if (str.equals("")) {
return 0;
}
int x = 1;
for (int i = 0; i < str.length() - 1; i++) {
x = x * 10;
}
x = x * Integer.parseInt(str.substring(0, 1));
return x + computeStr(str.substring(1));
}
For example: "2432" is (2 * 1000) + (4 * 100) + (3*10) + (2*1) = 2432
this algorithm begins at first position (2) from 2432
I know its kind of a late response but you could try something like this :-
private static int stringToInt(String string) {
if (string.length() == 0) {
return 0;
}
int rv;
int num = string.charAt(string.length() - 1) - '0';
String restOfTheString = string.substring(0, string.length() - 1);
rv = stringToInt(restOfTheString) * 10 + num;
return rv;
}
Try something like this:
Subtracting the ASCII code of the '0' character from your character returns an integer:
public class StringRecursion {
static int counter = 0;
public static void main(String[] args) {
System.out.println(convertStringToInt("123456"));
}
public static int convertStringToInt(String input) {
if (input.length() == 1)
return input.charAt(0) - '0';
int value = convertStringToInt(input.substring(0, input.length() - 1));
counter++;
return value * 10 + input.charAt(counter) - '0';
}
}
Try it like this :
public static int conStrToInt(String str) {
if(str.length()==0)
{
return 0;
}
char cc = str.charAt(0);
String ros = str.substring(1);
int factor=1;
for(int i=0;i<str.length()-1;i++)
factor*=10;
factor=factor*(cc-'0');
return factor+conStrToInt(ros);
}

Categories