How to capture inner matched value in indexWhere vector expression? - scala

Using a Vector[Vector[Int]] reference v, and the expression to find a given number num:
val posX = v.indexWhere(_.indexOf(num) > -1)
Is there any way to capture the value of _.indexOf(num) to use after the expression (i.e. the posY value)? The following signals an error 'Illegal start of simple expression':
val posX = v.indexWhere((val posY = _.indexOf(num)) > -1)

If we do not mind using a variable then we can capture indexOf() value of inner Vector (_ in the below code) in a var and use it later to build the y position:
val posX = v.indexWhere(_.indexOf(num) > -1)
val posY = v(posX).indexOf(num)

There are lots of nice functional ways to do this. The following is probably one of the more concise:
val v = Vector(Vector(1, 2, 3), Vector(4, 5, 6), Vector(7, 8, 9))
val num = 4
val Some((posY, posX)) = v.map(_ indexOf num).zipWithIndex.find(_._1 > -1)
// posY: Int = 0
// posX: Int = 1
Note that there's a lot of extra work going on here, though—we're creating a couple of intermediate collections, parts of which we don't need, etc. If you're calling this thing a lot or on very large collections, you unfortunately may need to take a more imperative approach. In that case I'd suggest bundling up all the unpleasantness:
def locationOf(v: Vector[Vector[Int]])(num: Int): Option[(Int, Int)] = {
var i, j = 0
var found = false
while (i < v.size && !found) {
j = 0
while (j < v(i).size && !found)
if (v(i)(j) == num) found = true else j += 1
if (!found) i += 1
}
if (!found) None else Some(i, j)
}
Not as elegant, but this method is probably going to be a lot faster and more memory efficient. It's small enough that it isn't likely to contain any of the bugs that this kind of programming is so prone to, and it's referentially transparent—all the mutation is local.

From my armchair,
scala> val v = Vector(Vector(1, 2, 3), Vector(4, 5, 6), Vector(7, 8, 9))
scala> v.zipWithIndex collectFirst {
| case (e, i) if (e indexOf num) >= 0 =>
| (i, e indexOf num)
| }
res7: Option[(Int, Int)] = Some((1,0))
I haven't done the armchair math, but that's one intermediate collection compared to Travis's. But see Travis's comment that the result inner index is computed twice here, and the whole point was not to do that.

Here is a solution that will only evaluate up until it finds the required element. I personally find it more readable and you can reuse it across programs. You can obviously make this more general if need be.
val v = Vector(Vector(1, 2, 3), Vector(4, 5, 6))
def findElem(i: Int, vs: Vector[Vector[Int]]): (Int, Int) =
(for {
row <- vs.indices.toStream
col <- vs(row).indices.toStream
if vs(row)(col) == i
} yield (row, col)).head
findElem(5, v) // (1, 1)
You could remove the .toStream methods if you want all positions. Using the .toStream just means that you will only evaluate up until the first occurrence.

Related

How to create an Iterable of semi-homogenous Integers that sum to a max in Scala?

In scala; given a maximum sum value and a maximum element value, how can an Iterable of elements be created such that the elements add up to the maximum sum? The Iterable should have the smallest size possible.
As an example, given
val maxSum = 47
val maxElementValue = 10
How can the following Iterable be created:
Iterable(10, 10, 10, 10, 7) //sum to 47
Other examples:
val maxSum = 9
val maxElementValue = 10
Iterable(9)
val maxSum = 11
val maxElementValue = 5
Iterable(5, 5, 1)
Thank you in advance for your consideration and response.
If you are in 2.13 you can use unfold
def elementGenerator(maxSum: Int, maxElementValue: Int): List[Int] =
Iterator.unfold(maxSum) { remainingSum =>
if (remainingSum == 0)
None
else if (remainingSum <= maxElementValue)
Some(remainingSum -> 0)
else
Some(maxElementValue -> (remainingSum - maxElementValue))
}.toList
You may also consider just returning the Iterator or using a LazyList if you do not need to keep all the elements right now but just know how to generate them.
How about
((maxSum % maxElementValue) :: List.fill(maxSum / maxElementValue)(maxElementValue)).filterNot(_ == 0)
You can use .unfold for this:
// Use `Iterator.unfold` if you want an Iterator instead of a List
List.unfold(maxSum) { remaining =>
if (remaining <= 0) None
else {
val nextElement = math.min(maxElementValue, remaining)
Some(nextElement -> (remaining - nextElement))
}
}
returns
List(10, 10, 10, 10, 7)
See it on scastie.
A recursive function can do the trick
#scala.annotation.tailrec
def elementGenerator(maxSum: Int, maxElementValue: Int, currentElements: Seq[Int] = Seq.empty[Int]) : Seq[Int] =
if(maxSum == 0 || maxValue <= 0)
currentElements
else if(maxSum < maxElementValue)
currentElements :+ maxSum
else
elementGenerator(maxSum - maxElementValue, maxElementValue, currentElements :+ maxElementValue)
Presented mostly as a "well, it works but you really don't want to do it this way" alternative :)
Iterator.fill(maxSum)(1).grouped(maxElementValue).map(_.sum)

