Index out of range when delete - java

Can you help? Get error Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1 when run this program. How to fix rhis? StringBuffer and StringTokenizer is necessary. Also, how can it be done simplier?
import java.util.StringTokenizer;
public class main {
public static int i, n;
public static boolean orly = false;
public static StringBuffer input, tokenStr;
public static StringTokenizer out;
public static char aChar;
public static void main(String[] args) {
input = new StringBuffer("some text");
System.out.println("Начальная строка - " + input.toString());
input = new StringBuffer(input.toString().replaceAll("[^a-z A-Z А-Я а-я]", ""));
if (input.toString().trim().length() != 0) {
out = new StringTokenizer(input.toString());
System.out.println("Форматированая строка - " + input.toString());
n = (out.countTokens());
String[] charSet = { "a", "e", "o", "u", "y" };
for (i = 0; i <= n - 1; i++) {
tokenStr = new StringBuffer(out.nextToken());
aChar = (tokenStr.charAt(0));
String firstchar = tokenStr.toString().substring(0,1);
if (tokenStr.length() > 1) {
for (int i = 0; i <= charSet.length-1; i++) {
if ((!firstchar.equals(charSet[i])) || (!firstchar.toUpperCase().equals(charSet[i]))) {
input.delete(input.indexOf(tokenStr.toString()),input.indexOf(tokenStr.toString())+ tokenStr.length() + 1);
}
}
} else {
input.deleteCharAt(input.indexOf(tokenStr.toString()));
}
}
}
}
}

for (i = 0; i <= n - 1; i++) {
//stuff
if (tokenStr.length() > 1) {
for (int i = 0; i <= charSet.length-1; i++) {
//stuff
}
}
}
in the first for loop, you have a temporary variable i that exists only inside those curly braces. However, in your second for loop, you're creating another variable i. This i will overwrite the first one yet will still be incremented in both loops. You'd best rename the second one to j or something.
Additionally, in:
input.delete(input.indexOf(tokenStr.toString()),input.indexOf(tokenStr.toString())+ tokenStr.length() + 1);
What happens if tokenStr is not in input? Then indexOf will return -1 (predefined behaviour), which is causing this particular Exception.
So.. I just need to delete all words in the String that not starts from "a", "e", "o", "u", "y", "i" and words with one char (like I, a). And create String with words that stay
Consider a different way. Rather than removing the unwanted words from the output StringBuffer, try adding wanted words to the output buffer as you find them. You can describe this logic to walking along your input string and writing down the words you want as you find them.
StringBuffer outString = new StringBuffer();
StringTokenizer st = new StringTokenizer(input.toString());
while(st.hasMoreTokens()){
String currentToken = (String)st.nextToken();
if(currentToken.length() < 2){
continue;
}
for(int i = 0; i < charSet.length; i++){
if(charSet[i] == currentToken.charAt(0)){
outString.append(currentToken);
break;
}
}
}

Related

Suggestions on how to fix this tricky problem in Java

In the given array in Java, [766-09-9090, 766-09-9090, 877-90-9090, 877-90-9090, "S", "T", "U"]
How could we obtain a new array with values like this :
[766-09-9090, 877-90-9090, 877-90-9090, 766-90-9090, "S", "T", "U"]
Note : No changes on non SSN values like "S", "T, "U"
This is my first stab but I am not getting the results I am looking for. Any suggestion would be appreciate
public static modifyArray(List<String> arrays) {
List<String> newArray = new ArrayList<String>();
boolean matchedFound = false;
for (int index = 0; index < arrays.size(); index++) {
if (arrays.get(index).length() == 9 && isValidSSN(arrays.get(index))) {
String nextMatchingSsn = getNextDistinctSsn(arrays);
System.out.println("Next Distinct SSN IS : " + nextMatchingSsn);
if (nextMatchingSsn != "") {
String[] pair = nextMatchingSsn.split(":");
if (pair.length == 2) {
Integer key = Integer.parseInt(pair[1]);
String ssn = pair[0];
swap(arrays.toArray(), index, key);
}
}
newArray.add(nextMatchingSsn);
} else {
System.out.println("Non Matching " + arrays.get(index));
newArray.add(arrays.get(index));
}
}
}
private static boolean isValidSSN(String s) {
if (s.length() != 9) {
throw new IllegalArgumentException("An SSN length must be 9");
}
for (int i = 0; i < 9; i++)
if (!Character.isDigit(s.charAt(i))) {
throw new IllegalArgumentException("SSN must have only digits.");
}
return (true);
}
private static String getNextDistinctSsn(List<String> ssns) {
String firstDiffSsn = "";
String currentSsn = "";
for (int index = 0; index < ssns.size(); index++) {
if (!currentSsn.equals(ssns.get(index)) && currentSsn != "") {
firstDiffSsn = ssns.get(index);
return firstDiffSsn + ":" + index;
} else {
currentSsn = ssns.get(index);
}
}
return firstDiffSsn;`enter code here`
}
public static final <T> void swap (T[] a, int i, int j) {
T t = a[i];
a[i] = a[j];
a[j] = t;
}
This is my first stab but I am not getting the results I am looking for. Any suggestion would be appreciated. So basically, if I have to write a unit test my expected result would look something like this:
public void validateResult(){
}
I can see a number of problems.
Your code is creating a new list (called newArray !?!) and populating it, but then not using it.
Your code is splitting SSNs on a : character, but the input data has no : characters.
Your SSN validation method will throw an unchecked exception if it encounters something that is not a valid SSN, but your code expects it to return false in that scenario.
This is wrong: currentSsn != "". Do not use == or != to compare strings. You are liable to get an incorrect result.
And so on.

