Deleting del word from input in Java - java

Question
Given a string, if the string "del" appears starting at index 1, return a string where that "del" has been deleted. Otherwise, return the string unchanged.
My Code
public String delDel(String str) {
return str.replaceAll("del","");
}
but my code failed for some test cases like:
1)delDel("del") → "del" ""
2)delDel("aadelbb") → "aadelbb" "aabb"
I am beginner to Java. Can anyone tell me why it's showing that error.
Question link : https://codingbat.com/prob/p100905
Thanks in advance...

Here String::replaceFirst should be used with a simpler regexp "^(.)del" because only the first occurrence at the beginning of the string needs to be matched:
public String delDel(String str) {
return str.replaceFirst("^(.)del", "$1");
}
Another solution may use String::regionMatches (or even shorter String::startsWith) and String::charAt + String::substring to perform the task without regular expressions at all:
public String delDel(String str) {
return str.startsWith("del", 1) ? str.charAt(0) + str.substring(4) : str;
// return str.regionMatches(1, "del", 0, 3) ? str.charAt(0) + str.substring(4) : str;
}

Related

Recursive method to combine a string and its reverse

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")

Java String index out of range error

I'm running into some issues with some java code that I do not know how to fix. I was wondering if I could get some help with figuring out why I keep getting
java.lang.StringIndexOutOfBoundsException: String index out of range: 1
Here's the code snippet where the problem is popping up (its part of a larger package for an assignment..) :
public class MyMapper extends Mapper {
#Override
//method takes docName and data as string
public void map(String documentID, String document) {
//this string array hold all the delimiters for our split
//String[] separators = {",", ".", "!", "?", ";", ":", "-", "' "," "};
//splits the string 'document' according to delimiters
String[] words = document.split(",|\\.|\\!|\\?|\\;|\\:|\\-|\\' |\\ |\\'.");
// for each word in String[] words, check that each word is legitimate
for (String word : words) {
if (isAlpha(word)){
//System.out.println(word);
emit(word.substring(0, 1).toUpperCase() , "1");
}
else;
}
}
// private helper method to check that each word is legitimate (alphas-only)
private boolean isAlpha(String name) {
char[] chars = name.toCharArray();
for (char c : chars) {
if(!Character.isLetter(c)) {
return false;
}
}
return true;
}
}
What I am trying to do is take in a document (stored in string form through bufferedReader) and seize the first letter of each word in the doc, and capitalize them.
***** Updated Code*****
I decided to go with the suggested check for the empty "word" in my private helper method. Everything works now.
Here is the updated code for documentation purposes:
// private helper method to check that each word is legitimate (alphas-only)
private boolean isAlpha(String name) {
if (name.equals(""))
return false;
char[] chars = name.toCharArray();
for (char c : chars) {
if(!Character.isLetter(c)) {
return false;
}
}
return true;
Looks like sometimes your word is empty. Make a check first to see that you've got something to work with:
if (isAlpha(word)){
if(!word.isEmpty()){ //you could also use 'if(word.length == 0)'
emit(word.substring(0, 1).toUpperCase() , "1");
}
}
Alternatively, make that check in your isAlpha() method.
If your word is empty just return a false from your isAlpha() like this
private boolean isAlpha(String name) {
if (name.equals(""))
return false;
char[] chars = name.toCharArray();
for (char c : chars) {
if(!Character.isLetter(c)) {
return false;
}
}
return true;
}
}
For some strings, your split regex can produce empty strings, for example in the not-at-all unusual case that a comma is followed by a space, e.g., the string document = "Some words, with comma."; will be split into [Some, words, , with, comma].
Instead of enumerating all the non-word characters that you can think of, I suggest using the \W character class (non-alphanumeric character) and also allowing multiple of those, i.e. words = document.split("\\W+");. This gives you [Some, words, with, comma].
If you need more control about the characters to split by and don't want to use a character class, you can still put the characters into [...]+ to shorten the regex and to split by groups of those, too, using words = document.split("[|.!?,;:' -]+"). (Inside [...], you do not need to escape all of those, as long as the - is last, so it's unambiguous.)
Would something like this do?
String text = "es saß ein wiesel, auf einem kiesel.";
String[] parts = text.split("\\s+");
StringBuilder resultingString = new StringBuilder();
for (String part : parts) {
part = Character.toUpperCase(part.charAt(0))
+ part.substring(1, part.length());
resultingString.append(part + " ");
}
text = resultingString.toString().substring(0,
resultingString.length() - 1);
System.out.println(text);

Use regex to replace sequences in a string with modified characters