Move zeros to the end of an Array

Im trying to solve below problem in scala
Input:[1,0,44,55,0,43,78,99]
output:[1,44,55,43,78,99,0,0]
here is what i have tried
def moveZeros(nums:Array[Int]): Array[Int] ={
for(i<-0 until nums.length ; j<-0 until nums.length){
if(nums(j)!=0)
{
var temp:Int = nums(i)
nums(i)=nums(j)
nums(j)=temp
}
}
nums
}
output :[0,0,1,44,55,78,99,43]
not expected output
Im looking for o(n) time complexity and O(1) space complexity solution
This is a leetcode problem
https://leetcode.com/problems/move-zeroes/
You can try something like that:
nums.zipWithIndex
.sortBy(t => if (t._1 == 0) Int.MaxValue else t._2)
.map(_._1)
zipWithIndex will map your collection into sequence of tuples of element value and it's index (i.e. [(1, 0), (0, 21), (44, 2)] for start of your example array)
sortBy will perform the ordering by either index of element or Int.MaxValue
map will return map to the original element.
i have rewritten my code with while loop it seems to work, lemme know if there is more elegant solution which satisfies linear time complexity and constant space complexity
def moveZeros(nums: Array[Int]): Array[Int] = {
var i = 0
var j = 0
while ( {
i < nums.length && j < nums.length
}) {
if (nums(j) != 0) {
val tmp = nums(i)
nums(i)=nums(j)
nums(j) = tmp
i+=1
}
j += 1
}
nums
}
This is a pure FP solution with O(n) time complexity and O(1) space complexity.
Unlike any of the other solutions so far, it can work for very large input that doesn't fit in memory:
object MoveZeros extends App {
def moveZerosToEnd(input: Iterator[Int]): Iterator[Int] = {
val endOfInputSignal = None
val iteratorWithEndSignal: Iterator[Option[Int]] =
input.map(Some(_)) ++ Iterator.single(endOfInputSignal)
iteratorWithEndSignal.scanLeft((0, Iterator.empty[Int])) {
case ((zerosCounter, _), value) => value match {
case Some(value) =>
if (value == 0)
// Count zero and drop it
(zerosCounter + 1, Iterator.empty)
else
(zerosCounter, Iterator.single(value))
case None =>
// Add counted zeros to the end
(zerosCounter, Iterator.fill(zerosCounter)(0))
}
}.flatMap(_._2)
}
val input = List(1,0,44,55,0,43,78,99)
val expected = List(1,44,55,43,78,99,0,0)
val res = moveZerosToEnd(input.iterator)
.toList // To list only for easy testing
assert(res == expected)
println(res)
}
Functional and immutable solution, also very simple to understand:
def moveZerosToEnd(input: Seq[Int]): Seq[Int] = {
val ZERO = 0
val zeroCount = input.count(_==ZERO)
val removeZeros = input.filter(_!=ZERO)
val zeroSuffix = Seq.fill(zeroCount)(ZERO)
removeZeros ++ zeroSuffix
}
Time complexity: O(n): Fixed number of iterations over the sequence.
Space complexity: O(n): removeZeros, zeroSuffix and the output line may consume up to n space, so complexity is O(n).
You can find all the immutable, functional, "true Scala" way of doing it in the above answers. But, considering the O(N) time-complexity and O(1) space complexity nothing beats a mutable, efficient, in-place algorithm!
Here is the implementation with Scala's array using foldLeft:
val arr = Array(1, 0, 44, 55, 0, 43, 78, 99)
val lastNonZero = arr.foldLeft(0) {
(zeros, elem) => if (elem != 0) { arr(zeros) = elem; zeros+1 } else zeros
}
(lastNonZero until arr.length).foreach{ i => arr(i) = 0 }
No extra space due to collection creation (not even .toList/.toArray) and no sorting.

