Scala program that gives me smallest and largest number from an Array - scala

I am looking for a scala code that gives me new Array that contains the smallest and largest number in myArr.
I am able to write the below code . How do i write it in a single function
scala> val myArr = Array(1,5,3)
myArr: Array[Int] = Array(1, 5, 3)
scala> myArr.reduce((a,b) => if(a>b)a else b)
res0: Int = 5
scala> myArr.reduce((a,b) => if(a<b)a else b)
res1: Int = 1
Expected output : Array(1,5)

val myArr = Array(1,5,3)
val result = myArr.foldLeft(List.empty[Int]){
case (min :: max :: _, value) if value < min => List(value, max) // lower than the minimun
case (min :: max :: _, value) if value > max => List(min, value) // greater than the maximun
case (Nil, value) => List(value, value) // first value
case (l, _) => l // the final list doesn't need to be updated
}
you can check it here https://scastie.scala-lang.org/XLE8VAKTRhWbl0JFrjGgnw
It uses the list to have better pattern matching.

Related

"conditionalZip" operator in Akka Streams

Assume that I have two sources:
val first = Source(1 :: 2 :: 4 :: 6 :: Nil)
val second = Source(1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: Nil)
Is it possible to create a zip that will pair only elements based on a condition? I mean something like:
first.conditionalZip(second, _ == _) // if that method exited
That code would take the element from the first source and drop elements from the second until there is an element that satisfies the condition, and then output a tuple. The result for the above call would be (1, 1), (2, 2), (4, 4), (6, 6).
Consider zipping the two Sources, followed by using statefulMapConcat to transform the zipped elements in accordance with the condition function, as shown below:
import akka.stream.scaladsl._
import akka.NotUsed
def popFirstMatch(ls: List[Int], condF: Int => Boolean): (Option[Int], List[Int]) = {
ls.find(condF) match {
case None =>
(None, ls)
case Some(e) =>
val idx = ls.indexOf(e)
if (idx < 0)
(None, ls)
else {
val (l, r) = ls.splitAt(idx)
(r.headOption, l ++ r.tail)
}
}
}
def conditionalZip( first: Source[Int, NotUsed],
second: Source[Int, NotUsed],
filler: Int,
condFcn: (Int, Int) => Boolean ): Source[(Int, Int), NotUsed] = {
first.zipAll(second, filler, filler).statefulMapConcat{ () =>
var prevList = List.empty[Int]
tuple => tuple match { case (e1, e2) =>
if (e2 != filler) {
if (e1 != filler && condFcn(e1, e2))
(e1, e2) :: Nil
else {
if (e1 != filler)
prevList :+= e1
val (opElem, rest) = popFirstMatch(prevList, condFcn(_, e2))
prevList = rest
opElem match {
case None => Nil
case Some(e) => (e, e2) :: Nil
}
}
}
else
Nil
}
}
}
Test running:
import akka.actor.ActorSystem
implicit val system = ActorSystem("system")
implicit val ec = system.dispatcher
// Example 1:
val first = Source(1 :: 2 :: 4 :: 6 :: Nil)
val second = Source(1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: Nil)
conditionalZip(first, second, Int.MinValue, _ == _).runForeach(println)
// (1,1)
// (2,2)
// (4,4)
// (6,6)
conditionalZip(first, second, Int.MinValue, _ > _).runForeach(println)
// (4,3)
// (6,4)
conditionalZip(first, second, Int.MinValue, _ < _).runForeach(println)
// (1,2)
// (2,3)
// (4,5)
// (6,7)
// Example 2:
val first = Source(3 :: 9 :: 5 :: 5 :: 6 :: Nil)
val second = Source(1 :: 3 :: 5 :: 2 :: 5 :: 6 :: Nil)
conditionalZip(first, second, Int.MinValue, _ == _).runForeach(println)
// (3,3)
// (5,5)
// (5,5)
// (6,6)
conditionalZip(first, second, Int.MinValue, _ > _).runForeach(println)
// (3,1)
// (9,3)
// (5,2)
// (6,5)
conditionalZip(first, second, Int.MinValue, _ < _).runForeach(println)
// (3,5)
// (5,6)
A few notes:
Method zipAll (available on Akka Stream 2.6+) zips the two Sources while padding the one with fewer elements with provided "filler" values. In this case, these fillers are of no interest hence should be assigned a distinct value from actual elements.
An internal List, prevList, is used within statefulMapConcat to store elements from the 1st Source for comparing in following iterations with elements from the 2nd Source. The List can be replaced with a Set for better lookup performance if elements within the Sources are distinct.
Method popFirstMatch is for extracting the first element in the prevList that matches the provided partial condition function, returning a Tuple of the element of type Option and the remaining List.
NOTE that this is just an illustration of how statefulMapConcat may be a solution for the described problem. Behavior of the sample code may not necessarily match the exact requirement without detailed implementation to either cover all cases or refine the scope of the fairly broad condition function (Int, Int) => Boolean.

