java.lang.StringIndexOutOfBoundsException: String index out of range: 45 - java

I'm trying to make a program that takes in a string like: KKKKKKKKKKKKKBCCDDDDDDDDDDDDDDDKKKKKMNUUUGGGGG
And returns something like this: $K13BCC$D15$K5MNUUU$G5
Another example is XYZAAAAAAGGTCCCCCCTTTAAAAAAAAAAAAAAKK
Returns: XYZ*A6GGT*C6TTT*A14KK
But i get this StringIndexOutOfBoundsException when i try the first input, can anyone tell me why? Here's my code:
import java.util.Scanner;
class RunLengthEncoding {
public static void main(String[] args) {
Scanner h = new Scanner(System.in);
String s;
char g;
System.out.print("Enter input string: ");
s = h.next();
for (int d = 0; d < s.length(); d++){
if (!Character.isUpperCase(s.charAt(d))){
System.out.print("Bad input.");
return;
}
}
System.out.print("Enter flag character: ");
g = h.next().charAt(0);
if (g != '#' && g != '$' && g != '&' && g != '*'){
System.out.println("Bad input.");
return;
}
char c = s.charAt(0);
String encode = "";
for (int n = 0; n < s.length() - 1; n++){
int k = 0;
int j = 0;
while (k + n < s.length() && s.charAt(k + n) == c){
j++;
k++;
}
if (j > 3){
encode += g;
encode += c;
encode += j;
n += j - 1;
}
else {
encode += c;
}
c = s.charAt(n + 1);
}
System.out.println("Encoded: " + encode);
}
}

The reason that you are getting an out of bounds exception is because you are incrementing n outside of the for loop statement. You do this when you are doing n += j - 1;. This gives you an out of bounds exception because when you do c = s.charAt(n + 1);, n could be greater than or equal to the length of the string. As a general rule, you should not alter the value of the iteration variable in the for loop anywhere outside of the for loop. It makes the code harder to debug.

For anyone interested in the solution I made:
import java.util.Scanner;
public class RunLengthEncoding {
public static void main(String[] args){
Scanner h = new Scanner(System.in);
String s;
char g;
StringBuilder encode = new StringBuilder();
System.out.print("Enter input string: ");
s = h.next();
for (int d = 0; d < s.length(); d++) {
if (!Character.isUpperCase(s.charAt(d))) {
System.out.print("Bad input.");
return;
}
}
System.out.print("Enter flag character: ");
g = h.next().charAt(0);
if (g != '#' && g != '$' && g != '&' && g != '*') {
System.out.println("Bad input.");
return;
}
for (int n = 0; n < s.length(); n++) {
int k = 1;
while (n < s.length() - 1 && s.charAt(n) == s.charAt(n + 1)) {
k++;
n++;
}
if (k > 3) {
encode.append(g).append(s.charAt(n)).append(k);
}
else {
for (int c = 0; c < k; c++) {
encode.append(s.charAt(n));
}
}
}
System.out.print("Encoded: " + encode);
}
}

Related

Rearrange words in string in alphabetical order