Count each element in string array

Hey guys this is my code for splitting the array first without using any inbuilt functions. It works fine, my question is in the second part.
static String[] split(String ss) {
String[] a = new String[1];
String s = "";
for (int i = 0; i < ss.length(); i++) {
if (ss.charAt(i) == ' ') {
s += ", "
} else {
s += ss.charAt(i);
}
for (int j = 0; j < a.length; j++) {
a[j] = "[" + s + "]";
}
}
return a;
}
I need now to count each letter in a word and give it out also without inbuilt functions as split, chartoarray and so on.
this is to what i came so far.
for example String="This is just an example". it should give out
This=4
is=2
..
static String[][] LettersCount(String[] array) {
int count=0;
String [][] a =new String[array.length][array.length];
String s= "" + Arrays.toString(array);
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') {
count = 0;
} else {
count++;
}
You can use property of character that it has a numerical value after all. Lets use it as index and store the counts in an array. (so we will mimic Map this way)
int[] counter = new int[256] ;// this will hold count of all letters
counter[(int) character]++; // this is how you do the counting
public class JavaArrayLengthTest {
public static void main(String[] args) {
String[] testArray = { "A", "B", "C" };
int arrayLength = testArray.length;
System.out.println("The length of the array is: " + arrayLength);
}
}

implement basic string compression

I am working on question 1.5 from the book Cracking The Coding interview. The problem is to take a string "aabcccccaaa" and turn it into a2b1c5a3.
If the compressed string is not smaller than the original string, then return the original string.
My code is below. I used an ArrayList because I would not know how long the compressed string would be.
My output is [a, 2, b, 1, c, 5], aabc, []. When the program gets to the end of string, it doesn't have a character to compare the last character too.
import java.util.*;
import java.io.*;
public class stringCompression {
public static void main(String[] args) {
String a = "aabcccccaaa";
String b = "aabc";
String v = "aaaa";
check(a);
System.out.println("");
check(b);
System.out.println("");
check(v);
}
public static void check(String g){
ArrayList<Character> c = new ArrayList<Character>();
int count = 1;
int i = 0;
int h = g.length();
for(int j = i + 1; j < g.length(); j++)
{
if(g.charAt(i) == g.charAt(j)){
count++;
}
else {
c.add(g.charAt(i));
c.add((char)( '0' + count));
i = j;
count = 1;
}
}
if(c.size() == g.length()){
System.out.print(g);
}
else{
System.out.print(c);
}
}
}
In the last loop you're not adding the result to the array. When j = g.length() still needs to add the current char and count to the array. So you could check the next value of j before increment it:
for(int j = i + 1; j < g.length(); j++)
{
if(g.charAt(i) == g.charAt(j)){
count++;
}
else {
c.add(g.charAt(i));
c.add((char)( '0' + count));
i = j;
count = 1;
}
if((j + 1) = g.length()){
c.add(g.charAt(i));
c.add((char)( '0' + count));
}
}
I would use a StringBuilder rather than an ArrayList to build your compressed String. When you start compressing, the first character should already be added to the result. The count of the character will be added once you've encountered a different character. When you've reached the end of the String you should just be appending the remaining count to the result for the last letter.
public static void main(String[] args) throws Exception {
String[] data = new String[] {
"aabcccccaaa",
"aabc",
"aaaa"
};
for (String d : data) {
System.out.println(compress(d));
}
}
public static String compress(String str) {
StringBuilder compressed = new StringBuilder();
// Add first character to compressed result
char currentChar = str.charAt(0);
compressed.append(currentChar);
// Always have a count of 1
int count = 1;
for (int i = 1; i < str.length(); i++) {
char nextChar = str.charAt(i);
if (currentChar == nextChar) {
count++;
} else {
// Append the count of the current character
compressed.append(count);
// Set the current character and count
currentChar = nextChar;
count = 1;
// Append the new current character
compressed.append(currentChar);
}
}
// Append the count of the last character
compressed.append(count);
// If the compressed string is not smaller than the original string, then return the original string
return (compressed.length() < str.length() ? compressed.toString() : str);
}
Results:
a2b1c5a3
aabc
a4
You have two errors:
one that Typo just mentioned, because your last character was not added;
and another one, if the original string is shorter like "abc" with only three chars: "a1b1c1" has six chars (the task is "If the compressed string is not smaller than the original string, then return the original string.")
You have to change your if statement, ask for >= instead of ==
if(c.size() >= g.length()){
System.out.print(g);
} else {
System.out.print(c);
}
Use StringBuilder and then iterate on the input string.
private static string CompressString(string inputString)
{
var count = 1;
var compressedSb = new StringBuilder();
for (var i = 0; i < inputString.Length; i++)
{
// Check if we are at the end
if(i == inputString.Length - 1)
{
compressedSb.Append(inputString[i] + count.ToString());
break;
}
if (inputString[i] == inputString[i + 1])
count++;
else
{
compressedSb.Append(inputString[i] + count.ToString());
count = 1;
}
}
var compressedString = compressedSb.ToString();
return compressedString.Length > inputString.Length ? inputString : compressedString;
}