Scala: Remove duplicated integers from Vector( tuples(Int,Int) , ...)

I have a big size of a vector (about 2000 elements), inside consists of many tuples, Tuple(Int,Int), i.e.
val myVectorEG = Vector((65,61), (29,49), (4,57), (12,49), (24,98), (21,52), (81,86), (91,23), (73,34), (97,41),...))
I wish to remove the repeated/duplicated integers for every tuple at the index (0), i.e. if Tuple(65,xx) repeated at other Tuple(65, yy) inside the vector, it should be removed)
I enable to access them and print out in this method:
val (id1,id2) = ( allSource.foreach(i=>println(i._1)), allSource.foreach(i=>i._2))
How can I remove duplicate integers? Or I should use another method, rather than using foreach to access my element index at 0
To remove all duplicates, first group by the first tuple and only collect the tuples where there is only one tuple that belongs to that particular key (_._1). Then flatten the result.
myVectorEG.groupBy(_._1).collect{
case (k, v) if v.size == 1 => v
}.flatten
This returns a List which you can call .toVector on if you need a Vector
This does the job and preserves order (unlike other solutions) but is O(n^2) so potentially slow for 2000 elements:
myVectorEG.filter(x => myVectorEG.count(_._1 == x._1) == 1)
This is more efficient for larger vectors but still preserves order:
val keep =
myVectorEG.groupBy(_._1).collect{
case (k, v) if v.size == 1 => k
}.toSet
myVectorEG.filter(x => keep.contains(x._1))
You can use a distinctBy to remove duplicates.
In the case of Vector[(Int, Int)] it will look like this
myVectorEG.distinctBy(_._1)
Updated, if you need to remove all the duplicates:
You can use groupBy but this will rearrange your order.
myVectorEG.groupBy(_._1).filter(_._2.size == 1).flatMap(_._2).toVector
Another option, taking advantage that you want the list sorted at the end.
def sortAndRemoveDuplicatesByFirst[A : Ordering, B](input: List[(A, B)]): List[(A, B)] = {
import Ordering.Implicits._
val sorted = input.sortBy(_._1)
#annotation.tailrec
def loop(remaining: List[(A, B)], previous: (A, B), repeated: Boolean, acc: List[(A, B)]): List[(A, B)] =
remaining match {
case x :: xs =>
if (x._1 == previous._1)
loop(remaining = xs, previous, repeated = true, acc)
else if (!repeated)
loop(remaining = xs, previous = x, repeated = false, previous :: acc)
else
loop(remaining = xs, previous = x, repeated = false, acc)
case Nil =>
(previous :: acc).reverse
}
sorted match {
case x :: xs =>
loop(remaining = xs, previous = x, repeated = false, acc = List.empty)
case Nil =>
List.empty
}
}
Which you can test like this:
val data = List(
1 -> "A",
3 -> "B",
1 -> "C",
4 -> "D",
3 -> "E",
5 -> "F",
1 -> "G",
0 -> "H"
)
sortAndRemoveDuplicatesByFirst(data)
// res: List[(Int, String)] = List((0,H), (4,D), (5,F))
(I used List instead of Vector to make it easy and performant to write the tail-rec algorithm)

Scala: Find max sum of consecutive negative numbers in a List of Double