I am trying to solve a codingbat problem using regular expressions whether it works on the website or not.
So far, I have the following code which does not add a * between the two consecutive equal characters. Instead, it just bulldozes over them and replaces them with a set string.
public String pairStar(String str) {
Pattern pattern = Pattern.compile("([a-z])\\1", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
if(matcher.find())
matcher.replaceAll(str);//this is where I don't know what to do
return str;
}
I want to know how I could keep using regex and replace the whole string. If needed, I think a recursive system could help.
This works:
while(str.matches(".*(.)\\1.*")) {
str = str.replaceAll("(.)\\1", "$1*$1");
}
return str;
Explanation of the regex:
The search regex (.)\\1:
(.) means "any character" (the .) and the brackets create a group - group 1 (the first left bracket)
\\1, which in regex is \1 (a java literal String must escape a backslash with another backslash) means "the first group" - this kind of term is called a "back reference"
So together (.)\1 means "any repeated character"
The replacement regex $1*$1:
The $1 term means "the content captured as group 1"
Recursive solution:
Technically, the solution called for on that site is a recursive solution, so here is recursive implementation:
public String pairStar(String str) {
if (!str.matches(".*(.)\\1.*")) return str;
return pairStar(str.replaceAll("(.)\\1", "$1*$1"));
}
FWIW, here's a non-recursive solution:
public String pairStar(String str) {
int len = str.length();
StringBuilder sb = new StringBuilder(len*2);
char last = '\0';
for (int i=0; i < len; ++i) {
char c = str.charAt(i);
if (c == last) sb.append('*');
sb.append(c);
last = c;
}
return sb.toString();
}
I dont know java, but I believe there is replace function for string in java or with regular expression. Your match string would be
([a-z])\\1
And the replace string would be
$1*$1
After some searching I think you are looking for this,
str.replaceAll("([a-z])\\1", "$1*$1").replaceAll("([a-z])\\1", "$1*$1");
This is my own solutions.
Recursive solution (which is probably more or less the solution that the problem is designed for)
public String pairStar(String str) {
if (str.length() <= 1) return str;
else return str.charAt(0) +
(str.charAt(0) == str.charAt(1) ? "*" : "") +
pairStar(str.substring(1));
}
If you want to complain about substring, then you can write a helper function pairStar(String str, int index) which does the actual recursion work.
Regex one-liner one-function-call solution
public String pairStar(String str) {
return str.replaceAll("(.)(?=\\1)", "$1*");
}
Both solution has the same spirit. They both check whether the current character is the same as the next character or not. If they are the same then insert a * between the 2 identical characters. Then we move on to check the next character. This is to produce the expected output a*a*a*a from input aaaa.
The normal regex solution of "(.)\\1" has a problem: it consumes 2 characters per match. As a result, we failed to compare whether the character after the 2nd character is the same character. The look-ahead is used to resolve this problem - it will do comparison with the next character without consuming it.
This is similar to the recursive solution, where we compare the next character str.charAt(0) == str.charAt(1), while calling the function recursively on the substring with only the current character removed pairStar(str.substring(1).

String type charAt

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.

Conditionally replacing the last characters of a string

I have a string, say xyzabc_1_1.
I want to first test if the last characters are _1 and if so, replace the last _1 with _01_1. The string will become xyzabc_1_01_1.
For finding if the last digits are _1 I'm using
str1.matches("^.*_\\d$")
But don't know the second part, i.e. how to replace the last occurrence with _01_1.
To replace the string, you can just grab a substring and concatenate your new suffix. Additionally, you can use endsWith instead of the regular expression. IMHO it's more readable.
public String replaceSuffix (String target) {
if (!target.endsWith("_1")) {
return target;
}
return target.substring(0, target.length() - 2) + "_01_1";
}
And just for the fun of it, here's a more reusable version for replacing different things:
public String replaceSuffix (String target, String suffix, String replacement) {
if (!target.endsWith(suffix)) {
return target;
}
String prefix = target.substring(0, target.length() - suffix.length());
return prefix + replacement;
}
Invoked as (for your specific example):
String replaced = replaceSuffix("xyzabc_1_1", "_1", "_01_1");
Depending on your expected input, you might also want some null/empty/length checks on str.
This is a simple one-liner, using replaceAll() and back-references:
String str2 = str1.replaceAll("_\\d$", "_01$0");
It's not clear if the 01 is based on the 1 or is a constant. ie if 2 were to become 02_2 then do this instead: str1.replaceAll("_(\\d)$", "_0$1_$1")
Here's a test:
String str1 = "xyzabc_1_1";
String str2 = str1.replaceAll("_\\d$", "_01$0");
System.out.println(str2);
Output:
xyzabc_1_01_1
You'd rather replace the whole string with the new one. Create a new string with the '_01_1' concatenated. Then replace.
Done but needs optimization...
String str1 = "xyzabc_1";
/* System.out.println(str1.matches("^.*_\\d$")); */
try {
if (str1.matches("^.*_\\d$")) {
String cutted = str1.substring(str1.lastIndexOf("_"),
str1.length());
str1 = str1.replaceAll(cutted, "_01" + cutted); //
System.out.println(str1);
} else {
}
} catch (Exception e) {
e.printStackTrace();
}

Categories

Resources