Java words reverse

I am new to Java and I found a interesting problem which I wanted to solve. I am trying to code a program that reverses the position of each word of a string. For example, the input string = "HERE AM I", the output string will be "I AM HERE". I have got into it, but it's not working out for me. Could anyone kindly point out the error, and how to fix it, because I am really curious to know what's going wrong. Thanks!
import java.util.Scanner;
public class Count{
static Scanner sc = new Scanner(System.in);
static String in = ""; static String ar[];
void accept(){
System.out.println("Enter the string: ");
in = sc.nextLine();
}
void intArray(int words){
ar = new String[words];
}
static int Words(String in){
in = in.trim(); //Rm space
int wc = 1;
char c;
for (int i = 0; i<in.length()-1;i++){
if (in.charAt(i)==' '&&in.charAt(i+1)!=' ') wc++;
}
return wc;
}
void generate(){
char c; String w = ""; int n = 0;
for (int i = 0; i<in.length(); i++){
c = in.charAt(i);
if (c!=' '){
w += c;
}
else {
ar[n] = w; n++;
}
}
}
void printOut(){
String finale = "";
for (int i = ar.length-1; i>=0;i--){
finale = finale + (ar[i]);
}
System.out.println("Reversed words: " + finale);
}
public static void main(String[] args){
Count a = new Count();
a.accept();
int words = Words(in);
a.intArray(words);
a.generate();
a.printOut();
}
}
Got it. Here is my code that implements split and reverse from scratch.
The split function is implemented through iterating through the string, and keeping track of start and end indexes. Once one of the indexes in the string is equivalent to a " ", the program sets the end index to the element behind the space, and adds the previous substring to an ArrayList, then creating a new start index to begin with.
Reverse is very straightforward - you simply iterate from the end of the string to the first element of the string.
Example:
Input: df gf sd
Output: sd gf df
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
public class Count{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("Enter string to reverse: ");
String unreversed = scan.nextLine();
System.out.println("Reversed String: " + reverse(unreversed));
}
public static String reverse(String unreversed)
{
ArrayList<String> parts = new ArrayList<String>();
String reversed = "";
int start = 0;
int end = 0;
for (int i = 0; i < unreversed.length(); i++)
{
if (unreversed.charAt(i) == ' ')
{
end = i;
parts.add(unreversed.substring(start, end));
start = i + 1;
}
}
parts.add(unreversed.substring(start, unreversed.length()));
for (int i = parts.size()-1; i >= 0; i--)
{
reversed += parts.get(i);
reversed += " ";
}
return reversed;
}
}
There is my suggestion :
String s = " HERE AM I ";
s = s.trim();
int j = s.length() - 1;
int index = 0;
StringBuilder builder = new StringBuilder();
for (int i = j; i >= 0; i--) {
Character c = s.charAt(i);
if (c.isWhitespace(c)) {
index = i;
String r = s.substring(index+1, j+1);
j = index - 1;
builder.append(r);
builder.append(" ");
}
}
String r=s.substring(0, index);
builder.append(r);
System.out.println(builder.toString());
From adding debug output between each method call it's easy to determine that you're successfully reading the input, counting the words, and initializing the array. That means that the problem is in generate().
Problem 1 in generate() (why "HERE" is duplicated in the output): after you add w to your array (when the word is complete) you don't reset w to "", meaning every word has the previous word(s) prepended to it. This is easily seen by adding debug output (or using a debugger) to print the state of ar and w each iteration of the loop.
Problem 2 in generate() (why "I" isn't in the output): there isn't a trailing space in the string, so the condition that adds a word to the array is never met for the last word before the loop terminates at the end of the string. The easy fix is to just add ar[n] = w; after the end of the loop to cover the last word.
I would use the split function and then print from the end of the list to the front.
String[] splitString = str.split(" ");
for(int i = splitString.length() - 1; i >= 0; i--){
System.out.print(splitString[i]);
if(i != 0) System.out.print(' ');
}
Oops read your comment. Disregard this if it is not what you want.
This has a function that does the same as split, but not the predefined split function
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the string : ");
String input = sc.nextLine();
// This splits the string into array of words separated with " "
String arr[] = myOwnSplit(input.trim(), ' '); // ["I", "AM", "HERE"]
// This ll contain the reverse string
String rev = "";
// Reading the array from the back
for(int i = (arr.length - 1) ; i >= 0 ; i --) {
// putting the words into the reverse string with a space to it's end
rev += (arr[i] + " ");
}
// Getting rid of the last extra space
rev.trim();
System.out.println("The reverse of the given string is : " + rev);
}
// The is my own version of the split function
public static String[] myOwnSplit(String str, char regex) {
char[] arr = str.toCharArray();
ArrayList<String> spltedArrayList = new ArrayList<String>();
String word = "";
// splitting the string based on the regex and bulding an arraylist
for(int i = 0 ; i < arr.length ; i ++) {
char c = arr[i];
if(c == regex) {
spltedArrayList.add(word);
word = "";
} else {
word += c;
}
if(i == (arr.length - 1)) {
spltedArrayList.add(word);
}
}
String[] splitedArray = new String[spltedArrayList.size()];
// Converting the arraylist to string array
for(int i = 0 ; i < spltedArrayList.size() ; i++) {
splitedArray[i] = spltedArrayList.get(i);
}
return splitedArray;
}

