Skip to content

Instantly share code, notes, and snippets.

@ryanlecompte
Last active December 19, 2015 21:08
Show Gist options
  • Select an option

  • Save ryanlecompte/6017746 to your computer and use it in GitHub Desktop.

Select an option

Save ryanlecompte/6017746 to your computer and use it in GitHub Desktop.
Finding the number of "monotonicity flips" in a Seq[Int] in Scala
// Finds the monotonicity breaks in a numerical sequence.
def findMonotonicityBreaks(items: Seq[Int]): Int = {
def comp(op: Symbol, a: Int, b: Int) = if (op == '<=) a <= b else a >= b
def flip(op: Symbol) = if (op == '<=) '>= else '<=
@tailrec
def detect(pairs: Seq[(Int, Int)], op: Symbol, breaks: Int): Int = {
pairs match {
case Seq() => breaks
case Seq((a, b), rest @ _*) if comp(op, a, b) => detect(rest, op, breaks)
case _ => detect(pairs, flip(op), breaks + 1)
}
}
if (items.isEmpty) 0
else {
val pairs = items.zip(items.tail)
pairs.collectFirst {
case (a, b) if a < b => '<=
case (a, b) if a > b => '>=
}.map { op => detect(pairs, op, 0)
}.getOrElse(0)
}
}
// Usage:
scala> findMonotonicityBreaks(Seq.empty[Int])
res21: Int = 0
scala> findMonotonicityBreaks(Seq(0,1,2,3,4,4,4,4,5,6))
res22: Int = 0
scala> findMonotonicityBreaks(Seq(0,1,2,3,3,3,2,1))
res23: Int = 1
scala> findMonotonicityBreaks(Seq(1,2,3,4,5,6,5,4,5,6,7))
res24: Int = 2
scala> findMonotonicityBreaks(Seq(5,4,3,2,1,0))
res25: Int = 0
scala> findMonotonicityBreaks(Seq(7,6,5,4,5,6,5,4,3,2,1))
res26: Int = 2
scala> findMonotonicityBreaks(Seq(1,2,3,3,3,2,1,0))
res27: Int = 1
scala> findMonotonicityBreaks(Seq(1,2,3,4,5,6,5,4,5,6,7,6,5,4,3))
res28: Int = 3
scala> findMonotonicityBreaks(scala.util.Random.shuffle(Vector.range(1, 100000)))
res29: Int = 66498
scala> findMonotonicityBreaks(Seq(5,5,5,4,3,2,1,0))
res30: Int = 0
scala> findMonotonicityBreaks(Seq(5,5,5,4,3,2,1,0,2,3,4,5))
res31: Int = 1
scala> findMonotonicityBreaks(Seq(1,1,1,1,2))
res32: Int = 0
scala> findMonotonicityBreaks(Seq(1,1,1,1,2,1))
res33: Int = 1
@gclaramunt
Copy link
Copy Markdown

Like this:
https://gist.github.com/gclaramunt/6021242

def  findMonotonicityBreaks(items:Seq[Int]):Int={
    @tailrec
    def breaksRec(itms:Seq[Int],currMono:Option[Int], count:Int):Int=itms match {
      case x::y::ys=> {
        val newMono=x.compare(y)
        val c=currMono.map(cm=>if (newMono != 0 && newMono != cm) 1 else 0).getOrElse(0)
        breaksRec(y::ys,Some(newMono),count+c )
      }
      case _ => count
    }
    breaksRec(items,None,0)
  }

@ryanlecompte
Copy link
Copy Markdown
Author

Great solutions, guys! Aren't Scala collections fun?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment