This program is intended to match a string to another string and calculate the number common substrings they share. For some reason, it always prints the same incorrect values. Using the same methods, how can I make this code work as I intended it to?
public static void main(String[] args) {
String secret = "word";
String guess = "gzek";
int count = 0;
int length = secret.length();
int guess_length = guess.length();
for(int i=0;i<length-1;i++){
if(secret.substring(i, i).equals(guess.substring(i, i))){
count ++;
}
}
System.out.println(count);
}
According to its JavaDoc, the end index parameter of the substring() method is exclusive:
#param beginIndex the beginning index, inclusive.
#param endIndex the ending index, exclusive.
This means that secret.substring(i, i) returns the sub-string from i to i-1, which is always the empty string "". Therefore, secret.substring(i, i).equals(guess.substring(i, i)) always compares "" with "" and is always true. Your code effectively counts the number of characters in guess.
If you want to compute all sub-strings of a string s, you need two loops, one for the start index and one for the end index:
for (int i = 0; i < s.length(); i++) {
for (int j = i; j < s.length(); j++) {
String substring = s.substring(i, j + 1);
// further code ...
}
}
Note that this only computes the sub-strings of one string. If I understood your question correctly, you want to compute all common sub-strings of two strings. To do this, you will need a total of four nested loops. This is going to be very slow even for small strings. There are of course much faster approaches, but they are also more complex.
Related
I have a task where I need to print words from an array in reverse(the word itself). This is what the task states :
Create an array of words called ‘wordList’ and assign the values ‘Stressed’, ‘Parts’, ‘Straw’, ‘Keep’, ‘Wolf’
Create a string called ‘reversedWord’ and do not assign it a value.
Similar to the above challenge, however, instead of reversing a sentence, reverse the order of the letters
within each string.
a. You will need to create a for-loop to access each word in turn. Immediately within the loop set
‘reversedWord = “”;’
b. Then create another for-loop inside of the first one to iterate backwards through the current
word. Update the value of ‘reversedWord’ on each iteration.
c. Print the reversed word on the screen.
STRETCH CHALLENGE: Handle the word so that it reads properly backwards. (Stressed becomes Dessert)
I don't know wether I'm just not understanding the wording of the task or not, but this is the code I have at the moment:
String[] wordList = {"Stressed", "Parts", "Straw", "Keep", "Wolf"};
String reversedWord;
for (int i = wordList.length; i >= 0; i++) {
reversedWord = "";
for (int j = wordList[i].length() - 1; i >= 0; j--) {
reversedWord += wordList[i].charAt(j);
System.out.println(reversedWord);
}
}
It gives me this error when i run it:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
at Main.main(Main.java:22)
Any help explanation would be helpful.
There are a few issues here. In the line
for (int i = wordList.length; i >= 0; i++) {
you are setting i to be the length of the wordList, which is 5. Remember, though, that array indexes start at 0. So the valid indexes of wordList are 0, 1, 2, 3, and 4, but not 5. To fix this, you can just subtract 1 from the length.
for (int i = wordList.length - 1; i >= 0; i++) {
The next problem is that you are increasing i at the end of each loop. Since it seems like you're trying to iterate backwards, you're gonna want to decrease i, not increase it.
for (int i = wordList.length - 1; i >= 0; i--) {
There is a simpler solution using Java's StringBuilder class:
public static void main(String[] args) {
String[] wordList = {"Stressed", "Parts", "Straw", "Keep", "Wolf"};
for (int i = 0; i < wordList.length; i++) {
String word = wordList[i]; // Get the word from array
word = new StringBuilder(word).reverse().toString(); // use StringBuilder to reverse the word
wordList[i] = word; // put word back in the array
}
System.out.println(Arrays.asList(wordList));
}
This outputs
[dessertS, straP, wartS, peeK, floW]
UPDATE:
For the words to read properly (first character in uppercase), You could do something like this:
word = word.toLowerCase();
word = word.replace(word.substring(0,1), word.substring(0,1).toUpperCase());
wordList[i] = word; // put word back in the array
There are more effective ways to do this, but is simpler for you to understand. This obviously outputs:
[Desserts, Strap, Warts, Peek, Flow]
substring(0,1) returns the first character (substring from index 0 to index 1; where the last index is not inclusive) as a String. Then, you are replacing the same substring with the uppercase substring.
Ok so I currently have a String array which contains keycodes, and i want to check if the first element shares common specifications with the second , e.g. [012] has similar elements with [123]. I currently loop through the length of the first element, and then loop through the length of the second element, and compare those two like this:
If(A[1].charAt(j) == A[2].charAt[i]) c++; c is a counter to show how many
common elements the keycodes have. Here is the method i created
static boolean hasSimilarity(String[] A, int K, int i){
int c = 0;
for(int j = 0;j<K;j++){
for(int m = j;m<K;m++){
if(A[i].charAt(j) == A[i+1].charAt(m)) c++;
}
}
return c != 0;
}
And here is the execution of it in the Main class:
int max = -1;
findSimilar FS = new findSimilar();
for (int i = 0; i < sum.length -1; i++) {
boolean hasSimilar = FS.hasSimilarity(key,K,i);
if (!hasSimilar) {
int summ = sum[i] + sum[i + 1];
System.out.println(summ);
if (summ > max) {
max = summ;
}
}
}
When i run this, i get a java.lang.StringIndexOutOfBoundsException out of range: 0 . What am I doing wrong? Is there any better way to compare two keycodes in order to find similarities beetween them?
This error:
java.lang.StringIndexOutOfBoundsException out of range: 0
Can only occur if one of your strings is the blank string "".
You are attempting to get charAt(0) when there is no char 0 (ie first char).
——-
You would avoid this problem, and have a far more efficient algorithm, if you first collected the counts of each character then compared those, which would have time complexity O(n), whereas your algorithm is O(n2) (albeit that it seems your n - the length of your inputs - is small).
So I was trying to build a solitaire encryption program, but I keep running into a problem when it comes to this method. The char array a represents the word the user inputs (converted it into an array to make it easier) and the char array b represents the alphabets so it has 25 indexes. What I am trying to do is match the alphabet to its number. It seemed simple enough but I am having a hard time as it keeps throwing an ArrayIndexOutOfBoundsException. I have tried to use for loops, nested for loops and other tests but it keeps throwing the exception or just outputs unexpected results such as [0, 0, 0, 0, 0]. I have debugged it and it seems like b[i] never equals a[j] so j will always be 0.
public static int[] converter(char[] a, char[] b){
int[] res = new int[a.length];
int i = 0;
int j = 0;
while(i < a.length){
if(b[i] == Character.toUpperCase(a[j])){ //Does not run through the first loop at all
res[j] = i + 1;
j = j + 1;
} else {
i = i + 1;
}
}
return res;
}
Please do not link the similar question. It does not answer my question.
The code below is a solution. We want the wordCharacterIndex to iterate through the word to see the place where a character is. The characterIndex iterates through the characters to compare with the word's character present at the wordCharacterIndex. After setting the result, we need to reset the characterIndex so that it goes back to the first character in the character array to compare with the other word characters, if we didn't, the following characters of the word would need to be at a higher character index, which is not what we want. Naming variables actual words is very important to better understand what you are trying to do within your code. You were comparing i < a.length while you were iterating through b[i] which made it possible to go larger than b's bounds and therefore cause an ArrayIndexOutOfBoundsException. I hope this helps you better understand.
public static int[] converter(char[] word, char[] characters){
int[] result = new int[word.length];
int characterIndex = 0;
int wordCharacterIndex = 0;
while(wordCharacterIndex < word.length){
if(characters[characterIndex] == Character.toUpperCase(word[wordCharacterIndex])){
result[wordCharacterIndex] = characterIndex + 1;
wordCharacterIndex++;
characterIndex = 0;
} else {
characterIndex++;
}
}
return result;
}
the function only returns value when I declare 'n' as int, but returns null when i use 'long'.
Given a string and a value n, the string should be concatenated n number of times. in the concatenated string, we will take the first n characters in that string and return the number of letter 'a' that appeared.
Print a single integer denoting the number of letter a's in the first n letters of the infinite string created by repeating s infinitely many times.
In this function, two parameters are passed, a string and a long value. The code works very well if use an int value instead of long. Please how do i fix this long and int issue ?
public class StringLettersRepeat {
static long repeatedString(String s, long n) {
String string = "";
int count =0;
for(int i=0; i<n; i++){
string+=s;
}
char[] strChar = string.toCharArray();
char[] result = new char[(int) n];
for(int i=0; i<strChar.length;i++){
result[i]=strChar[i];
}
for(char str : result){
if('a'==str){
count++;
}
}
return count;
}
public static void main(String[] args) {
long result = repeatedString("a", 1000l);
System.out.println(result);
}
}
I expect the output to return a value, which is the number of count.
for example, if I enter string "aba" and n=7, it should return 5.
But if i pass in a string, say 'a' with n=100000000000, it's supposed to return 100000000000 but it doesn't work. Please what's possibly wrong with my code?
Given your example of calling repeatedString("aba", 7), the resulting string would be "abaabaa", and has 5 a's, as you said.
But, you don't actually have to build that result string. Instead, realize that the result string is the original string repeated 2 times, plus the first 1 characters of the string, both of which can easily be calculated using division and remainder math:
long repeats = n / s.length();
long extra = n % s.length();
Now, if you count the number of a's in the string, you can multiply by repeats. You don't need to repeat the counting operation. If you then also count the number of a's in the first extra characters of string, you have your final result.
int countFull = 0, countExtra = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == 'a') {
countFull++;
if (i < extra)
countExtra++;
}
}
Then calculate the total and return it:
return countFull * repeats + countExtra;
This code also runs a lot faster, because you only have to iterate s once, it doesn't matter for performance what n is, and you don't copy any characters, so it also uses a lot less memory. It actually doesn't use any memory.
Big-O is:
Performance: O(m) where m is length of input string.
Memory: O(1)
Neither is related to n.
Test
System.out.println(repeatedString("aba", 7));
System.out.println(repeatedString("a", 100000000000L));
Output
5
100000000000
This is my assignment. I am not allowed to use if statements.
Write a program NumStrings.java that receives two strings through the command line as
input and then prints out the number of times the second string occurs as a substring in the
first.
My bad code:
public class Test {
public static void main(String[] args) {
String a = "HelloHelloHelloHello";
String b = "Hello";
int times = 0;
for(int i=0; i <= a.length()-5; i++){
for (int z=4; z<=(a.length()-1) && a.compareTo(b)==0; z++){
times = times +1;
}
}
System.out.print(times);
}
}
Here is the correct way to do it, using subString() (documentation here: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int)):
String a = "HelloHelloHelloHello";
String b = "Hello";
int times = 0;
for (int i = 0; i <= a.length() - b.length(); i++) {
String substring = a.subString(i, i + b.length());
if (substring.equals(b)) {
times = times + 1;
}
}
System.out.println(times);
And here is a way to do it without if statements... Which I don't recommend. But if you have to do it that way, this will work.
String a = "HelloHelloHelloHello";
String b = "Hello";
int times = 0;
for (int i = 0; i <= a.length() - b.length(); i++) {
String substring = a.substring(i, i + b.length());
for (int j = 0; substring.equals(b) && j < 1; j++) {
times = times + 1;
}
}
System.out.println(times);
Look at it this way: you don't have to count how often you find the second string in the first String, because you always have to check if you found it or not. So, to avoid all sorts of conditions or if statements, consider using firstString.split(secondString).
split(someString) will return you an array of remaining substrings once you "split" the base string everytime it finds your substring:
String first = "bababa";
String second = "a";
String[] substrings = first.split(second);
now substrings will look like this: ["b", "b", b"] because every a has been removed and the rest put in separate Strings.
Next you have to check the size of the array and you'll see how often your first String was split.
int count = substrings.length; // 3
However, this is not the end of it because we still have the following case:
String first = "bababaa";
With the above solution you would get an array of size 3: ["b", "b", "b"]. The last occurrence of a will only be removed without leaving any substring behind (not even an empty one '').
So you can take advantage of another (slightly different) split():
first.split(second, limit);
Where limit is the maximum number of occurrences the method tries to find. So how often can you find your second string in the first one? As many letters the first string has: int limit = first.length
first.split(second, first.length); // will produce [b, b, b, , ]
Can you see what happens? there are two empty strings at the end where there where two a. You get an array of substrings for everything that is found before or after the occurrence of the second String.
Naturally, when you split the string ba you would get ["b", ] so 2 substrings. But you don't care about the b just the "commas" in the middle (for every a a ,).
first.split(second, first.length).length -1; // that's how many commas there are, and thats how many second strings there are
EDIT
(thanks #saka1029 !) So, the "split" method still misses something when first="aaa" and second="aa" because it counts only 1 not 2 occurrences.
To correct that I thought of looping through the whole first string and checking only for the very first occurrence, and then removing the first letter and continuing (since OP already accepted another answer, I just post my code):
String first = "ZZZ";
String second = "ZZ";
int counter = 0; // counts the number of occurrences
int n = first.length(); // needs to be fixed, because we'll change the length of the first string in the loop
for(int i = 0; i < n; i++){ // check the first string letter by letter
String[] split = first.split(second, 2); // we want one substring and the rest (2 in total) like: ['', 'Z'] when we cut off the first 'ZZ'
counter += split.length - 1; // now add the number of occurrences (which will be either 0 or 1 in our case)
first = first.substring(1); // cut off the first letter of the first string and continue
}
System.out.println("counter = " + counter); // now we should get 3 for 'ZZZ'