StringIndexOutOfBoundsException in a counting loop in Java - java

I have to write a code for class using Java in which the number of occurrences of the letter E is counted and printed out (both cases included). This is what I have.
String sVerse = "As we enter our centennial year we are still young ";
System.out.println(sVerse);
int len3 = sVerse.length();
int countE = 0;
for (int d = 0; d <= len3; d++){
char e = sVerse.charAt(d);
d = d + 1;
if (e == 'e' || e == 'E')
{
countE = countE + 1;
}
else
{
countE = countE;
}
}
System.out.println(countE);
The code runs, and the string prints, but after the string prints I get this error:
java.lang.StringIndexOutOfBoundsException: String index out of range: 1258
at java.lang.String.charAt(Unknown Source)
at Unit4plus.main(Unit4plus.java:125)

You're increasing d inside the loop, which you shouldn't - just let the for loop do it's thing. Also, you should terminate the loop with <, not <=:
int countE = 0;
for (int d = 0; d < len3; d++) {
char e=sVerse.charAt(d);
if (e=='e' || e=='E') {
countE++;
}
}
But frankly, you could just stream the characters in the string for a much more elegant solution:
long countE = sVerse.chars().filter(c -> c == 'e' || c == 'E').count();

Your condition in the first loop should be :
d < len3
Since length starts at 1 but index of characters in your string are 0 based.
Moreover, your statement d=d+1 in the for loop is useless and makes you iterate 2 by 2 since you already increment it in the for loop with
d++

You need to change the condition for the loop since the length is +1 of the maximum index.You also increase the value of the variable "d" two times, one in the definition of the "for" loop, and the other is inside it. Try replace it with this code:
String sVerse = "As we enter our centennial year we are still young";
int len3 = sVerse.length();
int countE = 0;
for (int d = 0; d < len3; d++) {
char e = sVerse.charAt(d);
if (e == 'e' || e == 'E')
countE++;
}
System.out.println(countE);

Related

Counting Duplicates and Grouping in an Arraylist

for my project we have to manipulate certain LISP phrasing using Java. One of the tasks is given:
'(A A A A B C C A A D E E E E)
Group the duplicates and make the output like:
′((4A)(1B)(2C)(2A)(1D)(4E))
Notice how the first four A's are kept separate from the last 2...
My issues is with keeping track of how many is each letter. I added the given letters into an array list and I manipulated it a little:
for (int i=0;i<list.size();i++)
{
String val=list.get(i);
String first=list.get(0);
while (val.equals(first))
{
total+=1;
val="X";
}
}
Total should be the number of times of the first occurrence but it keeps giving me 6. 6 is the correct number for all the A's in the sequence, but how do I get it to stop at the first four, record the number and move on the the next letter?
Here is with Java 8 Stream API.
Map<Character, Long> countedDup = Arrays.asList('A' ,'A' ,'A', 'A', 'B', 'C', 'C', 'A', 'A', 'D', 'E', 'E', 'E', 'E')
.stream().collect(Collectors.groupingBy(c -> c, Collectors.counting()));
System.out.println(countedDup);//{A=6, B=1, C=2, D=1, E=4}
This is my solution:
for (int i = 0; i < list.size(); i++) {
String first = list.get(i);
int total = 1;
while (i + 1 < list.size() && first.equals(list.get(i + 1))) {
total++;
i++;
}
System.out.println("(" + total + first + ")");
}
You can debug to know how it run.
***** Note that when compare 2 String objects, never use ==. Use method equals()
This is my solution, though didn't used arrayList:
Edited: as per pointed out by Ascalonian
String text = "'(A A V A B C C X X X X A A Z Z Z K L N N N N N)";
int counter = 1;
System.out.print("'(");
for (int i = 2; i < text.length() - 1; i = i + 2) {
System.out.print("(");
while (((i + 2) < text.length())
&& (text.charAt(i) == text.charAt(i + 2))) {
++counter;
i += 2;
}
System.out.print(counter + "" + text.charAt(i) + ")");
counter = 1;
}
System.out.print(")");
o/p will be for sample text:
((2A)(1V)(1A)(1B)(2C)(4X)(2A)(3Z)(1K)(1L)(5N))
Not sure if using an ArrayList is a requirement, but if not, I use a different approach where I get just the letters, strip away the white spaces, make it a char[] and iterate each letter.
// the initial LISP phrase
String lispPhrase = "'(A A A A B C C A A D E E E E)";
// Pull out just the letters
String letters = lispPhrase.substring(2, lispPhrase.length()-1);
// Remove the white space between them
letters = letters.replaceAll("\\s","");
// Get an array for each letter
char[] letterArray = letters.toCharArray();
char previousLetter = ' ';
char nextLetter = ' ';
int letterCounter = 1;
System.out.print("'(");
// now go through each letter
for (char currentLetter : letterArray) {
// If the first time through, set previousLetter
if (previousLetter == ' ') {
previousLetter = currentLetter;
}else {
nextLetter = currentLetter;
// Is the next letter the same as before?
if (previousLetter == nextLetter) {
letterCounter++;
}else {
// If the next letter is different, print out the previous letter and count
System.out.print("(" + letterCounter + previousLetter + ")");
// Reset the counter back to 1
letterCounter = 1;
}
previousLetter = nextLetter;
}
}
System.out.print("(" + letterCounter + previousLetter + "))");
This gives the output of:
'((4A)(1B)(2C)(2A)(1D)(4E))
In order to get the required output that you specified in your question, I would keep track of the current and next values in the given list. The element count starts at 1 and is incremented when the equality condition is true, otherwise it is reset to 1. And the final output is only updated when the equality condition is false.
Sample code:
EDIT I updated my code based on #Ascalonian's suggestion.
String inputString = "'(A A A A B C C A A D E E E E)";
// I assume that the input always starts with "'("
String finalOutput = inputString.substring(0, 2);
int valCount = 1;
String valCurrent = inputString.substring(2, 3);
String valNext = "";
for (int i = 4; i < inputString.length(); i++) {
valNext = inputString.substring(i, i + 1);
if (valNext.equals(" ")) {
continue;
}
if (valCurrent.equals(valNext)) {
valCount++;
} else {
finalOutput += "(" + valCount + valCurrent + ")";
valCount = 1;
}
valCurrent = valNext;
}
finalOutput += ")";
System.out.println(finalOutput);
Output string: '((4A)(1B)(2C)(2A)(1D)(4E))
I hope this helps.