List whose elements depend on the previous ones

Suppose I have a list of increasing integers. If the difference of 2 consecutive numbers is less than a threshold, then we index them by the same number, starting from 0. Otherwise, we increase the index by 1.
For example: for the list (1,2,5,7,8,11,15,16,20) and the threshold = 3, the output will be: (0, 0, 1, 1, 1, 2, 3, 3, 4).
Here is my code:
val listToGroup = List(1,2,5,7,8,11,15,16,20)
val diff_list = listToGroup.sliding(2,1).map{case List(i, j) => j-i}.toList
val thres = 2
var j=0
val output_ = for(i <- diff_list.indices) yield {
if (diff_list(i) > thres ) {
j += 1
}
j
}
val output = List.concat(List(0), output_)
I'm new to Scala and I feel the list is not used efficiently. How can this code be improved?
You can avoid the mutable variable by using scanLeft to get a more idiomatic code:
val output = diff_list.scanLeft(0) { (count, i) =>
if (i > thres) count + 1
else count
}
Your code shows some constructs which are usually avoided in Scala, but common when coming from procedural langugues, like: for(i <- diff_list.indices) ... diff_list(i) can be replaced with for(i <- diff_list).
Other than that, I think your code is efficient - you need to traverse the list anyway and you do it in O(N). I would not worry about efficiency here, more about style and readability.
My rewrite to how I think it would be more natural in Scala for the whole code would be:
val listToGroup = List(1,2,5,7,8,11,15,16,20)
val thres = 2
val output = listToGroup.zip(listToGroup.drop(1)).scanLeft(0) { case (count, (i, j)) =>
if (j - i > thres) count + 1
else count
}
My adjustments to your code:
I use scanLeft to perform the result collection construction
I prefer x.zip(x.drop(1)) over x.sliding(2, 1) (constructing tuples seems a bit more efficient than constructing collections). You could also use x.zip(x.tail), but that does not handle empty x
I avoid the temporary result diff_list
val listToGroup = List(1, 2, 5, 7, 8, 11, 15, 16, 20)
val thres = 2
listToGroup
.sliding(2)
.scanLeft(0)((a, b) => { if (b.tail.head - b.head > thres) a + 1 else a })
.toList
.tail
You don't need to use mutable variable, you can achieve the same with scanLeft.

Scala: Problem with foldLeft with negative numbers in list

