private static int getTotalWordValue(String word) {
int totalWordValue = 0;
// Code that produces correct results.
for(int i=0; i < alpha.length(); i++) {
char letter = alpha.charAt(i);
for(char ch: word.toCharArray()) {
if(letter == ch) {
totalWordValue += i+1;
}
}
}
// Code that produces incorrect results.
totalWordValue = 0;
for(int i=0; i < alpha.length(); i++) {
String letter = String.valueOf(alpha.charAt(i)); // <-- here?
if(word.indexOf(letter) != -1) {
totalWordValue += i+1;
}
}
return totalWordValue;
}
Upon running the above code to solve Project Euler Problem 42 , I am getting different results. The first 'for' loop shown above outputs the correct results and the second 'for' loop outputs incorrect results.
The above code takes a String and returns its word value. For example, the word SKY will return a word value of 55 as the letters in this word add as follows (starting at 1):
19 + 11 + 25 = 55.
I have reduced the problem to the above code and do not understand why this occurs. Perhaps I have missed an important piece of information as it relates to the Java String class and its methods.
I am running Java 8 in Eclipse Neon.3 Release (4.6.3) on Windows 10.
The two pieces of code are entirely different.
In both cases you have an outer loop which serves up each character of the string alpha
in the variable letter
.
In the first case, you then have an inner loop which runs through every character of the string word
and counts every matching occurrence of letter
. When the inner loop has counted every occurrence of letter
in word
, the outer loop moves on to the next letter
.
In the second case, there's no inner loop. Each time around the outer loop you use word.indexOf(letter)
to try to find the index of the first occurrence of letter
in word
. If there is one, you advance your count. Either way, you're now done with that letter
and the outer loop moves on to the next letter
. There might have been other occurrences of letter
in word
, but this case didn't try to find them and count them.
The word value is incorrect in the second implementation for words that contain some letters multiple times. For example for WOOD, the first method will calculate 3 + 14 + 14 + 22, but the second will calculate 3 + 14 + 22.
Why? The first method iterates over characters of the word :
for(char ch: word.toCharArray()) { if(letter == ch) { totalWordValue += i+1; } }
The second method iterates over characters of the alphabet :
for(int i=0; i < alpha.length(); i++) { String letter = String.valueOf(alpha.charAt(i)); // <-- here? if(word.indexOf(letter) != -1) { totalWordValue += i+1; } }
So in the example of "WOOD", "O" will be counted only once, instead of twice.
As an aside, the conversion to String
is pointless here:
String letter = String.valueOf(alpha.charAt(i)); if(word.indexOf(letter) != -1) {
A better way to write the same thing:
char letter = alpha.charAt(i);
if (word.indexOf(letter) != -1) {
(But the implementation would still be incorrect.)
Finally, if the alphabet is English AZ, then a faster implementation is possible:
int totalWordValue = 0;
for (char c : word.toCharArray()) {
if ('A' <= c && c <= 'Z') {
totalWordValue += (c - 'A') + 1;
}
}
return totalWordValue;
indexOf
has 4 overloaded method and one of them except character
argument and return the index of the first occurrence of the character in the character sequence.
Now, coming to you question. In your scenario indexOf
and charAt
will behave same because you are passing ONLY character. And, since internally, But, imagine, you have a String
and you wanted to check and get the index of it from another long String
. Then what would you do ? There comes indexOf
I know this doesn't necessarily solve your question about the differences between the mentioned methods, but others have answered well enough on that.
You want the sum of the positions in the alphabet of the letters of a String? We can do that in one loop with some arithmetic, without the added overhead of the inner loops or the alpha
constant.
Like so:
public static int getWordValue(String word) {
int value = 0; //total word value
for(char c : word.toLowerCase().toCharArray()) { //iterate over character array of lower case string
int charAsInt = (int) c; //cast char to int, giving the ASCII value
if(charAsInt <= 122 && charAsInt >= 97) { //122 is the ASCII value of 'z', and 97 is 'a'
value += (charAsInt - 96); //only subtract 96 because we want 'a' to be 1, not 0
}
}
return value;
}
If the reason this works is unclear to you now, it will become evident upon examining an ASCII to decimal table. Let's check one out.
Make note of the values of lowercase 'a' and lowercase 'z'. They are our lower and upper bounds, respectively. We simply loop over each lower case character, converting it to its ASCII decimal value with an int
cast. Then we subtract our ASCII value by the value of 'a', minus one.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.