I will give you a Scala implementation for this problem.
Here it is an automatic test (in BDD style with ScalaTest)
import org.scalatest._ class RichStringSpec extends FlatSpec with MustMatchers { "A rich string" should "find the longest run of consecutive characters" in { import Example._ "abceedd".longestRun mustBe Set("ee", "dd") "aeebceeedd".longestRun mustBe Set("eee") "aaaaaaa".longestRun mustBe Set("aaaaaaa") "abcdefgh".longestRun mustBe empty } }
The following is an imperative style implementation with nested loops and mutable variables that you usually choose in Java or C ++:
object Example { implicit class RichString(string: String) { def longestRun: Set[String] = { val chunks = mutable.Set.empty[String] val ilen = string.length var gmax = 0 for ((ch, curr) <- string.zipWithIndex) { val chunk = mutable.ListBuffer(ch) var next = curr + 1 while (next < ilen && string(next) == ch) { chunk += string(next) next = next + 1 } gmax = chunk.length max gmax if (gmax > 1) chunks += chunk.mkString } chunks.toSet.filter( _.length == gmax ) } } }
The implementation of the functional style is given below, so there are no variables, no loops, but tail recursion with result storages and pattern matching to compare each character with the next (crazy!)?
object Example { implicit class RichString(string: String) { def longestRun: Set[String] = { def recurse(chars: String, chunk: mutable.ListBuffer[Char], chunks: mutable.Set[String]): Set[String] = { chars.toList match { case List(x, y, _*) if (x == y) => recurse( chars.tail, if (chunk.isEmpty) chunk ++= List(x, y) else chunk += y, chunks ) case Nil => // terminate recursion chunks.toSet case _ => // x != y recurse( chars.tail, chunk = mutable.ListBuffer(), chunks += chunk.mkString ) } } val chunks = recurse(string, mutable.ListBuffer(), mutable.Set.empty[String]) val max = chunks.map(_.length).max if (max > 0) chunks.filter( _.length == max ) else Set() } } }
For example, for a given string "aeebceeedd" both implementations described above will contain the following set of pieces (duplicate characters)
Set("ee", "eee", "dd")
and they will filter those pieces that have the maximum length (the result is "eee" ).