Related
So, the task is to create a string that makes a progression throughout the letters of a string, returning a substring progressively longer.
For example if the input is Book, the answer would be: BBoBooBook . For the input Soup the method would return SSoSouSoup. I want to write it recursively. In my current method I receive no error but at the same time no anwer from the compiler.
public static String stringProgression(String str) {
int index = 1;
String result = "";
if (str.length() == 0) {
return "" ;
} else while (index <= str.length()); {
result = result + stringExplosion(str.substring(0, index));
index++;
}
return result;
}
In your code, you are using two different method names, stringProgression and stringExplosion.
Further, you have a while loop with a semicolon, while (index <= str.length()); which forms an empty loop. Since index doesn’t change in this empty loop, it will be an infinite loop when the condition is fulfilled.
Generally, a while loop contradicts the intent to have a recursive solution.
To find a recursive solution to a problem, you have to find the self-similarity in it. I.e. when you look at the intended result for Book, BBoBooBook, you can recognize that the beginning, BBoBoo is the right result for the string Boo, and BBo is the right result for Bo. So, the original string has to be appended to the result of a recursive evaluation of the substring:
public static String stringProgression(String str) {
if(str.isEmpty()) {
return str;
}
return stringProgression(str.substring(0, str.length() - 1)) + str;
}
An alternative, shorter syntax for the same is:
public static String stringProgression(String str) {
return str.isEmpty()? str: stringProgression(str.substring(0, str.length() - 1)) + str;
}
Check this one:
private static String doStringProgression(String str, String res, int length) {
if(length > str.length()) {
return res;
}
return doStringProgression(str, res + str.substring(0, length), length + 1);
}
And you can call the method with input like in the following example:
public static String stringProgression(String str) {
return doStringProgression(str, "", 1);
}
Given a string, compute recursively (no loops) a new string where all appearances of "pi" have been replaced by "3.14".
changePi("xpix") → "x3.14x"
changePi("pipi") → "3.143.14"
changePi("pip") → "3.14p"
My code worked perfectly but is there any other way (only recursively no loops) to do this problem without having to create a new string str2 ?
Thank you in advance
here is my code :
public String changePi(String str) {
String str2 = "";
return changePi(str, str2);
}
public String changePi(String str, String str2) {
if (str.length() == 0)
return str2;
else {
if (str.endsWith("pi")) {
str2 = 3.14 + str2;
return changePi(str.substring(0, str.length() - 2), str2);
} else
str2 = str.charAt(str.length() - 1) + str2;
}
return changePi(str.substring(0, str.length() - 1), str2);
}
Using the same mechanism you can use a StringBuilder and modify it in-situ. This should be much more memory efficient.
private static final String PI = "pi";
private static final String THREE_POINT_ONE_FOUR = "3.14";
public String changePi(String s) {
// Work with a StringBuilder for efficiency.
StringBuilder sb = new StringBuilder(s);
// Start replacement at 0.
return changePi(sb, 0).toString();
}
private StringBuilder changePi(StringBuilder sb, int i) {
// Long enough?
if (i + PI.length() <= sb.length()) {
// Is it there?
if (sb.subSequence(i, i + PI.length()).equals(PI)) {
// Yes! - Replace it and recurse.
sb.replace(i, i + PI.length(), THREE_POINT_ONE_FOUR);
return changePi(sb, i + THREE_POINT_ONE_FOUR.length());
} else {
// Not there - step to next.
return changePi(sb, i + 1);
}
}
return sb;
}
private void test(String s) {
System.out.println(s + " -> " + changePi(s));
}
private void test() {
test("pipi");
test("xpix");
test("pip");
}
You are doing the same mistake as you did in your previous question. Also I would prefer to check if a string starts with, and not ends with a string...I am assuming that you would like something that you can understand and it's easy to explain.
Can you match "pi" or the string is already less than length("pi") symbols -> cant do nothing much so return it.
Does it starts with "pi"? If so return the replacement concatenated with the rest of the string (just the rest starts length("pi") characters away from the 0th index...
If it isn't starting with "pi" than concatenate the first character with what's the output of changePi and the rest of the string as its input.
public static String changePi(String str) {
if (str.length() < "pi".length()) {
return str;
}
if (str.startsWith("pi")) {
return "3.14" + changePi(str.substring("pi".length(), str.length()));
}
return str.charAt(0) + changePi(str.substring(1, str.length()));
}
And still if you like to use the "endsWith" logic then here is the same algorythm applied.
public static String changePi(String str) {
if (str.length() < "pi".length()) {
return str;
}
if (str.endsWith("pi")) {
return changePi(str.substring(0, str.length() - "pi".length())) + "3.14";
}
return changePi(str.substring(0, str.length() - 1)) + str.charAt(str.length() - 1);
}
public static String changePi(String str) {
int num = str.indexOf("pi");
if (num==-1) return str;
return str.substring(0,num)+"3.14"+changePi(str.substring(num+2));
}
does it, though I guess it depends what you mean by create a new string. In a sense this does, but without naming it.
Your solution is a nice approach (it's a little confusing as you replace twice, I believe) and I would make sth like:
If str <= than 2, check str if equals pi, return 3,14 or str
Else, if ends with pi return Change(str-2)+Change(last2), else return Change(str-1)+Change(lastChar)
Edited: now changes pi for 3,14
Voila! simple and clean:
String fun(int i) {
if(i == s.length()) return "";
if(i+1 < s.length() && s.charAt(i) == 'p' && s.charAt(i+1) == 'i') {
return "3.14" + fun(i+2);
} else {
return s.charAt(i) + fun(i+1);
}
}
Any reason why you have not considered using regular expressions?
The following seems to work fine for all the test cases you mentioned:
public String changePi(String str) {
return str.replaceAll("pi", "3.14");
}
Note that in Java a String is immutable. You cannot modify a String once you initialise it. Each time you are doing str2 = ... you are really creating a completely new String object.
If you need to do it recursively (i.e. it is some coursework), then what you did is perfectly fine (although I would have used indexOf("pi") rather than endsWith("pi") and removing the trailing characters, but anyway.
It is the standard way to perform recursion, with str2 being the accumulator (maybe you want to rename it so that it is clear what it is doing). You might want to consider using StringBuilder instead of a String for the second parameter, and in your base case you call toString() to get the final string... although honestly the difference in computation cost between creating a new String and using a StringBuilder has become very low.
I've never written Java before, but this seems to work:
public class HelloWorld {
public static void main(String[] args) {
System.out.println(changePi("xpix"));
System.out.println(changePi("pipi"));
System.out.println(changePi("pip"));
}
public static String changePi(String str) {
int len = str.length();
if (len < 2)
return str;
if (str.endsWith("pi"))
return changePi(str.substring(0, len - 2)) + "3.14";
else
return changePi(str.substring(0, len - 1)) + str.substring(len - 1, len);
}
}
Explaination:
This is closer to a true recursive solution, since the function doesn't know about the right portion of the string (no str2), it's the calling function's responsibility to keep track of it.
The terminal case is running on a string shorter than "pi", in which case we return the remainder (0 or 1 chars).
If the string ends in "pi", we take the rest of the string before that and pass that to the new iteration, but keep in mind to append "3.14" when that returns.
If the string doesn't end in that, we just break off a single character and keep it to reattach.
Criticism:
This is horribly inefficient, though, as every .substr call is creating a whole new string object, and we do a lot of these calls.
You would have better luck using something like a linked list of characters.
public String changePi(String str) {
if(str.length() == 0){
return str;
}
if(str.startsWith("pi")){
return "3.14" + changePi(str.substring(2));
}
return str.substring(0,1) + changePi(str.substring(1));
}
public class ChangePi {
public static String changePi(String str) {
String pi = "3.14";
if (str.length() < 2) {
return str;
}
return (str.substring(0, 2).equals("pi")) ? pi + changePi(str.substring(2)) :
str.substring(0, 1) + changePi(str.substring(1));
}
}
Hope my answer explains everything :)
public String changePi(String str) {
if (str.length() < 1) return ""; // return if string length is zero
String count = str.substring(0,1); // get the string
int increment = 1; // increment variable to iterate the string
if (str.length() > 1 && str.substring(0, 2).equals("pi")){
//string length > 1 and it pi if found
count = "3.14";
increment = 2;//increment by 2 characters
}
//attach the 3.14 part or substring(0,1) and move forward in the string
return count + changePi(str.substring(increment));
}
Here is the answer:
public String changePi(String str) {
if(str.equals("")){
return str;
}
else if(str.length()>=2 && str.charAt(0)=='p' && str.charAt(1)=='i') {
return "3.14" + changePi(str.substring(2));
}
else{
return str.charAt(0) + changePi(str.substring(1));
}
}
public String changePi(String str) {
if(str.length() == 0) return str;
if(str.charAt(0) == 'p' && str.length() >= 2){
if(str.charAt(1) == 'i'){
return "3.14" + changePi(str.substring(2));
}
}
return str.charAt(0) + changePi(str.substring(1));
}
I want to count number of words in my string using recursive method (java)
so far i wrote this code
public static int CountWords(String sen) {
int count = 0;
int i = sen.indexOf(" ");
if (sen.isEmpty()) {
return 0;
}else
if (i == sen.indexOf(" ")) {
return count++;
}
//sen.substring(0,sen.indexOf(" ")-1);
count++;
return count + CountWords(sen.substring(i + 1));
}
i always get 0 when i call the method
can anyone help me make this code run
How you're using indexOf is the problem. You're setting i to the result of calling indexOf, then seeing if it's equal to the result of calling indexOf on the same string with the same parameter. The result of the test i == sen.indexOf(" ") will always be true. That's why you always get 0.
String#indexOf returns -1 if the char it's looking for is not found. indexOf comes in very handy here.
Also you shouldn't need a local count variable. Introducing a variable here just makes the code harder to read, because the reader has to hunt around to figure out what the value of it is.
Assuming your input always has exactly one blank between words this could be done as:
public static int countWords(String s) {
if (s.isEmpty()) return 0;
if (s.indexOf(" ") == -1) return 1;
return 1 + countWords(s.substring(s.indexOf(" ") + 1));
}
For multiple blanks between words you can check for a blank and skip past it:
public static int countWords(String s) {
if (s.isEmpty()) return 0;
if (s.indexOf(' ') == -1) return 1;
if (s.charAt(0) == ' ') return countWords(s.substring(1));
return 1 + countWords(s.substring(s.indexOf(' ') + 1));
}
This should work, I think:
public static int countWords(String sen) {
int i = sen.indexOf(" ");
if (sen.isEmpty()) {
return 0;
} else if (i == -1) {
return 1;
} else return 1 + countWords(sen.substring(i + 1));
}
Some notes on what is happening:
Java naming conventions dictate you should start method names with a lower case letter
The line if (i == sen.indexOf(" ")) is redunant - you just assigned i to be that before, so it'll always evaluate to true.
And therefore, your recursion never gets called. You need to change it so that if sen isn't empty and contains at least one more space, countWords calls itself with sen minus the first word.
This method uses a String with no spaces as a base case. Then it removes everything up to and including the first space in the String and recurses.
It handles both the special case of an empty String and the case that a String passed to the method starts with a space appropriately.
public static int CountWords(String sen)
{ int i = sen.indexOf(" ");
if(sen.isEmpty()) return 0; // special case
if(i == -1) return 1; // base case
if(i != 0)
return 1 + CountWords(sen.substring(i+1));
else
return CountWords(sen.substring(1));
}
This will work -
public static int CountWords(String sen) {
if("".equals(sen)){
return 0;
}
int count = 0;
int i = sen.indexOf(" ");
String substr = sen.substring(0,i+1) ;
if (i != -1) {
count++;
}else{
if(sen.length()>0){
count++;
}
sen="";
}
//sen.substring(0,sen.indexOf(" ")-1);
return count + CountWords(sen.substring(substr.length()));
}
Is it possible to reverse String in Java without using any of the temporary variables like String, Char[] or StringBuilder?
Only can use int, or int[].
String reverseMe = "reverse me!";
for (int i = 0; i < reverseMe.length(); i++) {
reverseMe = reverseMe.substring(1, reverseMe.length() - i)
+ reverseMe.substring(0, 1)
+ reverseMe.substring(reverseMe.length() - i, reverseMe.length());
}
System.out.println(reverseMe);
Output:
!em esrever
Just for the fun of it, of course using StringBuffer would be better, here I'm creating new Strings for each Iteration, the only difference is that I'm not introducing a new reference, and I've only an int counter.
The objects of the Java String class are immutable - their contents cannot be altered after being created.
You will need at least two temporary objects - one for the final result and one for the intermediate values - even if you do find a way to avoid using a local variable.
EDIT:
That said, since you can use int[] you may be able to cheat.
Since char can be assigned to int, you can use String.charAt() to create an int array with the character values in reverse order. Or you may be allowed to use String.toCharArray() to get a char array that will be copied over to your int[] temporary.
Then you use the variable that holds the reference to your original string (or the result variable, if you are allowed one) to start from an empty string (easily obtainable with a direct assignment or String.substring()) and use String.concat() to create the final result.
In no case, however, will you be able to swap the characters in-place as you would do in C/C++.
EDIT 2:
Here's my version which does not use StringBuffer/Builders internally:
int r[] = new int[s.length()];
int idx = r.length - 1;
for (int i : s.toCharArray()) {
r[idx--] = i;
}
s = s.substring(0, 0);
for (int i : r) {
s = s.concat(String.valueOf((char)i));
}
String s = "Hello World!";
for(int i = 0; i < s.length(); i++)
{
s = s.substring(1, s.length() - i) + s.charAt(0) + s.substring(s.length() - i);
}
System.out.println(s); // !dlroW olleH
No temporary variables! :)
One of many ways:
String str = "The quick brown fox jumps over the lazy dog";
int len = str.length();
for (int i = (len-1); i >= 0; --i)
str += str.charAt(i);
str = str.substring(len);
System.out.println(str);
public String reverseStr(String str) {
if (str.length() <= 1) {
return str;
}
return reverseStr(str.substring(1)) + str.charAt(0);
}
Because you can use an int, you can assign an int a char value:
String aString = "abc";
int intChar = aString.charAt(0);
You will have to convert from the int back to the char to assign it to aString.charAt(2).
I'm sure you can figure it out from there.
First append the string to itself in reverse manner. Then take the second half out of it.
public class RevString {
public static void main(String[] args) {
String s="string";
for(int i=s.length()-1;i>=0;i--){
s+=s.charAt(i);
}
s=s.substring(s.length()/2, s.length());
System.out.println(s);
}
}
Without using any collection,StringBulider, StringBuffer or temp array reverse the string. Simple and crisp:
public static void main(String[] args) {
String test = "Hello World";
String rev = "";
Pattern p = Pattern.compile("[\\w|\\W]");
Matcher m = p.matcher(test);
while (m.find()) {
rev = m.group()+rev;
}
System.out.println("Reverse==" + rev);
}
Output
Reverse==dlroW olleH
Hope it helps :)
public class Test {
static St`enter code here`ring reverseString(String str) {
for (int i = 0; i < str.length() / 2; i++) {
if (i == 0) {
str = str.charAt(str.length() - 1 - i) + str.substring(i + 1, str.length() - 1 - i) + str.charAt(i);
} else {
str = str.substring(0, i) + str.charAt(str.length() - 1 - i)
+ str.substring(i + 1, str.length() - 1 - i) + str.charAt(i)
+ str.substring(str.length() - i, str.length());
}
}
return str;
}
public static void main(String args[]) {
String s = "ABCDE";
System.out.println(Test.reverseString(s));
}
}
String str = "Welcome";
for(int i=0;i<str.length();){
System.out.print(str.charAt(str.length()-1));
str = str.substring(0,str.length()-1);
}
Except for loop variables.
You can use class java.lang.StringBuilder:
String reservedString = new StringBuilder(str).reserve().toString();
I want to remove the last character from a string. I've tried doing this:
public String method(String str) {
if (str.charAt(str.length()-1)=='x'){
str = str.replace(str.substring(str.length()-1), "");
return str;
} else{
return str;
}
}
Getting the length of the string - 1 and replacing the last letter with nothing (deleting it), but every time I run the program, it deletes middle letters that are the same as the last letter.
For example, the word is "admirer"; after I run the method, I get "admie." I want it to return the word admire.
replace will replace all instances of a letter. All you need to do is use substring():
public String method(String str) {
if (str != null && str.length() > 0 && str.charAt(str.length() - 1) == 'x') {
str = str.substring(0, str.length() - 1);
}
return str;
}
Why not just one liner?
public static String removeLastChar(String str) {
return removeLastChars(str, 1);
}
public static String removeLastChars(String str, int chars) {
return str.substring(0, str.length() - chars);
}
Full Code
public class Main {
public static void main (String[] args) throws java.lang.Exception {
String s1 = "Remove Last CharacterY";
String s2 = "Remove Last Character2";
System.out.println("After removing s1==" + removeLastChar(s1) + "==");
System.out.println("After removing s2==" + removeLastChar(s2) + "==");
}
public static String removeLastChar(String str) {
return removeLastChars(str, 1);
}
public static String removeLastChars(String str, int chars) {
return str.substring(0, str.length() - chars);
}
}
Demo
Since we're on a subject, one can use regular expressions too
"aaabcd".replaceFirst(".$",""); //=> aaabc
The described problem and proposed solutions sometimes relate to removing separators. If this is your case, then have a look at Apache Commons StringUtils, it has a method called removeEnd which is very elegant.
Example:
StringUtils.removeEnd("string 1|string 2|string 3|", "|");
Would result in:
"string 1|string 2|string 3"
public String removeLastChar(String s) {
if (s == null || s.length() == 0) {
return s;
}
return s.substring(0, s.length()-1);
}
Don't try to reinvent the wheel, while others have already written libraries to perform string manipulation:
org.apache.commons.lang3.StringUtils.chop()
In Kotlin you can used dropLast() method of the string class.
It will drop the given number from string, return a new string
var string1 = "Some Text"
string1 = string1.dropLast(1)
Use this:
if(string.endsWith("x")) {
string= string.substring(0, string.length() - 1);
}
if (str.endsWith("x")) {
return str.substring(0, str.length() - 1);
}
return str;
For example, the word is "admirer"; after I run the method, I get "admie." I want it to return the word admire.
In case you're trying to stem English words
Stemming is the process for reducing inflected (or sometimes derived) words to their stem, base or root form—generally a written word form.
...
A stemmer for English, for example, should identify the string "cats" (and possibly "catlike", "catty" etc.) as based on the root "cat", and "stemmer", "stemming", "stemmed" as based on "stem". A stemming algorithm reduces the words "fishing", "fished", "fish", and "fisher" to the root word, "fish".
Difference between Lucene stemmers: EnglishStemmer, PorterStemmer, LovinsStemmer outlines some Java options.
As far as the readability is concerned, I find this to be the most concise
StringUtils.substring("string", 0, -1);
The negative indexes can be used in Apache's StringUtils utility.
All negative numbers are treated from offset from the end of the string.
string = string.substring(0, (string.length() - 1));
I'm using this in my code, it's easy and simple.
it only works while the String is > 0.
I have it connected to a button and inside the following if statement
if (string.length() > 0) {
string = string.substring(0, (string.length() - 1));
}
public String removeLastChar(String s) {
if (!Util.isEmpty(s)) {
s = s.substring(0, s.length()-1);
}
return s;
}
removes last occurence of the 'xxx':
System.out.println("aaa xxx aaa xxx ".replaceAll("xxx([^xxx]*)$", "$1"));
removes last occurrence of the 'xxx' if it is last:
System.out.println("aaa xxx aaa ".replaceAll("xxx\\s*$", ""));
you can replace the 'xxx' on what you want but watch out on special chars
Look to StringBuilder Class :
StringBuilder sb=new StringBuilder("toto,");
System.out.println(sb.deleteCharAt(sb.length()-1));//display "toto"
// creating StringBuilder
StringBuilder builder = new StringBuilder(requestString);
// removing last character from String
builder.deleteCharAt(requestString.length() - 1);
How can a simple task be made complicated. My solution is:
public String removeLastChar(String s) {
return s[0..-1]
}
or
public String removeLastChar(String s) {
if (s.length() > 0) {
return s[0..-1]
}
return s
}
// Remove n last characters
// System.out.println(removeLast("Hello!!!333",3));
public String removeLast(String mes, int n) {
return mes != null && !mes.isEmpty() && mes.length()>n
? mes.substring(0, mes.length()-n): mes;
}
// Leave substring before character/string
// System.out.println(leaveBeforeChar("Hello!!!123", "1"));
public String leaveBeforeChar(String mes, String last) {
return mes != null && !mes.isEmpty() && mes.lastIndexOf(last)!=-1
? mes.substring(0, mes.lastIndexOf(last)): mes;
}
A one-liner answer (just a funny alternative - do not try this at home, and great answers already given):
public String removeLastChar(String s){return (s != null && s.length() != 0) ? s.substring(0, s.length() - 1): s;}
Most answers here forgot about surrogate pairs.
For instance, the character 𝕫 (codepoint U+1D56B) does not fit into a single char, so in order to be represented, it must form a surrogate pair of two chars.
If one simply applies the currently accepted answer (using str.substring(0, str.length() - 1), one splices the surrogate pair, leading to unexpected results.
One should also include a check whether the last character is a surrogate pair:
public static String removeLastChar(String str) {
Objects.requireNonNull(str, "The string should not be null");
if (str.isEmpty()) {
return str;
}
char lastChar = str.charAt(str.length() - 1);
int cut = Character.isSurrogate(lastChar) ? 2 : 1;
return str.substring(0, str.length() - cut);
}
Java 8
import java.util.Optional;
public class Test
{
public static void main(String[] args) throws InterruptedException
{
System.out.println(removeLastChar("test-abc"));
}
public static String removeLastChar(String s) {
return Optional.ofNullable(s)
.filter(str -> str.length() != 0)
.map(str -> str.substring(0, str.length() - 1))
.orElse(s);
}
}
Output : test-ab
public String removeLastCharacter(String str){
String result = null;
if ((str != null) && (str.length() > 0)) {
return str.substring(0, str.length() - 1);
}
else{
return "";
}
}
if we want to remove file extension of the given file,
** Sample code
public static String removeNCharactersFromLast(String str,int n){
if (str != null && (str.length() > 0)) {
return str.substring(0, str.length() - n);
}
return "";
}
For kotlin check out
string.dropLast(1)
if you have special character like ; in json just use String.replace(";", "") otherwise you must rewrite all character in string minus the last.
Why not use the escape sequence ... !
System.out.println(str + '\b');
Life is much easier now . XD ! ~ A readable one-liner
How to make the char in the recursion at the end:
public static String removeChar(String word, char charToRemove)
{
String char_toremove=Character.toString(charToRemove);
for(int i = 0; i < word.length(); i++)
{
if(word.charAt(i) == charToRemove)
{
String newWord = word.substring(0, i) + word.substring(i + 1);
return removeChar(newWord,charToRemove);
}
}
System.out.println(word);
return word;
}
for exemple:
removeChar ("hello world, let's go!",'l') → "heo word, et's go!llll"
removeChar("you should not go",'o') → "yu shuld nt goooo"
Here's an answer that works with codepoints outside of the Basic Multilingual Plane (Java 8+).
Using streams:
public String method(String str) {
return str.codePoints()
.limit(str.codePoints().count() - 1)
.mapToObj(i->new String(Character.toChars(i)))
.collect(Collectors.joining());
}
More efficient maybe:
public String method(String str) {
return str.isEmpty()? "": str.substring(0, str.length() - Character.charCount(str.codePointBefore(str.length())));
}
just replace the condition of "if" like this:
if(a.substring(a.length()-1).equals("x"))'
this will do the trick for you.
Suppose total length of my string=24
I want to cut last character after position 14 to end, mean I want starting 14 to be there.
So I apply following solution.
String date = "2019-07-31T22:00:00.000Z";
String result = date.substring(0, date.length() - 14);
I had to write code for a similar problem. One way that I was able to solve it used a recursive method of coding.
static String removeChar(String word, char charToRemove)
{
for(int i = 0; i < word.lenght(); i++)
{
if(word.charAt(i) == charToRemove)
{
String newWord = word.substring(0, i) + word.substring(i + 1);
return removeChar(newWord, charToRemove);
}
}
return word;
}
Most of the code I've seen on this topic doesn't use recursion so hopefully I can help you or someone who has the same problem.