I'm trying to rearrange words in any given string (20 words or less). I'm having this issue because I can not get the last word in the string to print. I tried modifying the loop range, but I am not able to fix the issue.
public class ListString {
String[] list = new String[20];
int n = 0;
public void read() {
Scanner in = new Scanner(System.in);
System.out.println("Please enter the sentence");
String s = in.nextLine();
String temp = "";
for (int i = 0; i < s.length(); i++)
{
char ch = s.charAt(i);
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) // range from a to z
temp = temp + ch;
else
{
if (temp.length() > 0)
{
list[n] = temp;
n++;
temp = "";
}
}
}
}
public void print() {
System.out.print(list[0]);
for (int i = 0; i < n; i++)
System.out.print(" " + list[i]);
System.out.println(" ");
}
public void sort() {
for (int i = 0; i < n; i++) {
String key = list[i];
int j = i - 1;
while (j >= 0 && (list[j].compareToIgnoreCase(key) > 0))
{
list[j + 1] = list[j];
j = j - 1;
}
list[j + 1] = key;
}
}
}
That happens, when you hit end of the string and temp is not empty. To fix it you can add same if statement after loop:
for(int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
temp = temp + ch;
} else {
if(temp.length() > 0) {
list[n] = temp;
n++;
temp = "";
}
}
}
if(temp.length() > 0) {
list[n] = temp;
n++;
temp = "";
}
Also you would need to fix your output to not print first word twice:
public void print() {
for(int i = 0; i < n; i++) {
System.out.print(list[i] + " ");
}
System.out.println();
}
Output before fix:
a b c d e f g h i j k l m n o p q r s t
a a b c d e f g h i j k l m n o p q r s
Output after fix:
a b c d e f g h i j k l m n o p q r s t
a b c d e f g h i j k l m n o p q r s t
Update:
Also you can solve your problem in one line, using streams
public void read() {
Scanner in = new Scanner(System.in);
System.out.println("Please enter the sentence");
String s = in.nextLine();
String[] list = Arrays.stream(s.split(" ")).limit(20).sorted().toArray(String[]::new);
}
It splits input string by space character, takes first 20 words, sorts them and creates an array of them.
Output:
t s r q p o n m l k j i h g f e d c b a z z z z z
a b c d e f g h i j k l m n o p q r s t
You don't need to handle the end of the string explicitly: by using integer pointers to the start and end of words, you can do it as follows:
int start = 0;
while (start < s.length()) {
// Increment a start pointer until it points to the end of the string or the start of a word.
while (start < s.length() && !isLetter(s.charAt(start))) {
start++;
}
// Increment an end pointer until it points to the end of the string or a non-word character.
int end = start;
while (end < s.length() && isLetter(s.charAt(end))) {
end++;
}
if (start == end) {
// You reached the end of the string.
break;
}
// Grab the portion of the string between start and end, this is a word.
list[n++] = s.substring(start, end);
// Set up the start pointer to point to the end of this word, for the next iteration.
start = end;
}
where isLetter(char) is a method that checks if the argument is between A and Z (in either case).
I have seen a variation on this method which avoids the inner while loops: I don't like this as much, as I think it's less clear to read; but it doesn't have quite so much repetitive checking of the length (I think this code works, not tried it):
for (int start = 0, end = 0; start < s.length();) {
if (!isLetter(s.charAt(start))) {
start++;
end = start;
} else if (isLetter(s.charAt(end))) {
end++;
if (end >= s.length() || !isLetter(s.charAt(end))) {
list[n++] = s.substring(start, end);
start = end;
}
}
}

How to keep the desired letter and hide the other characters with "*"? Is there a simpler and efficient way?

