DEV Community

Nikita Zonov
Nikita Zonov

Posted on

Find all subsequences in the sequence

Let's start with the signature of our function

def groupSubseq[T](in: Seq[T])(p: (T, T) => Boolean): Seq[Seq[T]]

Here p is predicate we use before add item to the existing subseq or create new one

We are going to use foldLeft

def groupSubseq[T](in: Seq[T])(p: (T, T) => Boolean): Seq[Seq[T]] = in
  .foldLeft(Seq.empty[Seq[T]])((seq, item) => seq match {
    case Nil => Seq(Seq(item)) // processing first element
    case currentSeq +: tail =>
      if (p(currentSeq.head, item)) {
        // new element satisfies the condition, add it to the subsequence
        (item +: currentSeq) +: tail 
      } else {
        // new element not satisfies the condition, start new subsequence
        Seq(item) +: seq
      }
  })

Looks like we've done here. But let me explain ))... This post is a result of a few similar tasks I've faced recently.

Task 1

Find all the sequences of the same character in the given string and count number of the character in each sequence

def countChar(seq: String): Seq[Char, Int] = ???

val test1 = "aaabbaaaabbb"

countChar(test1)

//res0: List((a,3), (b,2), (a,4), (b,3))

Task 2

Count number of all the sequences of the same sign in the given sequence of Int

def countSign(seq: Set[Int]): Int = ???

val test1 = Seq(1, 2, 3, -3, -2, 6, 7, 8, 9, -3, -1, -6, 7)

countSign(test1)

//res0: 3

Using our recent invention we may solve it easily

def countChar(seq: String) =
  groupSubseq(seq)(_ == _).map(seq => seq.head -> seq.length).reverse

countChar("aaabbaaacddddd")

// res0: Seq[(Char, Int)] = List((a,3), (b,2), (a,3), (c,1), (d,5))


def countSign(seq: Seq[Int]) = groupSubseq(seq)(_ * _ > 0).count(_.length > 2)

countSign(Seq(1, 2, 3, 4, -1, 1, -1, -2, -3, -4, 0, 0, 0))

// res1: Int = 2

I hope to see your pros and cons in the comments. Thanks for reading.

Top comments (0)