CodingBat hasBad "StringIndexOutOfBoundsException" - java

Hey guys I was hoping someone could explain to me the error in this code? I'm just having a little trouble understanding why it's throwing that exception.

The first condition checks for the minimum length of string which should be 3. So "bad" and "xba" passes the first condition.
Lets go with bad first.
The second condition has two OR clauses and string "bad" satisfies the first of two OR clauses at line no 3. And hence the answer is TRUE
Now with xba..
The first of two OR clauses fails, so it checks for the second one. And here str.substrin(1, 4) throws StringIndexOutOfBoundsException as the number of character in the String xba is only 3.
I would simple do a STRING.regionMatches() as below
String testString = "bad";
String givenString = "xxbad";
boolean zeroIndexMatch = givenString.regionMatches(true, 0, testString, 0, 3);
boolean firstIndexMatch = givenString.regionMatches(true, 1, testString, 0, 3);
if (zeroIndexMatch || firstIndexMatch) {
System.out.println(true);
} else {
System.out.println(false);
}

The tested String "xba" has the length 3 with the indices from 0 to 2.
Your second method call of substring is str.substring(1,4). Therefore it tries to read the indices 1 till 3 (the endIndex 4 is exclusive). So you're trying to read from index 3, but since the String isn't long enough to have such index, you're getting the mentioned Exception.

When you are using the str.substring(1, 4) method it is causing a problem with that 7th test because it is only using a string that is 3 characters long. By trying the access that fourth character you are going out of the string's bounds, and therefore getting the StringIndexOutOfBoundsException.

Related

finding the middle index of a substring when there are duplicates in the string

