In the code below I have a double for loop resulting in a time complexity of O^2 in method getResponse(). This code prompts the user for a 10 integer sequence string and an uppercase sensitive pin. It then converts the pin to numbers on a phone pad ie. [ABC] --> 2, [DEF] --> 3. Lastly a response array is generated with each digit of the new phone pin corresponding to indexes of sequence. So input "0123456789","HAM", response = "426"
import java.util.Scanner;
public class Test {
public static final int SEQ_DIGITS = 10;
public static final String ERR_SEQ = "Invalid sequence";
public static final String ERR_PIN = "Invalid PIN";
public static int letterToPhone(char c) {
int phoneNumber = 0;
if (Character.toString(c).matches("[ABC]")) {
phoneNumber = 2;
} else if (Character.toString(c).matches("[DEF]")) {
phoneNumber = 3;
} else if (Character.toString(c).matches("[GHI]")) {
phoneNumber = 4;
} else if (Character.toString(c).matches("[JKL]")) {
phoneNumber = 5;
} else if (Character.toString(c).matches("[MNO]")) {
phoneNumber = 6;
} else if (Character.toString(c).matches("[PQRS]")) {
phoneNumber = 7;
} else if (Character.toString(c).matches("[TUV]")) {
phoneNumber = 8;
} else if (Character.toString(c).matches("[WXYZ]")) {
phoneNumber = 9;
}
return phoneNumber;
}
public static int[] getResponse(String pin, int[] values) {
int[] response = new int[pin.length()];
for(int i = 0; i < pin.length(); i++) {
for (int j = 0; j < values.length; j++) {
int x = letterToPhone(pin.charAt(i));
if(x == j) {
response[i] = values[j];
}
}
}
return response;
}
public static boolean stringIsLengthK(String s, int k) {
boolean isLength = false;
if (s.length() == k) {
isLength = true;
}
return isLength;
}
public static boolean allDigits(String s) {
boolean isDigit = true;
for (int i = 0; i < s.length(); i++) {
if (!(Character.isDigit(s.charAt(i)))) {
isDigit = false;
break;
}
}
return isDigit;
}
public static boolean allUppercaseLetters(String s) {
boolean isUpper = true;
for (int i = 0; i < s.length(); i++) {
if (!(Character.isUpperCase(s.charAt(i)))) {
isUpper = false;
break;
}
}
return isUpper;
}
public static int[] digitStringToIntArray(String s) {
int[] arrayS = new int[s.length()];
for(int i = 0; i < arrayS.length; i++) {
for(int j = 0; j < SEQ_DIGITS; j++) {
if (((int) s.charAt(i) - 48) == j) {
arrayS[i] = j;
}
}
}
return arrayS;
}
public static int countValues(int value, int[] values) {
int count = 0;
for(int i = 0; i < values.length; i++) {
if(value == values[i]) {
count++;
}
}
return count;
}
public static int numPossible(int[] response, int[] values) {
int product = 1;
int[] count = new int[response.length];
for (int i = 0; i < count.length; i++) {
count[i] = countValues(response[i], values);
}
for(int i=0; i<response.length; i++){
product = product * count[i];
}
return product;
}
public static void main(String[] args) {
try (Scanner in = new Scanner(System.in)) {
System.out.printf("Enter value sequence: ");
final String seq = in.nextLine();
System.out.printf("Enter PIN: ");
final String pin = in.nextLine();
if (!(allUppercaseLetters(pin))) {
throw new AssertionError(ERR_PIN);
} else if (!(allDigits(seq)) || !(stringIsLengthK(seq, SEQ_DIGITS))) {
throw new AssertionError(ERR_SEQ);
}
int[] seqArray = new int[SEQ_DIGITS];
seqArray = digitStringToIntArray(seq);
int[] response = new int[SEQ_DIGITS];
response = getResponse(pin, seqArray);
System.out.printf("Response: ");
for (int i = 0; i < response.length; i++) {
System.out.printf("%d", response[i]);
}
System.out.printf("%n");
numPossible(response, seqArray);
} catch (Error e) {
System.out.println(e.getMessage());
}
}
}
I want to be to able to accommodate larger sequence numbers without a scaling of n^2. Is there a way to change the for loop to instead compare the int x = letterToPhone(pin.charAt(i)); value in getResponse() to a range of integers such as "[0-9]"
One easy optimization of constant factors is to move the call to letterToPhone() out of the inner loop.
And yes, you can compare the x value to a range, eliminating the need for the inner loop.
for(int i = 0; i < pin.length(); i++) {
int x = letterToPhone(pin.charAt(i));
if ( (0 <= x) && (x < values.length)) {
response[i] = values[x];
}
}
Another optimization of constant factors would be to replace all the function calls in letterToPhone() with a switch statement. The compiler may choose to optimize that into a table lookup.
I am trying to find a simple solution and I have read all the information or question that try to answer or have solve the problem , and i have being testing.
I have found a solution which i converted from c#, and it works, but is too complicated and i do not understand how it works, so i was trying to make my own solution.
public static String lcs(String[] strings) {
if (strings.length == 0)
return "0";
if (strings.length == 1)
return strings[0];
int max = -1;//max length of a string
int cacheSize = 1; //multiplied length size of array with each other.
for (int i = 0; i < strings.length; i++) {
cacheSize *= strings[i].length();
if (strings[i].length() > max)
max = strings[i].length();
}
String[] cache = new String[cacheSize];
int[] indexes = new int[strings.length];
for (int i = 0; i < indexes.length; i++)
indexes[i] = strings[i].length() - 1;
return lcsBack(strings, indexes, cache);
}
public static String lcsBack(String[] strings, int[] indexes, String[] cache) {
for (int i = 0; i < indexes.length; i++)
if (indexes[i] == -1)
return "";
boolean match = true;
for (int i = 1; i < indexes.length; i++) {
if (strings[0].charAt(indexes[0]) != strings[i].charAt(indexes[i])) {
match = false;
break;
}
}
if (match) {
int[] newIndexes = new int[indexes.length];
for (int i = 0; i < indexes.length; i++)
newIndexes[i] = indexes[i] - 1;
String result = lcsBack(strings, newIndexes, cache) + strings[0].charAt(indexes[0]);
cache[calcCachePos(indexes, strings)] = result;
return result;
} else {
String[] subStrings = new String[strings.length];
for (int i = 0; i < strings.length; i++) {
if (indexes[i] <= 0)
subStrings[i] = "";
else {
int[] newIndexes = new int[indexes.length];
for (int j = 0; j < indexes.length; j++)
newIndexes[j] = indexes[j];
newIndexes[i]--;
int cachePos = calcCachePos(newIndexes, strings);
if (cache[cachePos] == null)
subStrings[i] = lcsBack(strings, newIndexes, cache);
else
subStrings[i] = cache[cachePos];
}
}
String longestString = "";
int longestlength = 0;
for (int i = 0; i < subStrings.length; i++) {
if (subStrings[i].length() > longestlength) {
longestString = subStrings[i];
longestlength = longestString.length();
}
}
cache[calcCachePos(indexes, strings)] = longestString;
return longestString;
}
}
static int calcCachePos(int[] indexes, String[] strings) {
int factor = 1;
int pos = 0;
for (int i = 0; i < indexes.length; i++) {
pos += indexes[i] * factor;
factor *= strings[i].length();
}
return pos;
}
So on what i understand i have being able, to make this method which is simple, but still doesn't work.
And i know from readings that the best way to solve this is using dinamic programming I would appreciate if somebody can help, thank you
/**
* #param strArr .
* #return String
*/
public String findCommonString(String[] words) throws Exception {
try {
String commonStr = "";
String tempCom = "";
char[] longestWordChars = findTheLongestString(words).toCharArray();
for (char c : longestWordChars) {
tempCom += c;
for (String word : words) {
if (!word.contains(tempCom)) {
tempCom = Character.toString(c);
for (String word2 : words) {
if (!word2.contains(tempCom)) {
tempCom = "";
break;
}
}
break;
}
}
if (tempCom != "" && tempCom.length()>commonStr.length()) {
commonStr = tempCom;
//strArr = removeFirstOccurrence(strArr, tempCom);
// tempCom = "";
}
}
return commonStr;
} catch (Exception e) {
logger.warn("[findCommonString] [STATUS] - ERROR ");
logger.warn("[findCommonString] [EXCEPTION] " + e.getMessage());
throw e;
}
/**
* #param strArr .
* #return String
*/
public String findTheLongestString(String[] words) throws Exception { // test
try {
String longestWord = "";
for (String s : words) {
if (longestWord.length() < s.length()) {
longestWord = s;
}
}
return longestWord;
} catch (Exception e) {
logger.warn("[findTheLongestString] [STATUS] - ERROR ");
logger.warn("[findTheLongestString] [EXCEPTION] " + e.getMessage());
throw e;
}
}
I have being testing with this two test unit example
#Test
public void SubsequenceServiceTest3() throws Exception {
assertEquals("CDAC", subsequenceService.findCommonSequence(new String[] { "BCDAACD", "ACDBAC" }));
}
#Test
public void SubsequenceServiceTest14() throws Exception {
assertEquals("CA", subsequenceService.findCommonSequence(new String[] { "ACADB", "CBDA" }));
}
I wanted to get the maximum repeating characters count and its relevant index. I am able to print the max repeating characters in a given string and its index. However I am unable to print the total count of repeating character. Below is my code
public class MaxRepeating {
static char charactercountIndex(String str) {
int len = str.length();
int count = 0;
char res = str.charAt(0);
for (int i = 0; i < len; i++) {
int cur_count = 0;
for (int j = i + 1; j < len; j++) {
if (str.charAt(i) != str.charAt(j))
break;
cur_count++;
}
if (cur_count > count) {
count = cur_count;
res = str.charAt(i);
}
}
return res;
}
public static void main(String args[]) {
String str = "aaaaaaccde";
char s1 = charactercountIndex(str);
str.indexOf(s1);
System.out.println(str.indexOf(s1));
System.out.println(charactercountIndex(str));
}
}
output should <0,6>
0 is the index of character a
6 is the total time character "a" present in the string
If you are open to a slightly different approach, there is a fairly straightforward way to do this using regex and streams. We can try splitting the input string into like-lettered substring components using the following regex:
(?<=(.))(?!\\1)
Then, we can use Collections.max to find the largest string in the collection, and finally use String#indexOf to find the index of that substring.
String str = "aaaabbddddddddddddddddddddaaccde";
List<String> parts = Arrays.asList(str.split("(?<=(.))(?!\\1)"));
String max = Collections.max(parts, Comparator.comparing(s -> s.length()));
System.out.println("largest substring: " + max);
int index = str.indexOf(max);
System.out.println("index of largest substring: " + index);
largest substring: dddddddddddddddddddd
index of largest substring: 6
I've done something like this:
static Entry<String, Integer> charactercountIndex(String str) {
HashMap<String, Integer> stringIntegerHashMap = new HashMap<>();
for (String letter : str.split("")) {
if (stringIntegerHashMap.containsKey(letter)) {
stringIntegerHashMap.put(letter, (stringIntegerHashMap.get(letter) + 1));
} else {
stringIntegerHashMap.put(letter, 1);
}
}
Entry<String, Integer> maxEntry = null;
for (Entry<String, Integer> entry : stringIntegerHashMap.entrySet()) {
if (maxEntry == null
|| entry.getValue().compareTo(maxEntry.getValue()) > 0) {
maxEntry = entry;
}
}
return maxEntry;
}
public static void main(String args[]) {
String str = "aaaabbddddddddddddddddddddaaccde";
Entry<String, Integer> s1 = charactercountIndex(str);
System.out.println(s1.getKey());
System.out.println(s1.getValue());
}
If you have any trouble, let me know.
You can return the result through a local class instance (which contains both the character and its occurrences). I added a local class CountResult.
By the way, I fixed your code (see // including ... comment).
You can try and check the working code below here.
public class MaxRepeating {
private static CountResult charactercountIndex(String str) {
int len = str.length();
char res = str.charAt(0);
int count = 0;
for (int i = 0; i < len; i++) {
int cur_count = 1; // including the tested char (first occurence)
for (int j = i + 1; j < len; j++) {
if (str.charAt(i) != str.charAt(j))
break;
cur_count++;
}
if (cur_count > count) {
res = str.charAt(i);
count = cur_count;
}
}
return new CountResult(res, count);
}
private static class CountResult {
private char maxChar;
private int count;
public CountResult(char maxChar, int count) {
this.maxChar = maxChar;
this.count = count;
}
public String toString() {
return String.format("<" + maxChar + "," + count + ">");
}
}
public static void main(String args[]) {
String str = "aaaaaaccde";
System.out.println(charactercountIndex(str));
}
}
You can create your own class that you will not be bounded to count of returned parameters from method.
public class MyCharacter {
private static int count;
private static char character;
private static int indexOf;
public void characterCountIndex(String str) {
int len = str.length();
for (int i = 0; i < len; i++) {
int cur_count = 1;
for (int j = i + 1; j < len; j++) {
if (str.charAt(i) != str.charAt(j))
break;
cur_count++;
}
if (cur_count > count) {
count = cur_count;
character = str.charAt(i);
indexOf = str.indexOf(character);
}
}
}
#Override
public String toString() {
return String.format("<%d, %d>", indexOf, count);
}
public static void main(String[] args) {
String str = "aaaaaaccde";
MyCharacter myCharacter = new MyCharacter();
myCharacter.characterCountIndex(str);
System.out.println(myCharacter);
}
}
I want to write a code that count repeat of every word in a string,words separate each other with some character that input as a string...why my code don't work?
please answer soon!
public class repeat {
public static void main(String[] args) {
Scanner ss = new Scanner(System.in);
System.out.println("Please write a string:");
String s = ss.nextLine();
System.out.println("Please write a character:");
String w = ss.nextLine();
int i = 0;
int j = 0;
int k = 0;
int y=0;
for (i=0 ;i < s.length() ;i++) {
for (j = 0; j < w.length(); j++) {
if (w.charAt(j) == s.charAt(i) && i!=y && i!=0 && i!=s.length() -1 ) {
k += 1;
y=i+1;
}
}
}
i = 0;
j = 0;
y = 0;
int r = 0;
k++;
System.out.println(k);
String[] a = new String[k];
for (r=0 ;r < k-1 ;r++) {
for (j=1 ;j < s.length() ;j++) {
for (i = 1; i < w.length(); i++) {
if (w.charAt(i) == s.charAt(j)) {
a[r] = s.substring(y, j);
y = j+1;
}
}
}
System.out.println(a[r]);
}
a[k-1] = s.substring(y+1,s.length());
i = 0;
int[] b = new int[k];
while (i <k) {
b[i] = 0;
i++;
}
i = j = 0;
while (i < k) {
while (j != i && j < k) {
if (a[i] == a[j]) {
a[j] = null;
b[i]++;
}
j++;
}
i++;
}
i = j = 0;
while (i < k) {
if (a[i] != null) {
System.out.println(a[i] + " " + b[i]);
}
i++;
}
}
}
Looking through your code your taking a very long approach to this problem. The easiest thing to do is use regex https://docs.oracle.com/javase/tutorial/essential/regex/. Please see the methods below.
public Sentence(String sentanceString) {
this.fullSentence = sentanceString;
breakStringIntoWords(sentanceString);
}
private void breakStringIntoWords(String sentanceString) {
String[] wordsInString = sentanceString.split("\\W+");
for (String word : wordsInString) {
words.add(new Word(word));
}
}
In the second method I broke a sentence (delimited by [spaces]) into words. From here you would write code to compare each word (a class that has a to string method so treat it as a string) to every other word in the Words array list, be careful to avoid over counting.
ok this is now Java with Split instead of searching the string manually:
I don't exactly know if the copyarray is the best practice to make it larger but if your string is not megabytes large it won't be a problem:
public class repeat
{
public static void main(String[] args)
{
String s = "Hello world this is a very good test to a world just that contains just more words than just hello";
String w = " ";
String[] foundwords = new String[0];
int[] wordcount = new int[0];
String[] splittext = s.split(w);
for (int i = 0; i< splittext.length; i++)
{
int IndexOfWord = getIndexOfWord(splittext[i], foundwords);
if (IndexOfWord < 0)
{
String[] foundwordsTemp = new String[foundwords.length + 1];
int[] wordcountTemp = new int[foundwords.length + 1];
System.arraycopy(foundwords, 0, foundwordsTemp, 0, foundwords.length);
System.arraycopy(wordcount, 0, wordcountTemp, 0, foundwords.length);
foundwords = new String[foundwords.length + 1];
wordcount = new int[wordcount.length + 1];
System.arraycopy(foundwordsTemp, 0, foundwords, 0, foundwordsTemp.length);
System.arraycopy(wordcountTemp, 0, wordcount, 0, foundwordsTemp.length);
foundwords[foundwords.length-1] = splittext[i];
wordcount[foundwords.length-1] = 1;
}
else
{
wordcount[IndexOfWord]++;
}
}
for (int i = 0; i < foundwords.length; i++)
{
System.out.println(String.format("Found word '%s' %d times.", foundwords[i], wordcount[i]));
}
}
private static int getIndexOfWord(String word, String[] foundwords)
{
for (int i = 0; i < foundwords.length; i++)
{
if (word.equals(foundwords[i]))
{
return i;
}
}
return -1;
}
}
(Wrong language i did it wrongly in c# - see next answer for java)
I suggest to use array and Split for this because it is very complicated work with substring to seach for the char. While w still is a String, c need to be a type char.
String[] foundwords = { };
Int32[] wordcount = { };
foreach (String word in s.Split(w))
{
int IndexOfWord = Array.IndexOf(foundwords, word);
if (IndexOfWord < 0)
{
Array.Resize(ref foundwords, foundwords.Length + 1);
Array.Resize(ref wordcount, wordcount.Length + 1);
foundwords[foundwords.GetUpperBound(0)] = word;
wordcount[foundwords.GetUpperBound(0)] = 1;
}
else
{
wordcount[IndexOfWord]++;
}
}
for (int i = 0; i <= foundwords.GetUpperBound(0); i++)
{
Console.WriteLine(String.Format("Found word '{0}' {1} times.", foundwords[i], wordcount[i]));
}
be aware that it is case sensitive.
so if it is still on your list i made a code.
First - you where lost to just let it run in the main procedure only. You should start and seperate your work into single tasks instead of writing a strait start stop program. Using functions with a "good" name will make it easier to you in future.
First you need something to find the String in another.
Usually you may use
int dividerPosition = restString.indexOf(searchString);
this is a java build in function. If you want to write it yourself, you could create a function like this (that will do the same but you can "see" it working:)
private static int indexOf(String restString, String searchString)
{
int dividerPosition = -1;
for (int i = 0; i < restString.length()-searchString.length(); i++)
{
// Debuging test:
System.out.println(String.format("search Pos %d in '%s' for length %d.", i, restString, searchString.length()));
if (restString.substring(i, i + searchString.length()).equals(searchString))
{
dividerPosition = i;
i = restString.length();
}
}
return dividerPosition;
}
and use this function in your code later on like:
int dividerPosition = indexOf(restString, searchString);
I will again use the function to find either a word is allready known
private static int getIndexOfWord(String word, String[] foundwords)
{
for (int i = 0; i < foundwords.length; i++)
{
if (word.equals(foundwords[i]))
{
return i;
}
}
return -1;
}
Third Task would be to Split and count the Words at the found position.
The easier way (only my opinion) would be just to cut of the found Words from the String - so write a function that will "save" the found word in a array or count the "counter"-Array if it is allready found.
This most important task to understand is important - ok we will just look for the position of the string we are searching. We need to check if it is not found (so the last word)
We will store the found word (that is the part before the found String) in a variable and do the "count or create new word" thing. And then we will return the String cut of the word and the Seach-String.
The Cut-Off is important because we replace the origin String by the one without the first word and just repeat this until the origin String is "".
For the last word we ensure the function will return "" by changing the dividerPosition to the length of the RestString - that is the last word now only - minus "searchString.length()" so it will fit to the return "restString.substring(dividerPosition+searchString.length());" to return ""
Look in the next part into the function named "getNextW("
you can run int with the self-written IndexOf function or the Java function by changing the commentlines in
/// Index Of Search (better)
//int dividerPosition = restString.indexOf(searchString);
/// Manual Search (why make it more difficuilt - you should learn to make your work as easy as possible)
int dividerPosition = indexOf(restString, searchString);
Everything together
to get startet you will have very little code in the main procedure using the "cut" function until the String is empty - all together now:
public class repeat
{
public static void main(String[] args)
{
String s = "Hello a world a this is a very good test to a a a a world just that contains just more words than just hello";
String w = " ";
while (!(s = getNextW(s, w)).equals(""))
{
System.out.println(s);
}
System.out.println("");
for (int i = 0; i < foundwords.length; i++)
{
// Debuging test:
System.out.println(String.format("Found word '%s' %d times.", foundwords[i], wordcount[i]));
}
}
private static String[] foundwords = new String[0];
private static int[] wordcount = new int[0];
private static String getNextW(String restString, String searchString)
{
/// Index Of Search (better)
//int dividerPosition = restString.indexOf(searchString);
/// Manual Search (why make it more difficuilt - you should learn to make your work as easy as possible)
int dividerPosition = indexOf(restString, searchString);
String foundWord;
if (dividerPosition > 0)
{
foundWord = restString.substring(0, dividerPosition);
}
else
{
foundWord = restString;
dividerPosition = restString.length()-searchString.length();
}
int IndexOfWord = getIndexOfWord(foundWord, foundwords);
if (IndexOfWord < 0)
{
String[] foundwordsTemp = new String[foundwords.length + 1];
int[] wordcountTemp = new int[foundwords.length + 1];
System.arraycopy(foundwords, 0, foundwordsTemp, 0, foundwords.length);
System.arraycopy(wordcount, 0, wordcountTemp, 0, foundwords.length);
foundwords = new String[foundwords.length + 1];
wordcount = new int[wordcount.length + 1];
System.arraycopy(foundwordsTemp, 0, foundwords, 0, foundwordsTemp.length);
System.arraycopy(wordcountTemp, 0, wordcount, 0, foundwordsTemp.length);
foundwords[foundwords.length-1] = foundWord;
wordcount[foundwords.length-1] = 1;
}
else
{
wordcount[IndexOfWord]++;
}
// Debuging test:
System.out.println(String.format("Rest of String is '%s' positionnext is %d.", restString, dividerPosition));
return restString.substring(dividerPosition+searchString.length());
}
private static int getIndexOfWord(String word, String[] foundwords)
{
for (int i = 0; i < foundwords.length; i++)
{
if (word.equals(foundwords[i]))
{
return i;
}
}
return -1;
}
private static int indexOf(String restString, String searchString)
{
int dividerPosition = -1;
for (int i = 0; i < restString.length()-searchString.length(); i++)
{
// Debuging test:
System.out.println(String.format("search Pos %d in '%s' for length %d.", i, restString, searchString.length()));
if (restString.substring(i, i + searchString.length()).equals(searchString))
{
dividerPosition = i;
i = restString.length();
}
}
return dividerPosition;
}
}
Other variant with charAt and im am using your kind of "count words to size the array" what will result in a to big array (potentially far to big):
public class repeat
{
private static String[] foundwords;
private static int[] wordcount;
private static int counter;
public static void main(String[] args) {
String s = "Hello a world a this is a very good test to a a a a world just that contains just more words than just hello";
String w = " ";
int tempPos = 0;
counter = 1; // counting total w-strings+1 for dim
while ((tempPos = findnext(s, w, tempPos)) >= 0)
{
tempPos = tempPos + w.length();
counter++;
}
foundwords = new String[counter];
wordcount = new int[counter];
counter = 0;
while ((tempPos = findnext(s, w, 0)) >= 0)
{
String foundWord = s.substring(0, tempPos);
s = s.substring(tempPos + w.length());
foundWordToArray(foundWord);
}
foundWordToArray(s);
for (int i = 0; i < counter; i++)
{
System.out.println(String.format("Found word '%s' %d times.", foundwords[i], wordcount[i]));
}
}
public static int findnext(String haystack, String needle, int startPos)
{
int hpos, npos;
for (hpos = startPos; hpos < haystack.length()-needle.length(); hpos++)
{
for (npos = 0; npos < needle.length(); npos++)
{
if (haystack.charAt(hpos+npos)!=needle.charAt(npos))
{
npos = needle.length()+1;
}
}
if (npos == needle.length())
{
return hpos;
}
}
return -1;
}
private static int getIndexOfWord(String word, String[] foundwords)
{
for (int i = 0; i < foundwords.length; i++)
{
if (word.equals(foundwords[i]))
{
return i;
}
}
return -1;
}
private static void foundWordToArray(String foundWord)
{
int IndexOfWord = getIndexOfWord(foundWord, foundwords);
if (IndexOfWord < 0)
{
foundwords[counter] = foundWord;
wordcount[counter] = 1;
counter++;
}
else
{
wordcount[IndexOfWord]++;
}
}
}
i like this one:
public class repeat
{
private static String[] foundwords = new String[0];
private static int[] wordcount = new int[0];
public static void main(String[] args) {
String s = "Hello a world a this is a very good test to a a a a world just that contains just more words than just hello";
String w = " ";
int tempPos;
while ((tempPos = findnext(s, w, 0)) >= 0)
{
String foundWord = s.substring(0, tempPos);
s = s.substring(tempPos + w.length());
foundWordToArray(foundWord);
}
foundWordToArray(s);
for (int i = 0; i < foundwords.length; i++)
{
System.out.println(String.format("Found word '%s' %d times.", foundwords[i], wordcount[i]));
}
}
private static void foundWordToArray(String foundWord)
{
int IndexOfWord = getIndexOfWord(foundWord, foundwords);
if (IndexOfWord < 0)
{
String[] foundwordsTemp = new String[foundwords.length + 1];
int[] wordcountTemp = new int[foundwords.length + 1];
System.arraycopy(foundwords, 0, foundwordsTemp, 0, foundwords.length);
System.arraycopy(wordcount, 0, wordcountTemp, 0, foundwords.length);
foundwords = new String[foundwords.length + 1];
wordcount = new int[wordcount.length + 1];
System.arraycopy(foundwordsTemp, 0, foundwords, 0, foundwordsTemp.length);
System.arraycopy(wordcountTemp, 0, wordcount, 0, foundwordsTemp.length);
foundwords[foundwords.length-1] = foundWord;
wordcount[foundwords.length-1] = 1;
}
else
{
wordcount[IndexOfWord]++;
}
}
public static int findnext(String haystack, String needle, int startPos)
{
int hpos, npos;
for (hpos = startPos; hpos < haystack.length()-needle.length(); hpos++)
{
for (npos = 0; npos < needle.length(); npos++)
{
if (haystack.charAt(hpos+npos)!=needle.charAt(npos))
{
npos = needle.length()+1;
}
}
if (npos == needle.length())
{
return hpos;
}
}
return -1;
}
private static int getIndexOfWord(String word, String[] foundwords)
{
for (int i = 0; i < foundwords.length; i++)
{
if (word.equals(foundwords[i]))
{
return i;
}
}
return -1;
}
}
I have a requirement, in which I have to scan certain files for the match of certain keywords. My keywords list size is around 40000 and all my files have approximately 4000 lines. Also the keyword should not be commented in the file, hence I have to take care of comments as well. The code what I have written to know the occurrence of the keyword is taking around 5 minutes for each file. I don't know what change I can make to reduce the execution time.
The code is as shown below.
for (File fl : files) {
flag = false;
content = FileUtils.readFileToString(fl);
System.out.println(fl.getName());
fileName = fl.getName();
// Object Keywords scanning
keywords = null;
keywords = findKeywordType(fileName);
if (keywords != null) {
Boolean keywordCount = false;
for (String[] key : keywords) {
key[0] = key[1];
}
for (String[] key : keywords) {
Boolean check = false;
if (content.contains(key[0])) {
if (content.contains(key[3] + ".")) {
check = true;
}
if (check) {
continue;
}
if (content.contains(key[3])) {
keywordCount = FindOccurence(fl, key[0], key[3]);
if (keywordCount) {
System.out.println("Writing keywords");
objKwm = new ObjectKeywordMaster();
objKwm.setObjectName(key[0]);
objKwm.setObjectType(key[1]);
objKwm.setObjectOwner(key[2]);
objKwm.setDependentObjectName(key[3]);
objKwm.setDependentObjectType(key[4]);
objKwm.setDependentObjectOwner(key[5]);
objKw.getObjectKeywords().add(objKwm);
}
}
}
}
}
FindOccurrence method code is
private static Boolean FindOccurence(File fl, String objectName, String keyword) throws IOException {
int startComment = 0;
int endComment = 0;
Boolean objCheck = false;
Boolean keyCheck = false;
Boolean check = false;
List line = FileUtils.readLines(fl);
int fileLength = line.size();
int objCount = 0;
int keyCount = 0;
loop:
for (int j = 0; j < fileLength; j++) {
if (line.get(j).toString().contains("/*")) {
startComment = j;
}
if (line.get(j).toString().contains("*/")) {
endComment = j;
}
if (line.get(j).toString().contains(objectName)) {
objCheck = false;
Pattern p = Pattern.compile("\\b" + objectName + "\\b");
Matcher m = p.matcher(line.get(j).toString());
while (m.find()) {
objCheck = true;
objCount++;
}
if (objCheck) {
if (line.get(j).toString().contains("#")) {
int objIndex = line.get(j).toString().indexOf(objectName);
int commentIndex = line.get(j).toString().indexOf("#");
if (objIndex > commentIndex) {
objCount--;
}
} else {
if (line.get(j).toString().contains("--")) {
int objIndex = line.get(j).toString().indexOf(objectName);
int commentIndex = line.get(j).toString()
.indexOf("--");
if (objIndex > commentIndex) {
objCount--;
}
}
}
if ((j >= startComment && j <= endComment)||(j >= startComment && endComment==0)) {
objCount--;
}
}
}
if (line.get(j).toString().contains(keyword)) {
keyCheck = false;
Pattern p = Pattern.compile("\\b" + keyword + "\\b");
Matcher m = p.matcher(line.get(j).toString());
while (m.find()) {
keyCheck = true;
keyCount++;
}
if (keyCheck) {
if (line.get(j).toString().contains("#")) {
int objIndex = line.get(j).toString().indexOf(keyword);
int commentIndex = line.get(j).toString().indexOf("#");
if (objIndex > commentIndex) {
keyCount--;
}
} else {
if (line.get(j).toString().contains("--")) {
int objIndex = line.get(j).toString().indexOf(keyword);
int commentIndex = line.get(j).toString()
.indexOf("--");
if (objIndex > commentIndex) {
keyCount--;
}
}
}
if ((j >= startComment && j <= endComment)||(j >= startComment && endComment==0)) {
keyCount--;
}
}
}
if(objCount > 0 && keyCount >0){
check = true;
break loop;
} else
check = false;
}
return check;
}
}
I have two find occurence of two keywords present in the same list. Please suggest some ways so that I can reduce the execution time.
1) Before to start looking for any keyword, prepare the file content: remove the comments, ... .
2) Split file content in words.
3) Do not loop for each keyword: use a Set who stores all keywords.