2
\$\begingroup\$

Code

class Anagram(anagram: String) {
  def matches(candidates: Seq[String]) = {
    candidates.filter(isPermutation)
  }

  def isPermutation(candidate: String) = {
    (candidate.toLowerCase != anagram.toLowerCase) &&
        (candidate.toLowerCase.sortWith(_>_) ==
            anagram.toLowerCase.sortWith(_>_))
  }
}

Test Suite

import org.scalatest._

class AnagramSpecs extends FlatSpec with Matchers {
  it should "detect no matches" in {
    val detector = new Anagram("diaper")
    val anagrams = detector.matches(Seq("hello", "world", "zombies", "pants"))
    anagrams should equal (Seq())
  }

  it should "detect simple anagrams" in {
    val detector = new Anagram("ant")
    val anagrams = detector.matches(Seq("tan", "stand", "at"))
    anagrams should equal (Seq("tan"))
  }

  it should "detect multiple anagrams" in {
    val detector = new Anagram("master")
    val anagrams = detector.matches(Seq("stream", "pigeon", "maters"))
    anagrams.sorted should equal (Seq("maters", "stream"))
  }

  it should "not confuse different duplicates" in {
    val detector = new Anagram("galea")
    val anagrams = detector.matches(Seq("eagle"))
    anagrams should equal (Seq())
  }

  it should "not include identical words" in {
    val detector = new Anagram("corn")
    val anagrams = detector.matches(Seq(
      "corn", "dark", "Corn", "rank", "CORN", "cron", "park"
    ))
    anagrams should equal (Seq("cron"))
  }

  it should "elimitate anagrams with same checksum" in {
    val detector = new Anagram("mass")
    detector.matches(Seq("last")) should equal (Seq())
  }

  it should "eliminate anagrams subsets" in {
    val detector = new Anagram("good")
    detector.matches(Seq("dog", "goody")) should equal (Seq())
  }

  it should "detect anagrams" in {
    val detector = new Anagram("listen")
    val anagrams = detector.matches(Seq("enlists", "google", "inlets", "banana"))
    anagrams should equal (Seq("inlets"))
  }

  it should "detect more anagrams" in {
    val detector = new Anagram("allergy")
    val anagrams = detector.matches(Seq(
      "gallery", "ballerina", "regally", "clergy", "largely", "leading"
    ))
    anagrams.sorted should equal (Seq("gallery", "largely", "regally"))
  }

  it should "treat anagrams as case insensitive" in {
    val detector = new Anagram("Orchestra")
    val anagrams = detector.matches(Seq(
      "cashregister", "Carthorse", "radishes"
    ))
    anagrams should equal(Seq("Carthorse"))
  }
}

Although the code passes all the tests I still feel that there is still room for improvement. Currently I am new to Scala and functional programming both.

Source

\$\endgroup\$
4
\$\begingroup\$

Overall, short and sweet, with good detailed tests.

Performance

The anagram field (the subject) is lowercased and sorted many times. You could do perform these operations once at construction time.

The candidate parameter is lowercased twice, when you could do just once.

Naming

The Anagram class is rather an AnagramMatcher.

The anagram field is rather a subject.

isPermutation is rather isAnagram, with respect to subject.

\$\endgroup\$
  • \$\begingroup\$ Actually I wanted to see to what extent I can reduce assignment in code since it goes against functional paradigm. Saving lowercase and sorting state would need saving state I think. \$\endgroup\$ – CodeYogi Jun 21 '16 at 2:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.