regular expression replace 2 characters with one - java

i would like to use a regular expression for the following problem:
SOME_RANDOM_TEXT
should be converted to:
someRandomText
so, the _(any char) should be replaced with just the letter in upper case. i found something like that, using the tool:
_\w and $&
how to get only the second letter from the replacement?? any advice? thanks.

It might be easier simply to String.split("_") and then rejoin, capitalising the first letter of each string in your collection.
Note that Apache Commons has lots of useful string-related stuff, including a join() method.

The problem is that the case conversion from lowercase to uppercase is not supported by Java.util.regex.Pattern
This means you will need to do the conversion programmatically as Brian suggested. See also this thread

You can also write a simple method to do this. It's more complicated but more optimized :
public static String toCamelCase(String value) {
value = value.toLowerCase();
byte[] source = value.getBytes();
int maxLen = source.length;
byte[] target = new byte[maxLen];
int targetIndex = 0;
for (int sourceIndex = 0; sourceIndex < maxLen; sourceIndex++) {
byte c = source[sourceIndex];
if (c == '_') {
if (sourceIndex < maxLen - 1)
source[sourceIndex + 1] = (byte) Character.toUpperCase(source[sourceIndex + 1]);
continue;
}
target[targetIndex++] = source[sourceIndex];
}
return new String(target, 0, targetIndex);
}
I like Apache commons libraries, but sometimes it's good to know how it works and be able to write some specific code for jobs like this.

Related

Java: Shift all character-codes inside a String by a constant value