Can anybody help me to correct the following code?

Please help me to identify my mistakes in this code. I am new to Java. Excuse me if I have done any mistake. This is one of codingbat java questions. I am getting Timed Out error message for some inputs like "xxxyakyyyakzzz". For some inputs like "yakpak" and "pakyak" this code is working fine.
Question:
Suppose the string "yak" is unlucky. Given a string, return a version where all the "yak" are removed, but the "a" can be any char. The "yak" strings will not overlap.
public String stringYak(String str) {
String result = "";
int yakIndex = str.indexOf("yak");
if (yakIndex == -1)
return str; //there is no yak
//there is at least one yak
//if there are yaks store their indexes in the arraylist
ArrayList<Integer> yakArray = new ArrayList<Integer>();
int length = str.length();
yakIndex = 0;
while (yakIndex < length - 3) {
yakIndex = str.indexOf("yak", yakIndex);
yakArray.add(yakIndex);
yakIndex += 3;
}//all the yak indexes are stored in the arraylist
//iterate through the arraylist. skip the yaks and get non-yak substrings
for(int i = 0; i < length; i++) {
if (yakArray.contains(i))
i = i + 2;
else
result = result + str.charAt(i);
}
return result;
}
Shouldn't you be looking for any three character sequence starting with a 'y' and ending with a 'k'? Like so?
public static String stringYak(String str) {
char[] chars = (str != null) ? str.toCharArray()
: new char[] {};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == 'y' && chars[i + 2] == 'k') { // if we have 'y' and two away is 'k'
// then it's unlucky...
i += 2;
continue; //skip the statement sb.append
} //do not append any pattern like y1k or yak etc
sb.append(chars[i]);
}
return sb.toString();
}
public static void main(String[] args) {
System.out.println(stringYak("1yik2yak3yuk4")); // Remove the "unlucky" strings
// The result will be 1234.
}
It looks like your programming assignment. You need to use regular expressions.
Look at http://www.vogella.com/articles/JavaRegularExpressions/article.html#regex for more information.
Remember, that you can not use contains. Your code maybe something like
result = str.removeall("y\wk")
you can try this
public static String stringYak(String str) {
for (int i = 0; i < str.length(); i++) {
if(str.charAt(i)=='y'){
str=str.replace("yak", "");
}
}
return str;
}

Categories