Given two strings with the same length, we check how many chars on the same positions are different. For example: ABCD and ABBD should return 1. Here is a link to a gist with tests, to have a better understanding of what I'm building. Here is my solution:
object Hamming {
def compute(str1: String, str2: String):Int = {
if (str1.length != str2.length)
throw new IllegalArgumentException("Strings have different length")
(0 to str1.length - 1).filter(i => str1(i) != str2(i)).size
}
}
-
\$\begingroup\$ It's vaguely entertaining to see an Exercism question here. \$\endgroup\$Trevoke– Trevoke2016年08月22日 13:10:13 +00:00Commented Aug 22, 2016 at 13:10
2 Answers 2
How about this variant?
object Hamming {
def apply(a: String, b: String): Int = if (a.length != b.length) {
throw new IllegalArgumentException(s"Strings a=$a and b=$b have different length.")
} else a.zip(b).count {
case (charA, charB) => charA != charB
}
}
The zip
-function does create a new collection of tuples with two corresponding chars side by side in every tuple. (Char, Char)
The count
-function counts the number of elements for which a boolean evaluation function, passed as an argument, returns true
. This should work not only for characters, because it uses pattern matching. Also if there are two arguments of the same type (e.g. for comparison) and I cannot further specify what they are, then I like to name them a
and b
.
I cannot tell if this solution is faster than yours, but I don't think there will be a significant difference.
P.S.:
- I see the function is named
compute
. Thats really general and abstract. I named itapply
. It can be called like this:Hamming("Alice", "Bob")
- Look at what I did with the brackets.
If you would like to use the function for other sequences than characters you can change the snippet to this:
def apply(a: Seq[_], b: Seq[_]): Int = if (a.size != b.size) { throw new IllegalArgumentException("Parameters have different length.") } else a.zip(b).count { case (charA, charB) => charA != charB }
Note of warning: I haven't done Scala in a while. The style may have changed, or I may have never known the right one, so I could be wrong.
It looks good, except for two things:
- Please, put brackets around one-line
if
s. It makes things much easier to keep track of in the long run, even if you don't need it now. Before you say "this is just a project to learn the language", if you get into good habits now, you won't have to break bad ones later. - You have a pair of newlines that have no purpose after the beginning and before the end of the
object
definition
Aside from that, it looks good! I like the 'algorithm' you chose to use; it's actually quite clever and easy to understand.
-
\$\begingroup\$ About if block, I know its a good practice to wrap one liners in javascript. I'm not sure about Scala, I've seen a lot of good code where people didn't do this, so I picked up that style. Maybe someone will have something to say about this case \$\endgroup\$HeeL– HeeL2015年07月01日 09:42:45 +00:00Commented Jul 1, 2015 at 9:42
-
\$\begingroup\$ @HeeL It's generally a better idea, for lots of reasons -- you see people talking about it in Java, C#, Javascript -- pretty much every language where you can wrap brackets around
if
blocks, it's said you should. I'd assume the same extends to Scala. \$\endgroup\$anon– anon2015年07月01日 09:46:40 +00:00Commented Jul 1, 2015 at 9:46