1. Overview

An acronym is a word or series of letters formed by taking the initial letters of a phrase or a text. Some popular acronyms are FAQ (Frequently Asked Questions), CEO (Chief Executive Officer), and so on.

In this tutorial, we’ll implement a Scala program to generate an acronym for an input string.

2. Solution

In this section, let’s implement the solution using Scala. Before we dive into the implementation, let’s clarify the assumptions guiding our approach.

2.1. Assumptions

Acronyms are formed exclusively from letters. If a word starts with a number or a special character, we skip it, considering it invalid.

The acronym might be empty if the input is empty or if there are no valid words in the input.

There should also be no spaces between letters.

2.2. Implementation

Let’s implement the solution for the acronym generation:

def acronymUsingSplit(text: String): String = {
  text
    .split("\\s")
    .filterNot(_.trim.isEmpty)
    .map(_.head)
    .filter(_.isLetter)
    .mkString
    .toUpperCase
}

Initially, we split the text using the regex for space and removed the words that might only contain spaces. Subsequently, we take the first character of the word using the head() method. Then, we select only alphabets using the isLetter() method. Finally, the letters are combined using mkString() and converted into upper case.

3. Testing the Solution

Now that the implementation is completed, we can test different scenarios.

3.1. Testing Different Cases

Let’s write a unit test to make sure that the code is working as expected. We can use ScalaTest to write the test cases.

Let’s start with testing the positive case:

it should "generate acronym for FAQ" in {
  val acronym = acronymUsingSplit("Frequently Asked Questions")
  acronym shouldBe "FAQ"
}

Next, let’s add a test for a case that contains special characters:

it should "generate acronym for NASA with extra spaces in between" in {
  val acronym =
    acronymUsingSplit("National Aeronautics & Space   Administration ")
  acronym shouldBe "NASA"
}

Finally, we can add a test case for an acronym that could be empty:

it should "generate empty acronym for numeric/special char starting string" in {
  val acronym = acronymUsingSplit("1is 7m @num")
  acronym shouldBe empty
}

3.2. Property-Based Testing

We’ve included several test cases for various scenarios, but it’s possible that we might have overlooked some cases. For this situation, we can enhance testing by incorporating property-based testing.

We can use the ScalaCheck library to write property-based tests in Scala. ScalaTest provides an integration for this, and we can add it to the build.sbt:

libraryDependencies += "org.scalatestplus" %% "scalacheck-1-17" % "3.2.17.0" % Test

Now, we can mix in the ScalaCheckPropertyChecks trait and generate random sentences using ScalaCheck generators:

val sentenceGenerator: Gen[String] = for {
  charPart <- Gen.alphaStr
  numPart <- Gen.listOfN(5, Gen.numChar).map(_.mkString)
  specialCharPart <- Gen
    .listOfN(1, Gen.oneOf(Seq('@', "_", "*")))
    .map(_.mkString)
  alphaNum <- Gen.alphaNumStr
} yield s"$charPart $numPart $specialCharPart$charPart $alphaNum"

Finally, we can use this generator to test various cases:

it should "generate acronym for random generated string correctly" in {
  forAll(sentenceGenerator) { sentence =>
    val acronym = AcronymGenerator.acronymUsingSplit(sentence)
    withClue(s"Gen sentence = $sentence , acronym = $acronym") {
      acronym.forall(_.isLetter) shouldBe true
      acronym.exists(_ == ' ') shouldBe false
      acronym.forall(_.isUpper) shouldBe true
    }
  }
}

The forAll() method generates 10 random sentences using the provided generator. We translated the initially defined assumptions into the properties suitable for the testing.

4. Conclusion

In this short article, we implemented a program to generate an acronym for a given text. Moreover, we wrote comprehensive test cases to ensure that our implementation works as expected.

As always, the sample code used in this tutorial is available over on GitHub.

Comments are closed on this article!