We were experimenting with parallel collections in Scala and wanted to check whether the result was ordered. For that, I wrote a small function on the REPL to do that check on the very large List we were producing:
def isOrdered(l:List[Int]):Boolean = { l match {
case Nil => true
case x::Nil => true
case x::y::Nil => x>y
case x::y::tail => x>y & isOrdered(tail)
}
}
It fails with a stackOverflow (how appropriate for a question here!).
I was expecting it to be tail-optimized. What's wrong?
isOrdered is not the last call in your code, the & operator is. Try this instead:
#scala.annotation.tailrec def isOrdered(l:List[Int]):Boolean = { l match {
case Nil => true
case x::Nil => true
case x::y::Nil => x>y
case x::y::tail => if (x>y) isOrdered(tail) else false
}
}
Your algorithm is incorrect. Even with #Kim's improvement, isOrdered(List(4,3,5,4)) returns true.
Try this:
def isOrdered(l:List[Int]): Boolean = l match {
case Nil => true
case x :: Nil => true
case x :: y :: t => if (x <= y) isOrdered(l.tail) else false
}
(also updated so that signs are correct)
edit: my perferred layout would be this:
def isOrdered(list: List[Int]): Boolean = list match {
case Nil => true
case x :: Nil => true
case x :: xs => if (x > xs.head) false
else isOrdered(xs)
}
The quick way if performance isn't a problem would be
def isOrdered(l: List[Int]) = l == l.sorted
It can't be tail-optimized because you return this: 'x>y & isOrdered(tail)'. It means it will need to keep it on the stack.
Use the #tailrec annotation to force an error when you expect functions to be tail-recursive. It will also explain why it can't be.
I think the problem is that you're using the bitwise-and operator (&) in your last case. Since the runtime needs to know the value of the isOrdered call before it can evaluate the &, it can't tail-optimize the function. (That is, there is more code to run--the bitwise-and operation--after isOrdered is called.)
Using && or an if statement may help.
Related
I am trying to solve a beginner problem but can't reach the solution:
If any duplicates in list, return true, else false. Empty lists considered.
def duplicates(a: List[Int]): Boolean = {
case Nil => false
case x :: xs =>
if(xs.contains(x)) true else false
}
But this doesn't work. And it's not recursive. It's just something where I wanted to start but I'm stuck. Please kindly help and try to avoid non-beginner solutions if reasonable.
You need to call your function recursively. So if xs doesn't contain x, then call the function but with the remaining list.
def duplicates(a: List[Int]): Boolean = a match {
case Nil => false
case x :: xs =>
if(xs.contains(x)) true else duplicates(xs)
}
I have an array val x : Array[Double] and would like to check as precondition to a function that every x(i) <= x(i+1) for all i. What's the way to do it using functional programming in Scala. I looked for e.g. foldLeft or foldRight but they accumulate rather than visiting every pair of adjacent elements.
Consider this:
def isMonotonic(arr:Array[Int]) =
if (arr.isEmpty) true
else (arr, arr.tail).zipped.forall {case (a,b) => a <= b}
Simplified solution (thanks to #som-snytt):
def isMonotonic(arr:Array[Int]) =
(arr, arr.drop(1)).zipped.forall (_ <= _)
You can use IterableLike.sliding:
val isMonotonic =
Seq(1,2,3,4,5).sliding(2).forall {
case Seq(x, y) => x < y
case _ => true
}
Edit:
Since you're using an Array[Double], you'll need:
val isMonotonic =
Array(1d, 2d, 3d, 4d, 5d).sliding(2).forall {
case Array(x, y) => x < y
case _ => true
}
With a couple of fine answers to choose from, the next question is: Can we make it generic?
This is my shot at it.
def isMonotonic[T](ts: Traversable[T])(implicit ev: Ordering[T]): Boolean = {
if (ts.size < 2) true
else if (ev.gt(ts.head, ts.tail.head)) false
else isMonotonic(ts.tail)
}
Appears to work for the following.
isMonotonic(Array('c','a','z')) // false
isMonotonic(Vector(3.1, 2.2, 7.7)) // false
isMonotonic(List[Int]()) // true
isMonotonic(Seq("abc", "bcb", "tz", "xs")) // true
A slightly different approach
def isMonotonic(xs:List[Int]) = xs.sliding(2)
.collectFirst{case List(x,y) if x > y => 1}
.isEmpty
Works on empty and length-one lists because the partial function is never defined on those. Because it's collectFirst, it bails at the first evidence it's not monotonic The xs zip xs.drop(1) idea can be used if preferred
Let's say I have something like the following:
case class Thing(num: Int)
val xs = List(Thing(1), Thing(2), Thing(3))
What I'd like to do is separate the list into one particular value, and the rest of the list. The target value can be at any position in the list, or may not be present at all. The single value needs to be handled separately, after the other values are handled, so I can't simply use pattern matching.
What I have so far is this:
val (targetList, rest) = xs.partition(_.num == 2)
val targetEl = targetList match {
case x :: Nil => x
case _ => null
}
Is it possible to combine the two steps? Like
val (targetEl, rest) = xs.<some_method>
A note on handling order:
The reason that the target element must be handled last is that this is for use in a HTML template (Play framework). The other elements are looped through, and a HTML element is rendered for each. After that group of elements, another HTML element is created for the target element.
You can do it with pattern-matching in map, you just need multiple cases:
xs map {
case t # Thing(1) => // do something with thing 1
case t => // do something with the other things
}
To handle the OP's extra requirements:
xs map {
case t # Thing(num) if(num != 1) => // do something with things that are not "1"
case t => // do something with thing 1
}
Following produces two lists as tuples for some condition.
case class Thing(num: Int)
val xs = List(Thing(1), Thing(2), Thing(3))
val partioned = xs.foldLeft((List.empty[Thing], List.empty[Thing]))((x, y) => y match {
case t # Thing(1) => (x._1, t :: x._2)
case t => (t :: x._1, x._2)
})
//(List(Thing(3), Thing(2)),List(Thing(1)))
Try this:
val (targetEl, rest) = (xs.head, xs.tail)
It works for non-empty list. Nil case must be handled separately.
After some experimentation, I've come up with the following, which is almost what I'm looking for:
var (maybeTargetEl, rest) = xs
.foldLeft((Option.empty[Thing], List[Thing]())) { case ((opt, ls), x) =>
if (x.num == 1)
(Some(x), ls)
else
(opt, x :: ls)
}
The target value is still wrapped in a container, but at least it guarantees a single value.
After that I can do
rest map <some_method>
maybeTargetEl map <some_other_method>
If the order of the original list is important:
var (maybeTargetEl, rest) = xs.
foldLeft((Option.empty[Thing], ListBuffer[Thing]())){ case ((opt, lb), x) =>
if (x.num == 1)
(Some(x), ls)
else
(opt, lb += x)
} match {
case (opt, lb) => (opt, lb.toList)
}
#evanjdooner Your solution with fold works if target element is present only once. If you want to extract only one occurrence of target element:
def find(xs: List[T], target: T, prefix: List[T]) = xs match {
case target :: tail => (target, prefix ::: tail)
case other :: tail => find(tail, target, other :: prefix)
case Nil => throw new Exception("Not found")
}
val (el, rest) = find(xs, target, Nil)
Sorry, I can't add it as a comment.
Scenario:
val col: IndexedSeq[Array[Char]] = for (i <- 1 to n) yield {
val x = for (j <- 1 to m) yield 'x'
x.toArray
}
This is a fairly simple char matrix. toArray used to allow updating.
var west = last.x - 1
while (west >= 0 && arr(last.y)(west) == '.') {
arr(last.y)(west) = ch;
west -= 1;
}
This is updating all . to ch until a non-dot char is found.
Generically, update until stop condition is met, unknown number of steps.
What is the idiomatic equivalent of it?
Conclusion
It's doable, but the trade-off isn't worth it, a lot of performance is lost to expressive syntax when the collection allows updating.
Your wish for a "cleaner, more idiomatic" solution is of course a little fuzzy, because it leaves a lot of room for subjectivity. In general, I'd consider a tail-recursive updating routine more idiomatic, but it might not be "cleaner" if you're more familiar with a non-functional programming style. I came up with this:
#tailrec
def update(arr:List[Char], replace:Char, replacement:Char, result:List[Char] = Nil):List[Char] = arr match {
case `replace` :: tail =>
update(tail, replace, replacement, replacement :: result)
case _ => result.reverse ::: arr
}
This takes one of the inner sequences (assuming a List for easier pattern matching, since Arrays are trivially convertible to lists), and replaces the replace char with the replacement recursively.
You can then use map to update the outer sequence, like so:
col.map { x => update(x, '.', ch) }
Another more reusable alternative is writing your own mapUntil, or using one which is implemented in a supplemental library (Scalaz probably has something like it). The one I came up with looks like this:
def mapUntil[T](input:List[T])(f:(T => Option[T])) = {
#tailrec
def inner(xs:List[T], result:List[T]):List[T] = xs match {
case Nil => Nil
case head :: tail => f(head) match {
case None => (head :: result).reverse ::: tail
case Some(x) => inner(tail, x :: result)
}
}
inner(input, Nil)
}
It does the same as a regular map invocation, except that it stops as soon as the passed function returns None, e.g.
mapUntil(List(1,2,3,4)) {
case x if x >= 3 => None
case x => Some(x-1)
}
Will result in
List[Int] = List(0, 1, 3, 4)
If you want to look at Scalaz, this answer might be a good place to start.
x3ro's answer is the right answer, esp. if you care about performance or are going to be using this operation in multiple places. I would like to add simple solution using only what you find in the collections API:
col.map { a =>
val (l, r) = a.span(_ == '.')
l.map {
case '.' => ch
case x => x
} ++ r
}
I am looking for a way to do pattern matching based on the result of a function evaluation rather than the type of the val. For example,
def f1(x:String):Boolean = if (x contains ("Helllo")) true else false
val caller="Hello"
caller match
{
case f1(caller) => println ("caller said hello")
case _ => println ("caller did not say hello")
}
any idea ?
You want to use pattern guards:
caller match
{
case x if f1(x) => println ("caller said hello")
case _ => println ("caller did not say hello")
}
I would prefer to do it without guard, that would a bit faster and cleaner:
f1(caller) match {
case true => ....
case false => ....
}
but for Boolean better to use if/else expression, that would be cleaner in byte code and a bit faster