Too many Exception out of bounds - JAVA

Code is supposed to do this: Return 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.
The problem: Ran across Exception:java.lang.StringIndexOutOfBoundsException: String index out of range: 11 (line number:10)
public int countCode(String str){
int a = 0; // counter goes thru string
int b = str.length()-1;
int counter = 0; //counts code;
if(str.length() < 4) return 0;
else{
while (a <=b){
if(str.charAt(a) == 'c'){
if(str.charAt(a+1) == 'o'){
if(str.charAt(a+3) == 'e'){
counter++;
a= a+3;
} // checks e
else a++;
} // checks o
else a++;
} // checks c
else a++;
}
return counter;
}
}
Here's what I tried to evaluate to get said exception:
countCode("xxcozeyycop") --> EXPECTED RESULT 1
countCode("cozcop") --> EXPECTED RESULT
Your loop goes from 0 to the length of the string (excluded). But inside the loop, you're doing
str.charAt(a+3)
Obviously, if a is length - 1, a + 3 is length + 2, and you're thus trying to access an element outside the bounds of the string.
Side note: you would understand your own code better if you indented it correctly.
Instead of
while (a <=b){
use
while (a <= b - 3){
Reason: Your end sign in the while is the condition that the start of the String "code" is inside the String. However, if a = b - 2, then a + 3 = b + 1 = (str.length() - 1 + 1) = str.length() which is just outside the String.
public int countCode(String str) {
int count = 0;
for(int i = 0; i < str.length()-3; i++)
if(str.substring(i, i+2).equals("co") && str.charAt(i+3) == 'e')
count++;
return count;
}

How to add together an array representation of an integer with different number of digits?

How would I add together two integers with different number of digits, using an array, without causing an out of bounds exception?
For example: 500 + 99
each digit is an element of the array
This is how I'm doing it right now:
int aIILength = infiniteInteger.length-1;
int bIILength = anInfiniteInteger.infiniteInteger.length-1;
for(int f = aIILength; f >0; f--){
int aTempNum = infiniteInteger[f];
int bTempNum = anInfiniteInteger.infiniteInteger[f];
result = aTempNum + bTempNum;
//array representation of sum
tempArray[f] = result;
}
Let the counter in the loop go from 1 and up, and use it to access the digits from the end of each array.
You need a carry to hold the overflow of adding each set of digits.
Loop until you run out of digits in both arrays, and carry is zero.
Check the range when you access the digits from the arrays, and use zero when you run out of digits.
int aIILength = infiniteInteger.length;
int bIILength = anInfiniteInteger.infiniteInteger.length;
int carry = 0;
for(int f = 1; f <= aIILength || f <= bIILength || carry > 0; f++){
int aTempNum;
if (f <= aIILength) {
aTempNum = infiniteInteger[aIILength - f];
} else {
aTempNum = 0;
}
int bTempNum;
if (f <= bIILength) {
bTempNum = anInfiniteInteger.infiniteInteger[bIILength - f];
} else {
bTempNum = 0;
}
result = aTempNum + bTempNum + carry;
tempArray[tempArray.length - f] = result % 10;
carry = result / 10;
}
Note: Make tempArray longer than both the operand arrays, so that it has place for a potential carry to the next digit.

How to count in Java the trailing zeros from an Integer? (Ex: 234000 => 3 zeros)

The title is pretty much self explanatory. :)
1232 => 0
1231030 => 1
2000 => 3
34444400000 => 5
If it fits into an int/long, just check if the number modulo 10 is 0 and keep a counter:
long x = ...
if (x == 0) {
return 0;
}
int counter = 0;
while (x % 10 == 0) {
counter++;
x /= 10;
}
If it's too big to fit in long, store it in a String and count zeroes from the last char:
String s = ...
int counter = 0;
while(counter < s.length() && s.charAt(s.length() - 1 - counter) == '0') {
counter++;
}
Integer class has an inbuilt function to count the trailing zeros.
javadocs
int trailingZeroes = Integer.numberOfTrailingZeros(int i);
Three lines:
int zeroes = 0
while(num%10 == 0 && num != 0) {
zeroes++;
num /= 10;
}
This uses the modulus operator. As long as we can divide by ten without remainder, increment the counter.
Here is another solution using Java 8 Streams:
int trailingZeros = String.valueOf(number).chars()
.reduce(0, (count, ch) -> (ch == '0') ? count + 1 : 0);
This transforms the number to an IntStream. This stream is then reduced using a lambda which resets a counter each time a non-zero char comes up.
You could always just use a regular expression:
Pattern pattern = Pattern.compile("(0+)$");
Matcher matcher = pattern.matcher(String.valueOf(123140000));
Integer trailingZeroes = 0;
if (matcher.find()) {
trailingZeroes = matcher.group(1).length();
}
System.out.println(trailingZeroes);
you can turn the int to a String and iterate in reverse, counting the zeros until you find a char that is not zero:
int countZeros(int x){
String a = Integer.toString(x);
int numOfZeros = 0;
for(int i = a.length() - 1; i >= 0; i--)
if (a.charAt(i) != '0') break;
else numOfZeros ++;
return numOfZeros;
}
Testing with :
System.out.println(countZeros(25000)); will print 3
System.out.println(countZeros(25)); will print 0
Hope this helps.
Not tried this code but this should work.
int counterForZeros=0;
for(long i=10;true;)
{
if(num%i==0)
{
counterForZeros++;
i*=10;
}
else
{
break;
}
}
System.out.println("Number of zeros in "+num+" is "+counterForZeros);
Well, if this is a contest to see who can do it in the fewest lines:
trailingZeroes = String.valueOf(num).length() - String.valueOf(num).replaceAll("0*$","").length();

How to decompress a string such as "a3b3" to aaabbb? [duplicate]

This question already has answers here:
Run-length decompression
(6 answers)
Closed 9 years ago.
I'm trying to take user input like a3b3 and decompress it to aaabbb. This is the code I came up with, and it prints a33b.
String getDecompressedText() {
int i;
int n = 1;
String d = "";
for (i = 0; i < compressedText.length(); i++){
if (Character.isDigit(compressedText.charAt(i)) == true) {
while (n < compressedText.charAt(i)-'0') {
d += compressedText.charAt(i);
n++;
}
}
else
d += compressedText.charAt(i);
}
return d;
here's your algorithm now:
for each character:
if it's not a digit, print it
if it is a digit, print the digit itself "digit - 1" times
not ideal. A few issues:
you printing the digit, not the letter preceding it. Use charAt(i-1)
you increment n, but never reset it back to 1. You should do that in the for loop.
you should indeed print the letter n - 1 times, since it got printed out once all by itself, so that's good
use a StringBuilder
the algorithm will break for things like a14 - 2-digit counts.
public static void main(String[] args) {
String compressedText = "a3b3";
int i;
int n = 1;
String d = "";
for (i = 0; i < compressedText.length(); i++) {
if (Character.isDigit(compressedText.charAt(i))) {
while (n < compressedText.charAt(i) - '0') {
d += compressedText.charAt(i - 1);
n++;
}
n = 0;
} else {
d += compressedText.charAt(i);
}
}
System.out.println(d);
}
Output:
aaabbbb
2 issues:
d += compressedText.charAt(i - 1); // Take the previous character, no the '3'
n = 0; // Reset the counter
Some notes:
Use a StringBuilder for concatenation in a loop
This will only work for single-digit numbers (0 - 9)

Categories