This works:
for (char c : sourceString.toCharArray())
destString += (char) (c + shiftValue);
System.out.println(destString);
Is there a better/faster (optimized) way?
Well I'd avoid using repeated string concatenation, to start with. That's a very well known performance problem.
In this case, you know the exact length you need to start with, so you don't even need a StringBuilder - a char[] is fine:
char[] result = new char[srcString.length()];
for (int i = 0; i < result.length; i++) {
result[i] = (char) (srcString.charAt(i) + shiftValue);
}
String destString = new String(result);
(The answer using toCharArray and then overwriting each element is nice too, although I'd expect any performance differences to be small. You'd want to test it with your actual system if this is really performance-critical code. The main point is that both are O(N) approaches rather than O(N2).)
However, you should think about whether you really want to just shift - most exercises like this are more rotate than shift, e.g. if you start with A-Z, you should end up with A-Z as well... a shift value of 1 should change Z to A, not to "the Unicode character after Z" (which is [). That may not be a requirement in your case, but you should certainly consider it.
A shorter version. No need to call charAt(i) every time in the loop.
char[] result = srcString.toCharArray();
for (int i = 0; i < result.length; i++) {
result[i] += shiftValue;
}
String destString = new String(result);
Yes, there is:
StringBuilder destString = new StringBuilder();
for (char c : srcString.toCharArray()) {
destString.appned((char) (c + shiftValue));
}
System.out.println(destString.toString());

What am I missing with this code? Google foo.bar

So recently I got invited to this google foo.bar challenge and I believe the code runs the way it should be. To be precise what I need to find is the number of occurrences of "abc" in a String. When I verify my code with them, I pass 3/10 test cases. I'm starting to feel bad because I don't know what I am doing wrong. I have written the code which I will share with you guys. Also the string needs to be less than 200 characters. When I run this from their website, I pass 3 tests and fail 7. Basically 7 things need to be right.
The actual question:
Write a function called answer(s) that, given a non-empty string less
than 200 characters in length describing the sequence of M&Ms. returns the maximum number of equal parts that can be cut from the cake without leaving any leftovers.
Example : Input : (string) s = "abccbaabccba"
output : (int) 2
Input: (string) s = "abcabcabcabc"
output : (int) 4
public static int answer(String s) {
int counter = 0;
int index;
String findWord ="ABC";
if(s!=null && s.length()<200){
s = s.toUpperCase();
while (s.contains(findWord))
{
index = s.indexOf(findWord);
s = s.substring(index + findWord.length(), s.length());
counter++;
}
}
return counter;
}
I see a couple of things in your code snippet:
1.
if(s.length()<200){
Why are you checking for the length to be lesser than 200? Is that a requirement? If not, you can skip checking the length.
2.
String findWord ="abc";
...
s.contains(findWord)
Can the test program be checking for upper case alphabets? Example: "ABC"? If so, you might need to consider changing your logic for the s.contains() line.
Update:
You should also consider putting a null check for the input string. This will ensure that the test cases will not fail for null inputs.
The logic of your code is well but on the other hand i found that you didn't check for if input string is empty or null.
I belief that google foo.bar wants to see the logic and the way of coding in a proper manner.
so don't be feel bad
I would go for a simpler approach
int beforeLen = s.length ();
String after = s.replace (findWord, "");
int afterLen = after.length ();
return (beforeLen - afterLen) / findWord.length ();
String pattern = "abc";
String line="<input text here>";
int i=0;
Pattern TokenPattern=Pattern.compile(pattern);
if(line!=null){
Matcher m=TokenPattern.matcher(line);
while(m.find()){
i++;
}}
System.out.println("No of occurences : "+ " "+i);
put declaration of index out before while block, isn't never good re-declare the same variable n time.
int index;
while (s.contains(findWord))
{
index = s.indexOf(findWord);
....
}
I hope this help
Update:
try to compact your code
public static int answer(String s) {
int counter = 0;
int index;
String findWord = "ABC";
if (s != null && s.length() < 200) {
s = s.toUpperCase();
while ((index = s.indexOf(findWord)) > -1) {
s = s.substring(index + findWord.length(), s.length());
counter++;
}
}
return counter;
}
Update:
The logic seems good to me, I'm still try to improve the performance, if you can try this
while ((index = s.indexOf(findWord, index)) > -1) {
//s = s.substring(index + findWord.length(), s.length());
index+=findWord.length();
counter++;
}

Java regex: How to replace all character inside a bracket?

How do I able to replace:
((90+1)%(100-4)) + ((90+1)%(100-4/(6-4))) - (var1%(var2%var3(var4-var5)))
with
XYZ((90+1),(100-4)) + XYZ((90+1),100-4/(6-4)) - XYZ(var1,XYZ(var2,var3(var4-var5)))
with regex?
Thanks,
J
this doesn't really look like a very good job for a regex. It looks like you might want to write a quick recursive descent parser instead. If I understand you correctly, you want to replace the infix operator % with a function name XYZ?
So (expression % expression) becomes XYZ(expression, expression)
This looks like a good resource to study: http://www.cs.uky.edu/~lewis/essays/compilers/rec-des.html
I don't know much about regex, but try looking at this, especially 9 and 10:
http://www.mkyong.com/regular-expressions/10-java-regular-expression-examples-you-should-know/
And of course:
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html
You could at least check them out until an in depth answer comes along.
See this code:
String input = "((90+1)%(100-4)) + ((90+1)%(100-4/(6-4))) - (var1%(var2%var3(var4-var5)))";
input = input.replaceAll("%", ",");
int level = 0;
List<Integer> targetStack = new ArrayList<Integer>();
List<Integer> splitIndices = new ArrayList<Integer>();
// add the index of last character as default checkpoint
splitIndices.add(input.length());
for (int i = input.length() - 1; i >= 0; i--) {
if (input.charAt(i) == ',') {
targetStack.add(level - 1);
} else if (input.charAt(i) == ')') {
level++;
}
else if (input.charAt(i) == '(') {
level--;
if (!targetStack.isEmpty() && level == targetStack.get(targetStack.size() - 1)) {
splitIndices.add(i);
}
}
}
Collections.reverse(splitIndices); // reversing the indices so that they are in increasing order
StringBuilder result = new StringBuilder();
for (int i = 1; i < splitIndices.size(); i++) {
result.append("XYZ");
result.append(input.substring(splitIndices.get(i - 1), splitIndices.get(i)));
}
System.out.println(result);
The output is as you expect it:
XYZ((90+1),(100-4)) + XYZ((90+1),(100-4/(6-4))) - XYZ(var1,XYZ(var2,var3(var4-var5)))
However keep in mind that it is a bit hacky and it might not work exactly as you expect it. Btw, I had to change a bit the output I added couple of brackets: XYZ((90+1), ( 100-4/(6-4 ) )) because otherwise you were not following your own conventions. Hopefully this code helps you. For me it was a good exercise at least.
Would it satisfy your requirements to do the following:
Find ( at first position or preceded by space and replace it with XYZ(
Find % and replace it with ,
If those two instructions are sufficient and satisfactory, then you could transform the original string in three "moves":
Replace ^\( with XYZ(
Replace \( with XYZ(
Replace % with ,

Reading characters from a file written with .net

I'm trying to use java to read a string from a file that was written with a .net binaryWriter.
I think the problem is because the .net binary writer uses some 7 bit format for it's strings. By researching online, I came across this code that is supposed to function like the binary reader's readString() method. This is in my CSDataInputStream class that extends DataInputStream.
public String readStringCS() throws IOException {
int stringLength = 0;
boolean stringLengthParsed = false;
int step = 0;
while(!stringLengthParsed) {
byte part = readByte();
stringLengthParsed = (((int)part >> 7) == 0);
int partCutter = part & 127;
part = (byte)partCutter;
int toAdd = (int)part << (step*7);
stringLength += toAdd;
step++;
}
char[] chars = new char[stringLength];
for(int i = 0; i < stringLength; i++) {
chars[i] = readChar();
}
return new String(chars);
}
The first part seems to be working as it is returning the correct amount of characters (7). But when it reads the characters they are all Chinese! I'm pretty sure the problem is with DataInputStream.readChar() but I have no idea why it isn't working... I have even tried using
Character.reverseBytes(readChar());
to read the char to see if that would work, but it would just return different Chinese characters.
Maybe I need to emulate .net's way of reading chars? How would I go about doing that?
Is there something else I'm missing?
Thanks.
Okay, so you've parsed the length correctly by the sounds of it - but you're then treating it as the length in characters. As far as I can tell from the documentation it's the length in bytes.
So you should read the data into a byte[] of the right length, and then use:
return new String(bytes, encoding);
where encoding is the appropriate coding based on whatever was written from .NET... it will default to UTF-8, but it can be specified as something else.
As an aside, I personally wouldn't extend DataInputStream - I would compose it instead, i.e. make your type or method take a DataInputStream (or perhaps just take InputStream and wrap that in a DataInputStream). In general, if you favour composition over inheritance it can make code clearer and easier to maintain, in my experience.

Fill strings with 0's using formatter

I know I can fill with spaces using :
String.format("%6s", "abc"); // ___abc ( three spaces before abc
But I can't seem to find how to produce:
000abc
Edit:
I tried %06s prior to asking this. Just letting you know before more ( untried ) answers show up.
Currently I have: String.format("%6s", data ).replace(' ', '0' ) But I think there must exists a better way.
You should really consider using StringUtils from Apache Commons Lang for such String manipulation tasks as your code will get much more readable. Your example would be StringUtils.leftPad("abc", 6, ' ');
Try rolling your own static-utility method
public static String leftPadStringWithChar(String s, int fixedLength, char c){
if(fixedLength < s.length()){
throw new IllegalArgumentException();
}
StringBuilder sb = new StringBuilder(s);
for(int i = 0; i < fixedLength - s.length(); i++){
sb.insert(0, c);
}
return sb.toString();
}
And then use it, as such
System.out.println(leftPadStringWithChar("abc", 6, '0'));
OUTPUT
000abc
By all means, find a library you like for this kind of stuff and learn what's in your shiny new toolbox so you reinvent fewer wheels (that sometimes have flats). I prefer Guava to Apache Commons. In this case they are equivalent:
Strings.padStart("abc",6,'0');
Quick and dirty (set the length of the "000....00" string as the maximum len you support) :
public static String lefTpadWithZeros(String x,int minlen) {
return x.length()<minlen ?
"000000000000000".substring(0,minlen-x.length()) + x : x;
}
I think this is what you're looking for.
String.format("%06s", "abc");

Categories