I want to keep the desired letter that the user inputs using the scanner and hide all the other characters with a "*", how would I do that with a for loop or substring? I managed to do it with a for loop for one letter the user inputs, but In total, this needs to happen with 5 different letters the user inputs using a scanner.
Sample input: 4(option #), dog(mysteryphrase), o(letter)
Sample output: *o*
This needs to happen with 5 letters, how would I do that?
This was my attempt:
else if (option == 4){
int counter = 1;
int counter2 = 0;
boolean go = true;
char letter = keyboard.next().charAt(0);
String r1 = "";
for (int y = 0; y < mysteryphrase.length(); y++){
char n1 = mysteryphrase.charAt(y);
if (n1 == letter)
r1+=n1;
else
r1+="*";
}
System.out.println(r1);
char letter2 = keyboard.next().charAt(0);
String r2 = "";
for (int x = 0; x < mysteryphrase.length(); x++){
char n2 = mysteryphrase.charAt(x);
if (n2 == letter2)
r2+=n2;
else
r2+="*";
}
System.out.println(r2);
char letter3 = keyboard.next().charAt(0);
String r3 = "";
for (int w = 0; w < mysteryphrase.length(); w++){
char n3 = mysteryphrase.charAt(w);
if (n3 == letter3)
r3+=n3;
else
r3+="*";
}
System.out.println(r3);
char letter4 = keyboard.next().charAt(0);
String r4 = "";
for (int z = 0; z < mysteryphrase.length(); z++){
char n4 = mysteryphrase.charAt(z);
if (n4 == letter4)
r4+=n4;
else
r4+="*";
}
System.out.println(r4);
char letter5 = keyboard.next().charAt(0);
String r5 = "";
for (int s = 0; s < mysteryphrase.length(); s++){
char n5 = mysteryphrase.charAt(s);
if (n5 == letter5)
r5+=n5;
else
r5+="*";
Although I managed to hide the letters with a "*", one another requirement is:
And whenever the letter is not in the word, let's say:
Sample input: 4, dog, z
Then it should output:
Sample output: Z is not in the word
This is where I'm stuck, can you please help? Thanks
Try this updated version:
String letters = "";
for (int i = 0; i < 5; i++) {
letters += keyboard.next().charAt(0) + ", ";
}
String r = "";
boolean found = false;
for (int y = 0; y < mysteryphrase.length(); y++) {
char n = mysteryphrase.charAt(y);
if (letters.indexOf(n) > -1) {
r += n;
found = true;
} else {
r += "*";
}
}
if (!found) {
System.out.println("Letters " + letters + " not in the word");
} else {
System.out.println(r);
}
Output for input a b c d e and mysteryphrase = "acknowledgement":
ac*****ed*e*e**
Output for input q b z r s and mysteryphrase = "acknowledgement":
Letters q,b,z,r,s not in the word
Or, if you have to do this task separately for each letter (not for all five ones together), you can extract a single method and call it 5 times:
for (int i = 0; i < 5; i++) {
char letter = keyboard.next().charAt(0);
String r = "";
boolean found = false;
for (int j = 0, n = mysteryphrase.length(); j < n; j++) {
char c = mysteryphrase.charAt(0);
if (c == letter) {
r += c;
found = true;
} else {
r += '*';
}
}
if (!found) {
System.out.println("Letter " + letter + " not in the word");
} else {
System.out.println(r);
}
}
Output:
Letter b not in the word
******l*****
a***********
*c**********
**k*********

I get java.lang.StringIndexOutOfBoundsException when translating c++ code into java code

I'm trying to solve this problem
https://vjudge.net/problem/UVALive-6805
I found solution but in c++ , Can anybody help me converting it to java code. I'm very newbie to programming
I tried a lot of solutions but non of them work.
Please I need help in this if possible
I don't know for example what is the equivalent for .erase function in c++ in java
Also is is sbstr in c++ provide different result from java ?
#include <iostream>
#include <string>
using namespace std;
int syllable(string word)
{
int L = word.size();
int syllable;
if (L>=7)
{
syllable = 3;
}
else if (L==6)
{
int indicator = 0;
for (int k=0; k<=L-2; k++)
{
string subword = word.substr(k, 2);
if (subword == "ng" || subword == "ny")
{
indicator++;
}
}
if (indicator == 0)
{
syllable = 3;
}
else
{
syllable = 2;
}
}
else if (L == 4 || L == 5)
{
syllable = 2;
}
else if (L == 3)
{
char Char = word[0];
if (Char=='a' || Char=='A' || Char=='e' || Char=='E' || Char=='i' || Char=='I' || Char=='o' || Char=='O' || Char=='u' || Char=='U')
{
syllable = 2;
}
else
{
syllable = 1;
}
}
else
{
syllable = 1;
}
return syllable;
}
int main()
{
string word;
int T;
cin >> T;
for (int i=1; i<=T; i++)
{
int syl[] = {0, -1, -2, -3};
string rhy[] = {"a", "b", "c", "d"};
int verse = 0;
int stop = 0;
while (stop == 0)
{
cin >> word;
int L = word.size();
char end = word[L-1];
if (end == '.')
{
stop = 1;
}
if (word[L-1] == ',' || word[L-1] == '.')
{
word = word.erase(L-1, 1);
L = word.size();
}
if (verse<=3)
{
syl[verse] = syl[verse] + syllable(word);
}
if (end == ',' || end == '.')
{
if (verse<=3)
{
rhy[verse] = word.substr(L-2, 2);
}
verse++;
if (verse<=3)
{
syl[verse] = 0;
}
}
}
int A = 0, B = 0, C = 0, D = 0;
for (int k=0; k<4; k++)
{
if (syl[k] >= 8 && syl[k] <= 12)
{
A = A + 10;
}
}
for (int k=0; k<2; k++)
{
if (rhy[k] == rhy[k+2])
{
B = B + 20;
}
}
for (int k=0; k<2; k++)
{
if (syl[k] == syl[k+2])
{
C = C + 10;
}
}
if (verse > 4)
{
D = (verse - 4) * 10;
}
int E = A + B + C - D;
cout << "Case #" << i << ": " << A << " " << B << " " << C << " " << D << " " << E << endl;
}
}
here is my trying
import java.util.*;
public class First {
public static int syllable(String word) {
int L = word.length();
int syllable;
if (L >= 7) {
syllable = 3;
} else if (L == 6) {
int indicator = 0;
for (int k = 0; k < L - 3; k++) {
String subword = word.substring(k, 2);
if (subword == "ng" || subword == "ny") {
indicator++;
}
}
if (indicator == 0) {
syllable = 3;
} else {
syllable = 2;
}
} else if (L == 4 || L == 5) {
syllable = 2;
} else if (L == 3) {
char Char = word.charAt(0);
if (Char == 'a' || Char == 'A' || Char == 'e' || Char == 'E' || Char == 'i' || Char == 'I' || Char == 'o'
|| Char == 'O' || Char == 'u' || Char == 'U') {
syllable = 2;
} else {
syllable = 1;
}
} else {
syllable = 1;
}
return syllable;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String word;
int T;
T = sc.nextInt();
for (int i = 1; i <= T; i++) {
int syl[] = { 0, -1, -2, -3 };
String rhy[] = { "a", "b", "c", "d" };
int verse = 0;
int stop = 0;
while (stop == 0) {
word = sc.next();
int L = word.length();
char end = word.charAt(L-1);
if (end == '.') {
stop = 1;
}
if (word.charAt(L-1) == ',' || word.charAt(L-1) == '.') {
word.substring(L-1, 1);
L = word.length();
}
if (verse <= 3) {
syl[verse] = syl[verse] + syllable(word);
}
if (end == ',' || end == '.') {
if (verse <= 3) {
rhy[verse] = word.substring(L - 2, 2);
}
verse++;
if (verse <= 3) {
syl[verse] = 0;
}
}
}
int A = 0, B = 0, C = 0, D = 0;
for (int k = 0; k < 4; k++) {
if (syl[k] >= 8 && syl[k] <= 12) {
A = A + 10;
}
}
for (int k = 0; k < 2; k++) {
if (rhy[k] == rhy[k + 2]) {
B = B + 20;
}
}
for (int k = 0; k < 2; k++) {
if (syl[k] == syl[k + 2]) {
C = C + 10;
}
}
if (verse > 4) {
D = (verse - 4) * 10;
}
int E = A + B + C - D;
System.out.println("Case #" + i + ": " + A + " " + B + " " + C + " " + D + " " + E);
}
}
}
The Exception is thrown by your second and your third call of String substring method. Your beginIndex is higher than your endIndex. As you can see in here https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int,%20int) beginIndex always has to be lower than the endIndex.
Before answering your question, there are some important points to mention in regards to Strings and Java in general.
Strings are immutable (This also applies to C++). This means that no method called on a String will change it, and that all methods simply return new versions of the original String with the operations done on it
The substring method in java has two forms.
One takes in beginIndex and returns everything from beginIndex to str.length() - 1 (where str represents a String)
The other takes in the beginIndex, and the endIndex, and returns everything from beginIndex to endIndex - 1. The beginIndex should never be larger than endIndex otherwise it throws an IndexOutOfBoundsException
C++'s substring method (string::substr()) takes in the beginning "index" and takes in the number of characters after it to include in the substring. So by doing substr(L-2, 2) you get the last two characters of the string.
Java will never allow you to go out of bounds. That means you need to constantly check whether you are within the bounds of anything you are iterating through.
With all this in mind, I would go and verify that all of the substring() method calls are returning the proper range of characters, and that you are properly reassigning the values returned from substring() to the proper variable.
To mimic C++'s string::erase(), depending on what part of the word you want to erase, you want to get the substring of the part before and the substring of the part after it and add them together.
Ex. Lets say I have a String line = "I do not like the movies"; Since it is impossible for anyone to not like movies, we want to cut out the word not
We do this by doing what I said above
String before = line.substring(0, 5); // This gives us "I do " since it goes up to but not including the 5th index.
String after = line.substring(5 + 3); // This gives us the rest of the string starting after the word "not" because not is 3 characters long and this skips to the 3rd index after index 5 (or index 8)
line = before + after; // This'll add those two Strings together and give you "I do like the movies"
Hope this helps!

Check if string contains a character with for loop?

I am currently working on a simple code that will check if an user inputted String contains character(s) that are specified in the for loop.
My current code
import java.util.Scanner;
public class AutumnLeaves {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int G = 0;
int R = 0;
int Y = 0;
int B = 0;
String S = sc.nextLine();
for (int i = 0; i < S.length(); i++) {
if (S.contains("G")) {
G++;
} else {
if (S.contains("R")) {
R++;
} else {
if (S.contains("Y")) {
Y++;
} else {
if (S.contains("B")) {
B++;
}
}
}
}
}
int total = G + R + Y + B;
System.out.println(G/total);
System.out.println(R/total);
System.out.println(Y/total);
System.out.println(B/total);
}
}
As you can see, it checks if the string contains such characters and it will increase the counter of the character by one. However when I run it, I don't receive the results I predicted.
If I input GGRY, it outputs 1 0 0 0. When the desired out put is
0.5
0.25
0.25
0.0
Any help would be appreciated!
The problem is that S.contains returns true if the whole string contains the given character. S.charAt should solve your problem:
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == 'G') G++;
else if (S.charAt(i) == 'R') R++;
else if (S.charAt(i) == 'Y') Y++;
else if (S.charAt(i) == 'B') B++;
}
Also, dividing integers will return an integer (rounded down). As such your output would always be 0 unless all the characters are the same. Just cast them to double before printing:
System.out.println((double) G/total);
System.out.println((double) R/total);
System.out.println((double) Y/total);
System.out.println((double) B/total);
Edit: As pointed out by Sumit Gulati in a comment, a switch statement will have better performance in Java 7. Also, as David Conrad pointed out using only ifs in the for loop would work too as the conditions are mutually exclusive.
Your earlier code S.contains("some character") was finding the index of the character in the entire string. Use S.charAt(i) to specifically find the index at ith location in the string.
Finally, you need to convert the integer to floating point in order to print output as floating values.
public class AutumnLeaves {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int G = 0;
int R = 0;
int Y = 0;
int B = 0;
String S = sc.nextLine();
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == 'G') {
G++;
} else {
if (S.charAt(i) == 'R') {
R++;
} else {
if (S.charAt(i) == 'Y') {
Y++;
} else {
if (S.charAt(i) == 'B') {
B++;
}
}
}
}
}
int total = G + R + Y + B;
System.out.println(G * 1.0 / total);
System.out.println(R * 1.0 / total);
System.out.println(Y * 1.0 / total);
System.out.println(B * 1.0 / total);
}
}