I have a List[Double] with the following values:
{-1.2200000000000006, -1.3200000000000003, -1.0099999999999998, 22.22, 11.11,
-31.310000000000002, -0.9799999999999986,-4, -5, 3, 2, 2.959999999999999}`
I was to find the max sum of the consecutive negative numbers.
So from original list to separate consecutive lists of negative and positive
{
{-1.2200000000000006, -1.3200000000000003, -1.0099999999999998},
{22.22, 11.11},
{-31.310000000000002, -0.9799999999999986,-4, -5},
{3, 2, 2.959999999999999}
}
then remove the positive consecutive numbers
{
{-1.2200000000000006, -1.3200000000000003, -1.0099999999999998},
{-31.310000000000002, -0.9799999999999986,-4, -5}
}
then sum
{-3.5500000000000007, -41.29}
then change to absolute values
{3.5500000000000007, 41.29}
then find max = 41.29
You can use foldLeft for that:
val (max, _) = list.foldLeft((0,0)) {
case((max, current), n) if(n >= 0) => (max, 0)
case((m, current), n) =>
val sum = current - n
(sum max m, sum)
}
If you really mean to sum all the consecutive negative numbers, and then find the maximum sum, this will do it.
val nums = List(-1.2200000000000006, -1.3200000000000003, -1.0099999999999998,
22.22, 11.11, -31.310000000000002, -0.9799999999999986, 2.959999999999999)
nums.foldLeft(List[Double]()){
case (l,n) if n < 0 => if (l.isEmpty) List(n) else n + l.head :: l.tail
case (l, _) => Double.MinValue :: l
}.max
// res0: Double = -3.5500000000000007
update
OK, a minor change will get you what you're after.
nums.foldLeft(List(0.0)){
case (l,n) if n < 0 => n + l.head :: l.tail
case (l, _) => 0.0 :: l
}.min.abs // res0: Double = 32.29
Note: What you're actually after is the minimum sum. If you want it expressed as a positive number you can get the absolute value after the fact.
You could use sliding.
For sums of consecutive pairs of negative numbers:
val doubles = List(-1.2200000000000006, -1.3200000000000003, ...)
val result = doubles.sliding(2)
.collect { case List(a, b) if a < 0 && b < 0 => List(a, b) }
.map(_.sum)
.min
.abs

How to elegantly extract range of list based on specific criteria?

I want to extract range of elements from a list, meeting the following requirements:
First element of range has to be an element previous to element matching specific condition
Last element of range has to be an element next to element matching specific condition
Example: For list (1,1,1,10,2,10,1,1,1) and condition x >= 10 I want to get (1,10,2,10,1)
This is very simple to program imperatively, but I am just wondering if there is some smart Scala-functional way to achieve it. Is it?
Keeping it in the scala standard lib, I would solve this using recursion:
def f(_xs: List[Int])(cond: Int => Boolean): List[Int] = {
def inner(xs: List[Int], res: List[Int]): List[Int] = xs match {
case Nil => Nil
case x :: y :: tail if cond(y) && res.isEmpty => inner(tail, res ++ (x :: y :: Nil))
case x :: y :: tail if cond(x) && res.nonEmpty => res ++ (x :: y :: Nil)
case x :: tail if res.nonEmpty => inner(tail, res :+ x)
case x :: tail => inner(tail, res)
}
inner(_xs, Nil)
}
scala> f(List(1,1,1,10,2,10,1,1,1))(_ >= 10)
res3: List[Int] = List(1, 10, 2, 10, 1)
scala> f(List(2,10,2,10))(_ >= 10)
res4: List[Int] = List()
scala> f(List(2,10,2,10,1))(_ >= 10)
res5: List[Int] = List(2, 10, 2, 10, 1)
Maybe there is something I did not think of in this solution, or I missunderstood something, but I think you will get the basic idea.
Good functional algorithm design practice is all about breaking complex problems into simpler ones.
The principle is called Divide and Conquer.
It's easy to extract two simpler subproblems from the subject problem:
Get a list of all elements after the matching one, preceded with this matching element,
preceded with an element before it.
Get a list of all elements up to the latest matching one, followed by the matching element and
the element after it.
The named problems are simple enough for the appropriate functions to be implemented, so no subdivision is required.
Here's the implementation of the first function:
def afterWithPredecessor
[ A ]
( elements : List[ A ] )
( test : A => Boolean )
: List[ A ]
= elements match {
case Nil => Nil
case a :: tail if test( a ) => Nil // since there is no predecessor
case a :: b :: tail if test( b ) => a :: b :: tail
case a :: tail => afterWithPredecessor( tail )( test )
}
Since the second problem can be seen as a direct inverse of the first one, it can be easily implemented by reversing the input and output:
def beforeWithSuccessor
[ A ]
( elements : List[ A ] )
( test : A => Boolean )
: List[ A ]
= afterWithPredecessor( elements.reverse )( test ).reverse
But here's an optimized version of this:
def beforeWithSuccessor
[ A ]
( elements : List[ A ] )
( test : A => Boolean )
: List[ A ]
= elements match {
case Nil => Nil
case a :: b :: tail if test( a ) =>
a :: b :: beforeWithSuccessor( tail )( test )
case a :: tail =>
beforeWithSuccessor( tail )( test ) match {
case Nil => Nil
case r => a :: r
}
}
Finally, composing the above functions together to produce the function solving your problem becomes quite trivial:
def range[ A ]( elements : List[ A ] )( test : A => Boolean ) : List[ A ]
= beforeWithSuccessor( afterWithPredecessor( elements )( test ) )( test )
Tests:
scala> range( List(1,1,1,10,2,10,1,1,1) )( _ >= 10 )
res0: List[Int] = List(1, 10, 2, 10, 1)
scala> range( List(1,1,1,10,2,10,1,1,1) )( _ >= 1 )
res1: List[Int] = List()
scala> range( List(1,1,1,10,2,10,1,1,1) )( _ == 2 )
res2: List[Int] = List(10, 2, 10)
The second test returns an empty list since the outermost elements satisfying the predicate have no predecessors (or successors).
def range[T](elements: List[T], condition: T => Boolean): List[T] = {
val first = elements.indexWhere(condition)
val last = elements.lastIndexWhere(condition)
elements.slice(first - 1, last + 2)
}
scala> range[Int](List(1,1,1,10,2,10,1,1,1), _ >= 10)
res0: List[Int] = List(1, 10, 2, 10, 1)
scala> range[Int](List(2,10,2,10), _ >= 10)
res1: List[Int] = List(2, 10, 2, 10)
scala> range[Int](List(), _ >= 10)
res2: List[Int] = List()
Zip and map to the rescue
val l = List(1, 1, 1, 10, 2, 1, 1, 1)
def test (i: Int) = i >= 10
((l.head :: l) zip (l.tail :+ l.last)) zip l filter {
case ((a, b), c) => (test (a) || test (b) || test (c) )
} map { case ((a, b), c ) => c }
That should work. I only have my smartphone and am miles from anywhere I could test this, so apologise for any typos or minor syntax errors
Edit: works now. I hope it's obvious that my solution shuffles the list to the right and to the left to create two new lists. When these are zipped together and zipped again with the original list, the result is a list of tuples, each containing the original element and a tuple of its neighbours. This is then trivial to filter and map back to a simple list.
Making this into a more general function (and using collect rather than filter -> map)...
def filterWithNeighbours[E](l: List[E])(p: E => Boolean) = l match {
case Nil => Nil
case li if li.size < 3 => if (l exists p) l else Nil
case _ => ((l.head :: l) zip (l.tail :+ l.last)) zip l collect {
case ((a, b), c) if (p (a) || p (b) || p (c) ) => c
}
}
This is less efficient than the recursive solution but makes the test much simpler and more clear. It can be difficult to match the right sequence of patterns in a recursive solution, as the patterns often express the shape of the chosen implementation rather than the original data. With the simple functional solution, each element is clearly and simply being compared to its neighbours.

Scala Get First and Last elements of List using Pattern Matching

I am doing a pattern matching on a list. Is there anyway I can access the first and last element of the list to compare?
I want to do something like..
case List(x, _*, y) if(x == y) => true
or
case x :: _* :: y =>
or something similar...
where x and y are first and last elements of the list..
How can I do that.. any Ideas?
Use the standard :+ and +: extractors from the scala.collection package
ORIGINAL ANSWER
Define a custom extractor object.
object :+ {
def unapply[A](l: List[A]): Option[(List[A], A)] = {
if(l.isEmpty)
None
else
Some(l.init, l.last)
}
}
Can be used as:
val first :: (l :+ last) = List(3, 89, 11, 29, 90)
println(first + " " + l + " " + last) // prints 3 List(89, 11, 29) 90
(For your case: case x :: (_ :+ y) if(x == y) => true)
In case you missed the obvious:
case list # (head :: tail) if head == list.last => true
The head::tail part is there so you don’t match on the empty list.
simply:
case head +: _ :+ last =>
for example:
scala> val items = Seq("ham", "spam", "eggs")
items: Seq[String] = List(ham, spam, eggs)
scala> items match {
| case head +: _ :+ last => Some((head, last))
| case List(head) => Some((head, head))
| case _ => None
| }
res0: Option[(String, String)] = Some((ham,eggs))
Lets understand the concept related to this question, there is a difference between '::', '+:' and ':+':
1st Operator:
'::' - It is right associative operator which works specially for lists
scala> val a :: b :: c = List(1,2,3,4)
a: Int = 1
b: Int = 2
c: List[Int] = List(3, 4)
2nd Operator:
'+:' - It is also right associative operator but it works on seq which is more general than just list.
scala> val a +: b +: c = List(1,2,3,4)
a: Int = 1
b: Int = 2
c: List[Int] = List(3, 4)
3rd Operator:
':+' - It is also left associative operator but it works on seq which is more general than just list
scala> val a :+ b :+ c = List(1,2,3,4)
a: List[Int] = List(1, 2)
b: Int = 3
c: Int = 4
The associativity of an operator is determined by the operator’s last character. Operators ending in a colon ‘:’ are right-associative. All other operators are left-associative.
A left-associative binary operation e1;op;e2 is interpreted as e1.op(e2)
If op is right-associative, the same operation is interpreted as { val x=e1; e2.op(x) }, where x is a fresh name.
Now comes answer for your question:
So now if you need to get first and last element from the list, please use following code
scala> val firstElement +: b :+ lastElement = List(1,2,3,4)
firstElement: Int = 1
b: List[Int] = List(2, 3)
lastElement: Int = 4