# CamelCase word count

Online challenge on Hacker Rank.

Problem Description

Alice wrote a sequence of words in CamelCase as a string of letters, S , having the following properties:

It is a concatenation of one or more words consisting of English letters. All letters in the first word are lowercase. For each of the subsequent words, the first letter is uppercase and rest of the letters are lowercase. Given, print the number of words in on a new line.

Input Format

A single line containing string S.

Constraints

Output Format

Print the number of words in string.

Sample Input

saveChangesInTheEditor


Sample Output

5


public class Solution {
private static int solve(String input) {
int len = input.length();
if (len == 0) {
return 0;
}
int count = 1;
for (int i = 0; i < len; i++) {
char c = input.charAt(i);
if ('A' <= c && c <= 'Z') {
count++;
}
else if (c == ' ') {
break;
}
}
return count;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.next();
System.out.println(solve(s));
}
}

• for the word CodeReview, your code will produce output 3 instead of 2 Dec 27, 2016 at 8:27
• @Abhisek if you read the problem's description, you'll see something like: "All letters in the first word are lowercase". However, you can point out in an answer how OP should treat this case (perhaps adding i != 0 in the second condition, etc). Feel free to add any other improvements Dec 27, 2016 at 8:55

# Glaring Deficiencies

1. What are you doing? You haven't bothered to explain your algorithm, either in the question body or in program comments.

2. Bugs. As pointed out by @Abhisek, your code prints 3 instead of 2. When you count the number of camelCase words, you should ignore whitespace, in fact, you should treat any non-alphabetic characters as lower-case, as per my understanding of the problem (although this is an edge case).

3. You haven't bothered to use any of Java's standard libraries. You would find the functions Character.isUpperCase(char), Character.isLowerCase(char) and Character.isWhitespace(char) extremely useful, instead of doing error-prone and language-limited manual checking. Also, String.isEmpty() is always a better check than String.length() == 0.

4. Non-descriptive naming. Your method does indeed solve a HackerRank problem, but that does not describe it properly. You could name it for what it does, something like getCamelCaseWordCount(String), as per some guidelines for Java method naming (Effective Java by Joshua Bloch).

5. You only use len once without the emptiness check. In fact, that is not required either, as the general code will handle that too. Just use the emptiness check to set the initial value of the word count to 0 or 1, depending on whether the input is empty or non-empty. respectively. You do not need to return early to avoid the loop as the loop won't iterate in the first place.

6. For that matter, as Strings are immutable, repeatedly calling .length() on the same String object does not have much overhead, so you do not need len even if you are concerned about the loop.

7. Avoid all the len business, and use a for-each loop. Kind of like:

for(char c : input.toCharArray()){//for JDK 1.5+
...
}


OR,

for(char c : input.chars()){//for JDK 1.8+
...
}

8. As usual, this is a 1-liner with Java 8 streams. This is an exact equivalent:

return in.isEmpty() ? 0 : 1 + in.chars().filter(Character::isUpperCase).count();


Note that the above returns a long, not an int. That's as per the Stream API.

Putting it all together,

# Modified Code

public class Test{
public static long getCamelCaseWordCountNormal(String in){
long words = in.isEmpty() ? 0 : 1;
for(char c : in.toCharArray()){
if(Character.isUpperCase(c)){
words++;
}
}
return words;
}

public static long getCamelCaseWordCountStreams(String in){
return in.isEmpty() ? 0 : 1 + in.chars().filter(Character::isUpperCase).count();
}
}