Making a hollow diamond with a word in it

What I need is a little modification to my code so that every part of my hollow diamond prints a letter of the word "HURRICANE"
My code is:
String st1 = "HURRICANE";
int a = 0;
for (int i = 5; i >= 1; i--) {
for (int j = 1; j <= 9; j++) {
if (j == i || (10 - i) == j) {
System.out.print(st1.charAt(a)); //needs change
} else {
System.out.print(' ');
}
}
System.out.println();
}
for (int i = 2; i <= 5; i++) {
for (int j = 1; j <= 9; j++) {
if (j == i || (10 - i) == j) {
System.out.print(st1.charAt(a)); //needs change
} else {
System.out.print(' ');
}
}
System.out.println();
}
The output comes out as:
H
H H
H H
H H
H H
H H
H H
H H
H
I need to modify my "charAt" statement a little so it comes out to be:
H
U U
R R
R R
I I
C C
A A
N N
E
How should I make my print statement?
It's worth noting that the example provided only works for Strings the same length as "HURRICANE". A superior solution would work for all strings.
Partial solution for you to complete, since I guess it's your coursework and I don't want you to copy / paste / fail exams :P
public static void main(String[] args) {
String st1 = "HURRICANE";
char[] st1CharArray = st1.toCharArray();
int maxSpaces = st1CharArray.length / 2 + 1;
for (int i = 0; i <= st1CharArray.length / 2; i++) {
if (i == 0) {
System.out.println(getSpacesString(maxSpaces) + st1CharArray[i]);
} else {
System.out.println(getSpacesString(maxSpaces - i)
+ st1CharArray[i] + getSpacesString(i * 2 - 1)
+ st1CharArray[i]);
}
}
// Loop from st1CharArray.length / 2 + 1 and get the second half done.
}
private static String getSpacesString(int numberOfSpaces) {
StringBuilder strBuilder = new StringBuilder();
for (int i = 0; i < numberOfSpaces; i++) {
strBuilder.append(" ");
}
return strBuilder.toString();
}
//: Playground - noun: a place where people can play
import UIKit
var name : String = "HURRICANE"
var dimensions : Int = name.count - 1
var k : Int = 0
for rows in 0...dimensions{
for columns in 0...dimensions{
k = abs( (dimensions/2) - rows )
if columns == k || columns == dimensions - k{
print(Array(name)[rows], terminator: "")
}
else{
print(" ", terminator: "" )
}
}
print("")
}
String st1 = "HURRICANE";
int a = 0;
for (int i = 5; i >= 1; i--) {
for (int j = 1; j <= 9; j++) {
if (j == i || (10 - i) == j) {
System.out.print(st1.charAt(5 - i));
} else {
System.out.print(' ');
}
}
System.out.println();
}
for (int i = 2; i <= 5; i++) {
for (int j = 1; j <= 9; j++) {
if (j == i || (10 - i) == j) {
System.out.print(st1.charAt(3 + i));
} else {
System.out.print(' ');
}
}
System.out.println();
}
Let's assume that a word has an odd number of characters, otherwise we get a crooked diamond.
Try it online!
public static void main(String[] args) {
String str = "abrahadabra";
int n = str.length() / 2;
for (int i = -n, ch = 0; i <= n && ch < str.length(); i++, ch++) {
for (int j = -n; j <= n; j++)
if (Math.abs(i) + Math.abs(j) == n)
System.out.print(str.charAt(ch));
else
System.out.print(" ");
System.out.println();
}
}
Output:
a
b b
r r
a a
h h
a a
d d
a a
b b
r r
a

Categories