import java.util.Scanner;
public class CountVowel{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
Getting the size of the array:
System.out.println("Type how many words will be typed: ");
int input = scan.nextInt();
Filling array with string values
String[] ar1 = new String[input];
for(int i = 0; i < ar1.length; i++){
System.out.println("Type the elements of array with words: ");
ar1[i] = scan.next();
}
Output of the program :
System.out.println( input + " words are typed and " +
countVowels(ar1) +
" of them contain more than 3 vowels.");
}
The method that counts vowels:
public static int countVowels(String[] ar1){ // this method counts
int a = 0;
String[] ar2 = new String[]{"a", "e", "i", "u", "y", "o"};
for(int i = 0; i < ar1.length; i++){
for(String s : ar2){
if(ar1[i].toLowerCase().contains(s)){
a++;
}
}
}
return a;
}
}
The method above is to check the vowels, but i dont know how to make it check if
there are more than 3 vowels.
Another solution with replaceAll method.
The main idea is to substract from word.length() the same word length without vowels. And check the difference.
public static int countVowels(String[] ar1){
int a = 0;
for (String word : ar1) {
int i = word.length() - word.toLowerCase().replaceAll("[aeyiuo]", "").length();
if (i >= 3) {
a++;
}
}
return a;
}
Or you can use matches() as #pkgajulapalli suggested. It can be quite concise with stream api:
long count = Arrays.stream(words)
.filter(s -> s.toLowerCase().matches("(.*[aeyiuo].*){3,}"))
.count();
public static int countVowels(String[] ar1) { // this method counts
int vowelPerWord = 0;
int totalWordsWithThreeVowels = 0;
char[] ar2 = new char[] { 'a', 'e', 'i', 'u', 'y', 'o' };
for (int i = 0; i < ar1.length; i++) {
vowelPerWord = 0;
for (int j = 0; j < ar1[i].length(); j++) {
for (int k = 0; k < ar2.length; k++) {
if (ar2[k] == (ar1[i].charAt(j))) {
vowelPerWord++;
}
}
}
if (vowelPerWord >= 3) {
totalWordsWithThreeVowels++;
}
}
return totalWordsWithThreeVowels;
}
EDIT
alright now i fixed the error and edited the variablenames to make a bit more sense. although this is O(n*m) i believe (where n is the number of strings and m is the number of char the longest string has) (not so good complexity) it gets the job done ar1 in this case is your input of strings, ar2 are just the vowels that exist.
so you go through every string in ar1 and set "vowelPerWord" to 0, go through every single char in every string and check if it is a vowel increase the vowelPerWord by 1. at the end, after you went through every char of that string you check if there were 3 or more vowels, if so increase the totalWordsWithThreeVowels, which at the end is returned.
What you need is an additional loop and count. Something like this:
// This method counts how many words have at least 3 vowels
public static int countVowels(String[] wordsArray){
int atLeastThreeVowelsCount = 0;
for(String word : wordsArray){
int vowelCount = 0;
for(String vowel : new String[]{ "a", "e", "i", "u", "y", "o" }){
if(word.toLowerCase().contains(vowel)){
vowelCount++;
}
}
if(vowelCount >= 3){
atLeastThreeVowelsCount++;
}
}
return atLeastThreeVowelsCount;
}
Try it online.
Note that I've also given the variables some more useful names, instead of ar1, s, etc. so it's easier to read what's going on.
You can use regex matching to find if a string contains any set of characters. For example, if you want to find if a string contains any of vowels, you can use:
String str = "yydyrf";
boolean contains = str.toLowerCase().matches(".*[aeiou].*");
System.out.println(contains);
EDIT:
So your code would look like:
public static int countVowels(String[] ar1) {
int a = 0;
String[] ar2 = new String[] { "a", "e", "i", "u", "y", "o" };
String pattern = ".*[" + String.join("", ar2) + "].*";
for (int i = 0; i < ar1.length; i++) {
if (ar1[i].matches(pattern)) {
a++;
}
}
return a;
}
You can use this:
public static int countVowels(String[] words) {
char[] chars = {'a', 'e', 'i', 'u', 'y', 'o'};
int wordsWith3Vowels = 0;
for (String word : words) {
int countedVowels = 0;
for (char s : chars) {
if (word.toLowerCase().indexOf(s) != -1) {
countedVowels++;
}
}
if (countedVowels >= 3) {
wordsWith3Vowels++;
}
}
return wordsWith3Vowels;
}
Which uses chars instead of Strings which is a tad faster
public static int countVowels(String[] ar1){ // this method counts
//Create hash map key = array string && value = vowels count
Map<String,Integer> mapVowels=new HashMap<String,Integer>();
int a = 0;
String[] ar2 = new String[]{"a", "e", "i", "u", "y", "o"};
for(int i = 0; i < ar1.length; i++){
for(String s : ar2){
if(ar1[i].toLowerCase().contains(s)){
//Check map string already has vowel count then increase by one
if(mapVowels.get(s)!=null) {
mapVowels.put(s,mapVowels.get(s)+1);
//After add the vowels count get actual count and check is it more than 3
if(mapVowels.get(s)>3)
a++;
}
else {
//If the vowels string new for map then add vowel count as 1 for first time
mapVowels.put(s,1);
}
}
}
}
return a;
}
Since java-8 you can now use Streams.
String[] values = {"AA","BC","CD","AE"};
boolean contains = Arrays.stream(values).anyMatch("s"::equals);
To check whether an array of int, double or long contains a value use IntStream, DoubleStream or LongStream respectively.
Example
int[] a = {1,2,3,4};
boolean contains = IntStream.of(a).anyMatch(x -> x == 4);
Related
I have to create a vowel counter and sorter, where someone can input a word or phrase and the program picks out, counts, and sorts the vowels. I have the code to where it counts and sorts the variables and shows their counts to the user, but it doesn't say which vowel has which count and I have exhausted all of my resources. I am very new to coding and know very little, so if there's anything anyone can do to help, I would appreciate it endlessly.
int[] vowelcounter = {a, e, i, o, u}; //This is the count of the vowels after reading the input.
boolean hasswapped = true;
while(hasswapped)
{
hasswapped = false;
for(int j = 0; j<vowelcounter.length; j++)
{
for(int k = j+1; k<vowelcounter.length; k++)
{
if(vowelcounter[j] > vowelcounter[k])
{
int temp = vowelcounter[j];
vowelcounter[j] = vowelcounter[j+1];
vowelcounter[j+1] = temp;
hasswapped = true;
}
}
}
}
for(int j=0; j<vowelcounter.length; j++)
{
System.out.println(vowelcounter[j]);
}
Instead of int value to represent a counter, a class may be introduced to store and print both the vowel character and its count:
class VowelCount {
private final char vowel;
private int count = 0;
public VowelCount(char v) {
this.vowel = v;
}
public void add() { this.count++; }
public int getCount() { return this.count; }
public char getVowel() { return this.vowel; }
#Override
public String toString() { return "Vowel '" + vowel + "' count = " + count;}
}
Then instead of int[] count an array of VowelCount is created and sorted:
VowelCount[] vowelcounter = {
new VowelCount('a'), new VowelCount('e'), new VowelCount('i'),
new VowelCount('o'), new VowelCount('u')
};
Sorting may be implemented using standard method Arrays::sort with a custom comparator instead of home-made bubble sorting
Arrays.sort(vowelcounter, Comparator.comparingInt(VowelCount::getCount));
Then printing of the stats is as follows (using for-each loop along with the overriden toString):
for (VowelCount v: vowelcounter) {
System.out.println(v); // print sorted by count
}
More advanced ways of calculating the frequencies is to use a map of vowels to their frequencies and sort the map by counter value.
You can use something that is called HashMap
HashMap<String, Integer> vowelCounts = new HashMap<>();
To add data to it just do:
vowelCounts.put("a", 1); // The vowel "a" is once in the sentence
vowelCounts.put("e", 2); // The vowel "e" is 2 times in the sentence
To print to the console:
for(String vowel : vowelCounts.keySet() ) {
System.out.println(vowel + ": " + vowelCounts.get(vowel));
}
For more info: click me!
Have a char[] vowels = { 'a', 'e', 'i', 'o', 'u' }. Every time you swap the counters, make an identical swap in the vowels array.
int temp = vowelcounter[j];
vowelcounter[j] = vowelcounter[j+1];
vowelcounter[j+1] = temp;
char temp2 = vowel[j];
vowel[j] = vowel[j+1];
vowel[j+1] = temp2;
hasswapped = true;
At the end, print out vowel[j] next to vowelcounter[j];
I am trying to generate permutations using list of strings taking one character one time.
Below is the code of input and output that I want.
Can we simply do it iteratively?. Also I am not finding exact method.
String[] lst = new String[]{"abc", "def", "ghi"}; //Given
String[] permutations = new String[]{ //To Generate
"adg", "adh", "adi",
"aeg", "aeh", "aei",
"afg", "afh", "afi",
"bdg", "bdh", "bdi",
"beg", "beh", "bei",
"bfg", "bfh", "bfi",
"cdg", "cdh", "cdi",
"ceg", "ceh", "cei",
"cfg", "cfh", "cfi",
};
Update: I am not looking just for the above example with list size=3. It can be of any size and each string may happen to be of different length.
For ex: list = [ "ab", "abc", "defghi", "x", "einsigl"]
In this answer I will walk through how I solved this problem to find an algorithm that works for an array of any length for words which can be any length and are not required to all be the same length.
I will first make a recursive solution, and then transorm it into an iterative one.
The easiest way to answer problems like this is to think of them recursively:
Generating all permutations of [] should return [""]
Generating all permutations of a non-empty list means, for each letter c in the first word in the list, return all permutations of the rest of the list with c prepended on the front.
This can be written in Java as follows:
public static List<String> generatePermutationsRecursiveSlow(String[] words) {
if (words.length == 0)
// base case
return Collections.singletonList("");
else {
// recursive case
// result list
ArrayList<String> permutations = new ArrayList<>();
// split array into item 0 and items [1..end]
String firstWord = words[0];
String[] otherWords = new String[words.length - 1];
System.arraycopy(words, 1, otherWords, 0, words.length - 1);
// recurse to find permutations for items [1..end]
List<String> otherWordsPermutations = generatePermutationsRecursiveSlow(otherWords);
// for each character in the first word
for (char c : firstWord.toCharArray()) {
// for each permutation from the recursive call's results
for (String otherWordsPermutation : otherWordsPermutations) {
// prepend this character onto the permutation and add it to the results
permutations.add(c + otherWordsPermutation);
}
}
return permutations;
}
}
Calling generatePermutationsRecursiveSlow(new String[0]) returns [""].
Calling generatePermutationsRecursiveSlow(new String[]{"cd"}) will cause the local c variable to be equal to 'c', and it will recurse with an empty array as the argument, making otherWordsPermutations equal to [""], so it will add 'c' + "" (which is "c") to the results, then it will do the same for 'd', adding "d" to the results.
Calling generatePermutationsRecursiveSlow(new String[]{"ab", "cd"}) will mean that when c is 'a', it will add to the results list 'a'+"c", then 'a'+"d", and whencis'b', it will add'b'+"c"and'b'+"d"`
A similar but better optimised version which works in the same way can be written like this:
public static List<String> generatePermutationsRecursive(String[] words) {
ArrayList<String> permutations = new ArrayList<>();
int wordLen = words.length;
generatePermutationsRecursive(words, permutations, new char[wordLen], 0);
return permutations;
}
public static void generatePermutationsRecursive(String[] words, ArrayList<String> permutations, char[] word, int i) {
if (i == word.length) {
// base case
permutations.add(new String(word));
} else {
for (int j = 0; j < words[i].length(); j++) {
// equivalent of prepending
word[i] = words[i].charAt(j);
// recurse
generatePermutationsRecursive(words, permutations, word, i + 1);
}
}
}
This is better optimised since it uses the word parameter to avoid the O(n) prepending to the string by instead modifying a character array. It also introduces the parameter i which is the effective start index of the array, making it possible to avoid copying parts of the input array.
This can be transformed into an iterative approach by tracking the variables that change between different recursive calls using a stack (in place of the call stack):
private static List<String> generatePermutationsIterative(String[] words) {
// in the recursive version, each recursive function call would have its own local copy of `i` and `j`
// simulate that here with 2 stacks
ArrayDeque<Integer> i_stack = new ArrayDeque<>(words.length);
ArrayDeque<Integer> j_stack = new ArrayDeque<>(words.length);
i_stack.add(0);
j_stack.add(0);
char[] word = new char[words.length];
ArrayList<String> permutations = new ArrayList<>();
while (!i_stack.isEmpty()) {
int i = i_stack.removeLast();
int j = j_stack.removeLast();
if (i == words.length) {
// base case
permutations.add(new String(word));
continue;
}
if (!(j < words[i].length())) {
// reached end of loop `for (int j = 0; j < words[i].length(); j++)`
continue;
}
// if not reached end of loop `for (int j = 0; j < words[i].length(); j++)` yet,
// then increment `j` and allow next iteration to happen
i_stack.add(i);
j_stack.add(j + 1);
word[i] = words[i].charAt(j);
// recurse
i_stack.add(i + 1);
j_stack.add(0);
}
return permutations;
}
Code here
As a sidenote, look how cool Haskell is with this 2-line solution to the problem here (admittedly its not iterative, but it should have tail-call optimisation, making it as fast as an iterative solution).
Here's one way to do it that should work for arbitrary number of words of arbitrary length (not including 0).
String[] lst = new String[] {
"abc",
"def",
"ghi"
};
int numWords = lst.length;
int wordlen = lst[0].length();
int numPerms = (int) Math.pow(wordlen, numWords);
char[][] perms = new char[numPerms][numWords];
char[][] chararr = Arrays.stream(lst)
.map(String::toCharArray)
.toArray(i -> new char[i][wordlen]);
for (int i = 0; i < numWords; i++) {
double permsLocal = Math.pow(wordlen, i + 1);
int numRepeats = (int) Math.ceil((numPerms / permsLocal));
int repeats = (int)(permsLocal / wordlen);
for (int x = 0; x < repeats; x++) {
char[] word = chararr[i];
for (int j = 0; j < wordlen; j++) {
char c = word[j];
for (int k = 0; k < numRepeats; k++) {
perms[(x * wordlen * numRepeats) + k + j * numRepeats][i] = c;
}
}
}
}
String[] permutations = Arrays.stream(perms)
.map(String::new)
.toArray(String[]::new);
Output:
[adg, adh, adi, aeg, aeh, aei, afg, afh, afi, bdg, bdh, bdi, beg, beh,
bei, bfg, bfh, bfi, cdg, cdh, cdi, ceg, ceh, cei, cfg, cfh, cfi]
Link to repl.it: https://repl.it/repls/BoilingExcitingAttributes
You can do it as follows:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
String[] lst = new String[] { "abc", "def", "ghi" };
List<String> list = new ArrayList<>();
for (char a : lst[0].toCharArray()) {
for (char b : lst[1].toCharArray()) {
for (char c : lst[2].toCharArray()) {
list.add(new String(new char[] { a, b, c }));
}
}
}
// Convert to array
String[] permutations = list.toArray(new String[0]);
// Display
System.out.println(Arrays.toString(permutations));
}
}
Output:
[adg, adh, adi, aeg, aeh, aei, afg, afh, afi, bdg, bdh, bdi, beg, beh, bei, bfg, bfh, bfi, cdg, cdh, cdi, ceg, ceh, cei, cfg, cfh, cfi]
I m trying to make a function that prints the number of characters common in given n strings. (note that characters may be used multiple times)
I am struggling to perform this operation on n strings However I did it for 2 strings without any characters repeated more than once.
I have posted my code.
public class CommonChars {
public static void main(String[] args) {
String str1 = "abcd";
String str2 = "bcde";
StringBuffer sb = new StringBuffer();
// get unique chars from both the strings
str1 = uniqueChar(str1);
str2 = uniqueChar(str2);
int count = 0;
int str1Len = str1.length();
int str2Len = str2.length();
for (int i = 0; i < str1Len; i++) {
for (int j = 0; j < str2Len; j++) {
// found match stop the loop
if (str1.charAt(i) == str2.charAt(j)) {
count++;
sb.append(str1.charAt(i));
break;
}
}
}
System.out.println("Common Chars Count : " + count + "\nCommon Chars :" +
sb.toString());
}
public static String uniqueChar(String inputString) {
String outputstr="",temp="";
for(int i=0;i<inputstr.length();i++) {
if(temp.indexOf(inputstr.charAt(i))<0) {
temp+=inputstr.charAt(i);
}
}
System.out.println("completed");
return temp;
}
}
3
abcaa
bcbd
bgc
3
their may be chances that a same character can be present multiple times in
a string and you are not supposed to eliminate those characters instead
check the no. of times they are repeated in other strings. for eg
3
abacd
aaxyz
aatre
output should be 2
it will be better if i get solution in java
You have to convert all Strings to Set of Characters and retain all from the first one. Below solution has many places which could be optimised but you should understand general idea.
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static void main(String[] args) {
List<String> input = Arrays.asList("jonas", "ton", "bonny");
System.out.println(findCommonCharsFor(input));
}
public static Collection<Character> findCommonCharsFor(List<String> strings) {
if (strings == null || strings.isEmpty()) {
return Collections.emptyList();
}
Set<Character> commonChars = convertStringToSetOfChars(strings.get(0));
strings.stream().skip(1).forEach(s -> commonChars.retainAll(convertStringToSetOfChars(s)));
return commonChars;
}
private static Set<Character> convertStringToSetOfChars(String string) {
if (string == null || string.isEmpty()) {
return Collections.emptySet();
}
Set<Character> set = new HashSet<>(string.length() + 10);
for (char c : string.toCharArray()) {
set.add(c);
}
return set;
}
}
Above code prints:
[n, o]
A better strategy for your problem is to use this method:
public int[] countChars(String s){
int[] count = new int[26];
for(char c: s.toCharArray()){
count[c-'a']++;
}
return count;
}
Now if you have n Strings (String[] strings) just find the min of common chars for each letter:
int[][] result = new int[n][26]
for(int i = 0; i<strings.length;i++){
result[i] = countChars(s);
}
// now if you sum the min common chars for each counter you are ready
int commonChars = 0;
for(int i = 0; i< 26;i++){
int min = result[0][i];
for(int i = 1; i< n;i++){
if(min>result[j][i]){
min = result[j][i];
}
}
commonChars+=min;
}
Get list of characters for each string:
List<Character> chars1 = s1.chars() // list of chars for first string
.mapToObj(c -> (char) c)
.collect(Collectors.toList());
List<Character> chars2 = s2.chars() // list of chars for second string
.mapToObj(c -> (char) c)
.collect(Collectors.toList());
Then use retainAll method:
chars1.retainAll(chars2); // retain in chars1 only the chars that are contained in the chars2 also
System.out.println(chars1.size());
If you want to get number of unique chars just use Collectors.toSet() instead of toList()
Well if one goes for hashing:
public static int uniqueChars(String first, String second) {
boolean[] hash = new boolean[26];
int count = 0;
//reduce first string to unique letters
for (char c : first.toLowerCase().toCharArray()) {
hash[c - 'a'] = true;
}
//reduce to unique letters in both strings
for(char c : second.toLowerCase().toCharArray()){
if(hash[c - 'a']){
count++;
hash[c - 'a'] = false;
}
}
return count;
}
This is using bucketsort which gives a n+m complexity but needs the 26 buckets(the "hash" array).
Imo one can't do better in regards of complexity as you need to look at every letter at least once which sums up to n+m.
Insitu the best you can get is imho somewhere in the range of O(n log(n) ) .
Your aproach is somewhere in the league of O(n²)
Addon: if you need the characters as a String(in essence the same as above with count is the length of the String returned):
public static String uniqueChars(String first, String second) {
boolean[] hash = new boolean[26];
StringBuilder sb = new StringBuilder();
for (char c : first.toLowerCase().toCharArray()) {
hash[c - 'a'] = true;
}
for(char c : second.toLowerCase().toCharArray()){
if(hash[c - 'a']){
sb.append(c);
hash[c - 'a'] = false;
}
}
return sb.toString();
}
public static String getCommonCharacters(String... words) {
if (words == null || words.length == 0)
return "";
Set<Character> unique = words[0].chars().mapToObj(ch -> (char)ch).collect(Collectors.toCollection(TreeSet::new));
for (String word : words)
unique.retainAll(word.chars().mapToObj(ch -> (char)ch).collect(Collectors.toSet()));
return unique.stream().map(String::valueOf).collect(Collectors.joining());
}
Another variant without creating temporary Set and using Character.
public static String getCommonCharacters(String... words) {
if (words == null || words.length == 0)
return "";
int[] arr = new int[26];
boolean[] tmp = new boolean[26];
for (String word : words) {
Arrays.fill(tmp, false);
for (int i = 0; i < word.length(); i++) {
int pos = Character.toLowerCase(word.charAt(i)) - 'a';
if (tmp[pos])
continue;
tmp[pos] = true;
arr[pos]++;
}
}
StringBuilder buf = new StringBuilder(26);
for (int i = 0; i < arr.length; i++)
if (arr[i] == words.length)
buf.append((char)('a' + i));
return buf.toString();
}
Demo
System.out.println(getCommonCharacters("abcd", "bcde")); // bcd
I recently was asked a question to create a sequence from an array of string such that the string elements can combine if the last character of element 1 matches the first character of element 2.
Eg: {"ab", "bc", "cd", "ad", "def", "cedd"} should return "abceddef".
What I'm getting for above input is "abcdef".
public class LongestSubstringConsecutiveEnds {
static StringBuilder sbMax = new StringBuilder();
static StringBuilder sbTemp;
public static void main(String[] args) {
String[] inputStrings = {"ab", "bc", "cd", "ad", "def", "cedd"};
List<String> inputList = new ArrayList<String>(Arrays.asList(inputStrings));
for(int i=0; i<inputList.size(); i++) {
String str = inputList.get(i);
sbTemp = new StringBuilder(str);
inputList.remove(str);
longestSequence(sbTemp, new ArrayList<String>(inputList));
inputList.add(0, str);
}
System.out.println(sbMax.toString());
}
private static void longestSequence(StringBuilder tempSubstring, final List<String> inputList) {
System.out.println(tempSubstring.toString() + inputList);
if(tempSubstring.length() > sbMax.length()) {
sbMax.delete(0, sbMax.length());
sbMax.append(tempSubstring);
}
for(int i=0; i<inputList.size(); i++) {
String inputListString = inputList.get(i);
char tempStrLastChar = tempSubstring.charAt(tempSubstring.length()-1);
if(inputListString.charAt(0) == tempStrLastChar) {
String str = inputList.remove(i);
longestSequence(tempSubstring.append(inputListString.substring(1)), inputList);
inputList.add(i, str);
}
}
}
}
According your question:
if the last character of element 1 matches the first character of element 2.
Part you described in your question can be done easy:
for (int i = 0; i < strings.length - 1; i++) {
// last char of element i is equal first char of element i+1
if (strings[i].charAt(strings[i].length()-1) == strings[i+1].charAt(0)) {
// print element i.
System.out.print(strings[i]);
}
}
Output:
cd
That is, position 3 matches with 4 (cd-def)
But that does not match with
should return "abceddef"
And I can't find a logic... where last ef comes from? you mean match when for example last is a and first is b ??. That would be:
for (int i = 0; i < strings.length - 1; i++) {
// get last and first char
String actual = strings[i];
char last = actual.charAt(actual.length()-1);
char first = strings[i+1].charAt(0);
if ((int) first == last + 1) {
System.out.print(actual);
}
}
Output:
ab
That is, position 2 matches with 3 (ab-cd)
public static void main(String...args){
final String[] input={"ab", "bc", "cd", "ad", "def", "cedd"};
System.out.println( funkyConcat(input));
}
private static String funkyConcat(String...strings){
String ret="";
for(String i:strings){
if(ret.isEmpty()){
ret=i;
}else if(ret.substring(ret.length()-1).equals(i.substring(0,1))){
ret+=i.substring(1);
}
}
return ret;
}
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;
}
}
}