I am writing a Scala function that returns the sum of even elements in a list, minus sum of odd elements in a list. I cannot use mutables, recursion or for/while loops for my solution. The code below passes 2/3 tests, but I can't seem to figure out why it can't compute the last test correctly.
def sumOfEvenMinusOdd(l: List[Int]) : Int = {
if (l.length == 0) return 0
val evens = l.filter(_%2==0)
val odds = l.filter(_%2==1)
val evenSum = evens.foldLeft(0)(_+_)
val oddSum = odds.foldLeft(0)(_+_)
evenSum-oddSum
}
//BEGIN TESTS
val i1 = sumOfEvenMinusOdd(List(1,3,5,4,5,2,1,0)) //answer: -9
val i2 = sumOfEvenMinusOdd(List(2,4,5,6,7,8,10)) //answer: 18
val i3 = sumOfEvenMinusOdd(List(109, 19, 12, 1, -5, -120, -15, 30,-33,-13, 12, 19, 3, 18, 1, -1)) //answer -133
My code is outputting this:
defined function sumOfEvenMinusOdd
i1: Int = -9
i2: Int = 18
i3: Int = -200
I am extremely confused why these negative numbers are tripping up the rest of my code. I saw a post explaining the order of operations with foldLeft foldRight, but even changing to foldRight still yields i3: Int = -200. Is there a detail I'm missing? Any guidance / help would be greatly appreciated.
The problem isn't foldLeft or foldRight, the problem is the way you filter out odd values:
val odds = l.filter(_ % 2 == 1)
Should be:
val odds = l.filter(_ % 2 != 0)
The predicate _ % 2 == 1 will only yield true for positive elements. For example, the expression -15 % 2 is equal to -1, and not 1.
As as side note, we can also make this a bit more efficient:
def sumOfEvenMinusOdd(l: List[Int]): Int = {
val (evenSum, oddSum) = l.foldLeft((0, 0)) {
case ((even, odd), element) =>
if (element % 2 == 0) (even + element, odd) else (even, odd + element)
}
evenSum - oddSum
}
Or even better by accumulating the difference only:
def sumOfEvenMinusOdd(l: List[Int]): Int = {
l.foldLeft(0) {
case (diff, element) =>
diff + element * (if (element % 2 == 0) 1 else -1)
}
}
The problem is on the filter condition that you apply on list to find odd numbers.
the odd condition that you doesn't work for negative odd number because mod 2 return -1 for this kind of number.
number % 2 == 0 if number is even
number % 2 != 0 if number is odd
so if you change the filter conditions all works as expected.
Another suggestion:
Why you want use foldleft function for a simple sum operation when you can use directly the sum functions?
test("Test sum Of even minus odd") {
def sumOfEvenMinusOdd(l: List[Int]) : Int = {
val evensSum = l.filter(_%2 == 0).sum
val oddsSum = l.filter(_%2 != 0).sum
evensSum-oddsSum
}
assert(sumOfEvenMinusOdd(List.empty[Int]) == 0)
assert(sumOfEvenMinusOdd(List(1,3,5,4,5,2,1,0)) == -9) //answer: -9
assert(sumOfEvenMinusOdd(List(2,4,5,6,7,8,10)) == 18) //answer: 18
assert(sumOfEvenMinusOdd(List(109, 19, 12, 1, -5, -120, -15, 30,-33,-13, 12, 19, 3, 18, 1, -1)) == -133)
}
With this solution your function is more clear and you can remove the if on the funciton

Code efficiency in Scala loops, counting up or counting down?

Clearly, if you need to count up, count up. If you need to count down, count down. However, other things being equal, is one faster than the other?
Here is my Scala code for a well-known puzzle - checking if a number is divisible by 13.
In the first example, I reverse my array and count upwards in the subsequent for-loop. In the second example I leave the array alone and do a decrementing for-loop. On the surface, the second example looks faster. Unfortunately, on the site where I run the code, it always times out.
// works every time
object Thirteen {
import scala.annotation.tailrec
#tailrec
def thirt(n: Long): Long = {
val getNum = (n: Int) => Array(1, 10, 9, 12, 3, 4)(n % 6)
val ni = n.toString.split("").reverse.map(_.toInt)
var s: Long = 0
for (i <- 0 to ni.length-1) {
s += ni(i) * getNum(i)
}
if (s == n) s else thirt(s)
}
}
// times out every time
object Thirteen {
import scala.annotation.tailrec
#tailrec
def thirt(n: Long): Long = {
val getNum = (n: Int) => Array(1, 10, 9, 12, 3, 4)(n % 6)
val ni = n.toString.split("").map(_.toInt)
var s: Long = 0
for (i <- ni.length-1 to 0 by -1) {
s = s + ni(i) * getNum(i)
}
if (s == n) s else thirt(s)
}
}
I ask the following questions:
Is there an obvious rule I am unaware of?
What is an easy way to test two code versions for performance – reliably measuring performance in the JVM appears difficult.
Does it help to look at the underlying byte code?
Is there a better piece of code solving
the same problem, If so, I'd be very grateful to see it.
Whilst I've seen similar questions, I can't find a definitive answer.
Here's how I'd be tempted to tackle it.
val nums :Stream[Int] = 1 #:: 10 #:: 9 #:: 12 #:: 3 #:: 4 #:: nums
def thirt(n :Long) :Long = {
val s :Long = Stream.iterate(n)(_ / 10)
.takeWhile(_ > 0)
.zip(nums)
.foldLeft(0L){case (sum, (i, num)) => sum + i%10 * num}
if (s == n) s else thirt(s)
}