public static boolean isIsogram(final String str) {
if (str == null) {
throw new IllegalArgumentException(
"str parameter may not be null."
);
}
if ("".equals(str)) {
return true;
}
final String lowerCase = str.toLowerCase();
final char[] chars = lowerCase.toCharArray();
final List charactersFound = new ArrayList();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (charactersFound.contains(c)) {
return false;
} else {
charactersFound.add(c);
}
}
return true;
}
Not pretty, not concise, but it gets the job done. I knew that it could be solved far more concisely using streams, so I switched to Kotlin and wrote this.
fun isIsogram(str: String): Boolean {
if ("" == str) {
return true
}
val distinctCharacters = str.toLowerCase()
.asSequence().distinct().count()
return str.length == distinctCharacters
}
I'm pretty sure something similar could be done in Java 8+, but I've been developing in Kotlin almost exclusively for almost two years now, so it's my go-to language for the JVM.
I've trained myself over the years to avoid function chaining so that one line makes my brain itch a bit. However, I think this implementation is much more expressive and concise than what I wrote in Java.
One of the reasons I like Kotlin is the implicit null safety. In the Kotlin solution, I didn't have to protect the function from a null argument value. It makes the solution more concise and easier to parse mentally. If I wanted to allow null as a value, I'd have to add special syntax to support it. That extra step always makes me stop and think is there a better way than allowing a null input and I can typically find a better way.
Using the stream features in my Kotlin solution reminded me that I wanted to learn more about Functional Programming. Code Wars offered a Haskell version of the kata, so I decided to give that a shot.
Unfortunately, I don't know anything about Haskell. Not even how to spell it. I always want to have just one L.
Fortunately, I listened to a lot of the early episodes of The Bikeshed and had heard Sean and Derek mention Miran Lipovaca's Learn You A Haskell website many times.
I started going through the content and found it very accessible. It's a good balance of explanation and examples. Pretty soon I was taking the individual topics and combining them to solve new problems.
For example, during the section on list operations, I was trying to write a function that would remove prune one list from another. That is, given lists A and B return A with everything in B removed. I couldn't find a solution using just the set operators, but once I got to the section on list operations a light bulb went of. After some trial and error, I came up with this:
filterOut s f = [ x | x <- s, not (elem x f) ]
For example:
ghci> filterOut ['A'..'Z'] ['I','P']
"ABCDEFGHJKLMNOQRSTUVWXYZ"
And, yes. Deep down inside I still find 3rd grader humor potty funny.
I still don't know enough to solve the Isogram problem in Haskell, but I'm getting close.