I was working on a Java coding problem and encountered the following issue.
Problem:
Given a string, does "xyz" appear in the middle of the string? To define middle, we'll say that the number of chars to the left and right of the "xyz" must differ by at most one
xyzMiddle("AAxyzBB") → true
xyzMiddle("AxyzBBB") → false
My Code:
public boolean xyzMiddle(String str) {
boolean result=false;
if(str.length()<3)result=false;
if(str.length()==3 && str.equals("xyz"))result=true;
for(int j=0;j<str.length()-3;j++){
if(str.substring(j,j+3).equals("xyz")){
String rightSide=str.substring(j+3,str.length());
int rightLength=rightSide.length();
String leftSide=str.substring(0,j);
int leftLength=leftSide.length();
int diff=Math.abs(rightLength-leftLength);
if(diff>=0 && diff<=1)result=true;
else result=false;
}
}
return result;
}
Output I am getting:
Running for most of the test cases but failing for certain edge cases involving more than once occurence of "xyz" in the string
Example:
xyzMiddle("xyzxyzAxyzBxyzxyz")
My present method is taking the "xyz" starting at the index 0. I understood the problem. I want a solution where the condition is using only string manipulation functions.
NOTE: I need to solve this using string manipulations like substrings. I am not considering using list, stringbuffer/builder etc. Would appreciate answers which can build up on my code.
There is no need to loop at all, because you only want to check if xyz is in the middle.
The string is of the form
prefix + "xyz" + suffix
The content of the prefix and suffix is irrelevant; the only thing that matters is they differ in length by at most 1.
Depending on the length of the string (and assuming it is at least 3):
Prefix and suffix must have the same length if the (string's length - the length of xyz) is even. In this case:
int prefixLen = (str.length()-3)/2;
result = str.substring(prefixLen, prefixLen+3).equals("xyz");
Otherwise, prefix and suffix differ in length by 1. In this case:
int minPrefixLen = (str.length()-3)/2;
int maxPrefixLen = minPrefixLen+1;
result = str.substring(minPrefixLen, minPrefixLen+3).equals("xyz") || str.substring(maxPrefixLen, maxPrefixLen+3).equals("xyz");
In fact, you don't even need the substring here. You can do it with str.regionMatches instead, and avoid creating the substrings, e.g. for the first case:
result = str.regionMatches(prefixLen, "xyz", 0, 3);
Super easy solution:
Use Apache StringUtils to split the string.
Specifically, splitByWholeSeparatorPreserveAllTokens.
Think about the problem.
Specifically, if the token is in the middle of the string then there must be an even number of tokens returned by the split call (see step 1 above).
Zero counts as an even number here.
If the number of tokens is even, add the lengths of the first group (first half of the tokens) and compare it to the lengths of the second group.
Pay attention to details,
an empty token indicates an occurrence of the token itself.
You can count this as zero length, count as the length of the token, or count it as literally any number as long as you always count it as the same number.
if (lengthFirstHalf == lengthSecondHalf) token is in middle.
Managing your code, I left unchanged the cases str.lengt<3 and str.lengt==3.
Taking inspiration from #Andy's answer, I considered the pattern
prefix+'xyz'+suffix
and, while looking for matches I controlled also if they respect the rule IsMiddle, as you defined it. If a match that respect the rule is found, the loop breaks and return a success, else the loop continue.
public boolean xyzMiddle(String str) {
boolean result=false;
if(str.length()<3)
result=false;
else if(str.length()==3 && str.equals("xyz"))
result=true;
else{
int preLen=-1;
int sufLen=-2;
int k=0;
while(k<str.lenght){
if(str.indexOf('xyz',k)!=-1){
count++;
k=str.indexOf('xyz',k);
//check if match is in the middle
preLen=str.substring(0,k).lenght;
sufLen=str.substring(k+3,str.lenght-1).lenght;
if(preLen==sufLen || preLen==sufLen-1 || preLen==sufLen+1){
result=true;
k=str.length; //breaks the while loop
}
else
result=false;
}
else
k++;
}
}
return result;
}

Java Exception: java.lang.StringIndexOutOfBoundsException

I have some problems with the code every time I try to compile the exception java.lang.StringIndexOutOfBoundsException appears. Here is the code with the problem I really don't know what I have done wrong. In the code I try to split a string using some conditions, the string represent a polynomial.
int[] coef1= new int[20];
for(i=0;i<polinom.length()+1;i++){
if(polinom.charAt(i)=='+' )
c=polinom.charAt(i+1);
else{
if(polinom.charAt(i)=='^'){
v=Integer.parseInt(Character.toString(polinom.charAt(i+1)));
coef1[v]=Integer.parseInt(Character.toString(c));
System.out.print(coef1[v]);
}
}
}
for(i=0;i<polinom.length()+1;i++){
if(polinom.charAt(i)=='-' )
c=polinom.charAt(i+1);
else{
if(polinom.charAt(i)=='^'){
v=Integer.parseInt(Character.toString(polinom.charAt(i+1)));
coef1[v]=-Integer.parseInt(Character.toString(c));
System.out.print(coef1[v]);
}
}
}
The exception is here if(polinom.charAt(i)=='+' )
Just replace all your
for(i=0;i<polinom.length()+1;i++){
with
for(i=0;i<polinom.length()-1;i++){
As indices are 0-based and you use polinom.charAt(i+1), i+1 should never be equal (nor greater) than polinom.length.
Or if you want ot be able to test until the last character of you string (for other processing), you can ensure that polinom.charAt(i+1) gets never triggered if i == polinom.length() - 1, just add a test before processing your stuff:
for(i=0;i<polinom.length();i++){ // not using -1, looping to the end of the string
if(polinom.charAt(i)=='+' && i < polinom.length() - 1) // checking that no exception will be thrown
c=polinom.charAt(i+1);
else{
if(polinom.charAt(i)=='^' && i < polinom.length() - 1){ // same
v=Integer.parseInt(Character.toString(polinom.charAt(i+1)));
coef1[v]=-Integer.parseInt(Character.toString(c));
System.out.print(coef1[v]);
}
}
}
In the second line here you are using
for(i=0;i<polinom.length()+1;i++){
That +1 should be -1.
I suppose the variable polinom is a String.
Your're looping beyond the end of the string:
for(i=0;i<polinom.length()+1;i++)
It should be
for(i=0;i<polinom.length()-1;i++)

Strange(?) out - of - bound with Stringuilder on array

There last 2 days I am 100% brain dead and cant find where the error is... Can anyone give me a tip >>
for(String inputString : word)
{
StringBuilder sb = new StringBuilder(inputString);
if(inputString.charAt(inputString.length()-1) == ']')
{
sb.deleteCharAt(inputString.length());
}
else if(inputString.charAt(0) == '[')
{
sb.deleteCharAt(0);
}
breaker.add(sb.toString());
}
It was suppose to be a simple function to remove the [ ] characters from a string but everytime I run it I get
Exception in thread "AWT-EventQueue-0" java.lang.StringIndexOutOfBoundsException: String index out of range: 4
But only on the third or fourth pass never the first or second.
Confused.
sb.deleteCharAt(inputString.length());
should be
sb.deleteCharAt(inputString.length() - 1);
Because you want to remove the last character (you did it correctly in the test!)
You're deleting the last char at the StringBuilder's length, rather than length - 1.
StringBuilder, not unlike all String and array representations in Java, is 0-indexed.
Use the following idiom instead:
sb.deleteCharAt(sb.length() - 1);
The reason why the StringIndexOutOfBoundsException is only thrown arbitrarily in your execution is likely because of the condition checking for the ] character, which may not always hold true (hence the offending code would not execute).

What is the correlation between string length and string substring methods?

I basically had to make a program that returns the number of times that the string "code" appears anywhere in the given string, except we'll accept any letter for the 'd', so "cope" and "cooe" count for my APCS class, I had no problems with the code except for the parameters of the for loop, the i<str.length()-3 in particular. It works fine, but only after I kept subtracting random numbers arbitrarily from the length. I really want to know what the correlation between that and the rest of the code is so it isn't just a guess and check thing for me. I don't want to get in the habit of doing that.
public int countCode(String str) {
int times = 0;
for(int i =0;i<str.length()-3;i++){
if(str.substring(i,i+2).equals("co") && str.substring(i+3,i+4).equals("e"))
times++;
}
return times;
}
The correlation is that the substring has to fit inside the source string. You are calling str.substring(i, i+2). Now let's say that your string is 5 characters long. This means the first index inside the string is 0, and the last one is 4. Now imagine that i is equal to 3.
When you call substring(i, i+2), you are really calling substring(3, 5). The substring method takes a start index and an end index. Your end index turns out to be 5, which is illegal because it's outside of the string the last index of which is 4.
So you should really be checking i < str.length() - searchString.length() + 1 instead of i < str.length() - 3.
Your search pattern is 4 characters long. The last character of the string is at index .length() - 1. Therefore the last index where the pattern can start is 3 characters earlier at .length() - 4. You used a less than comparison with .length - 3. So the last iteration of the loop is at this value. It's correct.
A little sketch can help in cases like this:
| 0 | 1 | 2 | 3 | Pattern
... | L-5 | L-4 | L-3 | L-2 | L-1 | String (L==str.length)
... < L-3 ...| Iterations
This is essentially a regular expression match. Using String#substring is needlessly complicated for this scenario. A better approach is to use Pattern#matcher as follows:
public static int countCode(String s) {
Pattern codepattern = Pattern.compile("co.e");
Matcher codematcher = codepattern.matcher(s);
int count = 0;
while (codematcher.find()) count++;
return count;
}
As you can see, find() will keep finding the regex until the end of the given string. For example, given String s = "This core supports all the code. Everyone comes to the core, for the cool stuff is all coded in here.";, the above method returns 5.
Edit: I realize this is not exactly what you had asked, but I thought this might help you.
Gene is spot on, but consider this regex-based alternative:
int times = str.replaceAll("co[a-z]e", "xxxxx").length() - str.length();
It's all done in one line and you let the regex engine do the heavy lifting.

Java String.indexOf and empty Strings

I'm curious why the String.indexOf is returning a 0 (instead of -1) when asking for the index of an empty string within a string.
The Javadocs only say this method returns the index in this string of the specified string, -1 if the string isn't found.
To me this behavior seems highly unexpected, I would have expected a -1. Any ideas why this unexpected behavior is going on? I would at the least think this is worth a note in the method's Javadocs...
System.out.println("FOO".indexOf("")); // outputs 0 wtf!!!
System.out.println("FOO".indexOf("bar")); // outputs -1 as expected
System.out.println("FOO".indexOf("F")); // outputs 0 as expected
System.out.println("".indexOf("")); // outputs 0 as expected, I think
The empty string is everywhere, and nowhere. It is within all strings at all times, permeating the essence of their being, yet as you seek it you shall never catch a glimpse.
How many empty strings can you fit at the beginning of a string? Mu
The student said to the teacher,
Teacher, I believe that I have found the nature of the empty string. The empty string is like a particle of dust, and it floats freely through a string as dust floats freely through the room, glistening in a beam of sunlight.
The teacher responded to the student,
Hmm. A fine notion. Now tell me, where is the dust, and where is the sunlight?
The teacher struck the student with a strap and instructed him to continue his meditation.
Well, if it helps, you can think of "FOO" as "" + "FOO".
int number_of_empty_strings_in_string_named_text = text.length() + 1
All characters are separated by an empty String. Additionally empty String is present at the beginning and at the end.
By using the expression "", you are actually referring to a null string. A null string is an ethereal tag placed on something that exists only to show that there is a lack of anything at this location.
So, by saying "".indexOf( "" ), you are really asking the interpreter:
Where does a string value of null exist in my null string?
It returns a zero, since the null is at the beginning of the non-existent null string.
To add anything to the string would now make it a non-null string... null can be thought of as the absence of everything, even nothing.
Using an algebraic approach, "" is the neutral element of string concatenation: x + "" == x and "" + x == x (although + is non commutative here).
Then it must also be:
x.indexOf ( y ) == i and i != -1
<==> x.substring ( 0, i ) + y + x.substring ( i + y.length () ) == x
when y = "", this holds if i == 0 and x.substring ( 0, 0 ) == "".
I didn't design Java, but I guess mathematicians participated in it...
if we look inside of String implementation for a method "foo".indexOf(""), we arrive at this method:
public int indexOf(String str) {
byte coder = coder();
if (coder == str.coder()) {
return isLatin1() ? StringLatin1.indexOf(value, str.value)
: StringUTF16.indexOf(value, str.value);
}
if (coder == LATIN1) { // str.coder == UTF16
return -1;
}
return StringUTF16.indexOfLatin1(value, str.value);
}
If we look inside of any of the called indexOf(value, str.value) methods we find a condition that says:
if the second parameter (string we are searching for) length is 0 return 0:
public static int indexOf(byte[] value, byte[] str) {
if (str.length == 0) {
return 0;
}
...
This is just defensive coding for an edge case, and it is necessary because in the next method that is called to do actual searching by comparing bytes of the string (string is a byte array) it would otherwise have resulted in an ArrayIndexOutOfBounds exception:
public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
byte first = str[0];
...
This question is actually two questions:
Why should a string contain the empty string?
Why should the empty string be found specifically at index zero?
Answering #1:
A string contains the empty string in order to be in accordance with Set Theory, according to which:
The empty set is a subset of every set including itself.
This also means that even the empty string contains the empty string, and the following statement proves it:
assert "".indexOf( "" ) == 0;
I am not sure why mathematicians have decided that it should be so, but I am pretty sure they have their reasons, and it appears that these reasons can be explained in layman's terms, as various youtube videos seem to do, (for example, https://www.youtube.com/watch?v=1nBKadtFViM) although I have not actually viewed any of those videos, because #AintNoBodyGotNoTimeFoDat.
Answering #2:
The empty string can be found specifically at index zero of any string, because why not? In other words, if not at index zero, then at which index? Index zero is as good as any other index, and index zero is guaranteed to be a valid index for all strings except for the trifling exception of the empty string.

Categories