For a given string check if matches the pattern [scala]

Viewed 2133

I am beginner in Scala and I was wondering how I can build a function to check if it matches a definite pattern or not?

For example:

def patternFound(s:String): Boolean = (s) match {
    case s matches xyxy pattern => true //where x,y are two consecutive characters in the string
    case s matches xxyy pattern => false //where x, y are two characters in that string
    case (_) => false //default
}
//Here x,y are not definite characters but the string s should match a pattern 
//which consist a string of pattern containing characters in alternating positions

patternFound("babab")//true because pattern of xyxy found in it
patternFound("baabba")//false because pattern of xxyy found in it

Can anyone show with an example how I can achieve this?

Looking for a solution which returns true for any occurrence of xyxyxy pattern in a string, but returns false when the pattern is xxyy in that string.

Example: The function should return true if the string is "babab" or "ababa" (which has pattern xyxy in it), but returns false for "aabba" or "bbaab" (which has the pattern xxyy in it)

Any help is appreciated! Thank you in advance.

3 Answers

This might be possible with regular expressions and look arounds, but I just created a helper function:

/**
  * Checks for recurring pattern in a String
  * @param s The input String to check
  * @param patternSize The size of the expected pattern.  For example in the String "aabbaabbaabb" the pattern is "aabb" which is a length of 4
  */
def checkPattern(s: String, patternSize: Int): Boolean = {
  val grouped = s.grouped(patternSize)
  grouped.toSet.size == 1 // everything should be the same
}

Some example usage of that function:

checkPattern("abababab", 2) // true
checkPattern("aabbaabbaabb", 2) // false
checkPattern("aabbaabbaabb", 4) // true
checkPattern("abcabcabc", 3) // true

So for your code you could do use it with some guard statements:

def patternFound(s: String): Boolean = s match {
  case "" => false // empty Strings can't have patterns
  case s if checkPattern(s, 2) => true
  case s if checkPattern(s, 4) => true
  case _ => false
}

patternFound("ababababab") // true
patternFound("aabbaabb") // true
patternFound("aabbzz") // false

Edit: I think the other answer is better for what you are looking for, but here is my updated answer for you updated question:

def patternFound(s: String): Boolean = s match {
  s.nonEmpty && checkPattern(s, 2)
}

For the two examples you've posted, these two Regex patterns will cover it.

def patternFound(s:String): Boolean = {
  val ptrn1 = "(.)(.)\\1\\2".r
  val ptrn2 = "(.)\\1(.)\\2".r
  s match {
    case ptrn1(_,_) => true
    case ptrn2(_,_) => true
    case _ => false
  }
}

proof:

patternFound("rrgg")  // res0: Boolean = true
patternFound("hqhq")  // res1: Boolean = true
patternFound("cccx")  // res2: Boolean = false

But I suspect that your requirements, as stated, are not specific enough to cover exactly what you're looking for.


UPDATE

You're 2nd requirement now makes no sense. Everything that doesn't match the 1st pattern will return false so there's no point in testing for a specific pattern to return false.

def patternFound(s:String): Boolean = {
  val ptrn = "(.)(.)\\1\\2".r.unanchored
  s match {
    case ptrn(_,_) => true
    case _ => false
  }
}
patternFound("babab")   //true because pattern of xyxy found in it
patternFound("baabba")  //false because it doesn't match the target pattern
Related