Exit for loop as soon as condition satisfied - scala

The following code hangs the repl:
(
for {
i <- 1 to 1000000
j <- 2 to 1000000
if i * i == j
} yield i -> j
).take(1)
It seems the for expression is eagerly evaluated. Any solutions?

I'd turn that into a stream:
(
for {
i <- Stream.range(1, 1000000)
j <- Stream.range(2, 1000000)
if i * i == j
} yield i -> j
).take(1)

Related

Best purely functional alternative to a while loop

Is the a better functional idiom alternative to the code below? ie Is there a neater way to get the value j without having to use a var?
var j = i + 1
while (j < idxs.length && idxs(j) == x) j += 1
val j = idxs.drop(i).indexWhere(_ != x) + i
Or, as suggested by #kosii in the comments, use the indexWhere overload that takes an index from where to start searching:
val j = idxs.indexWhere(_ != x, i)
Edit
Since j must equal the length of idxs in case all items following i are equal to x:
val index = idxs.indexWhere(_ != x, i)
val j = if(index < 0) idxs.length else index
// or
val j = if (idxs.drop(i).forall(_ == x)) idxs.length
else idxs.indexWhere(_ != x, i)
Maybe with streams, something like:
((i + 1) to idxs.length).toStream.takeWhile(j => idxs(j) == x).last

How to get unique elements from two lists of strings in scala?

I have two list to compare:
List one:
List("one","two","three","four")
List two:
List("one","two")
how can I get the unique values from these two lists?
If your two lists are r1 and r2, and assuming you want the values in each list that are not present in the other:
r1.filterNot(r2.contains) ::: r2.filterNot(r1.contains)
or
r1.diff(r2) ::: r2.diff(r1)
Turn them into sets, and get the intersection. You may then turn it back to Seq if you want, but first ask yourself if they had to be Seq in first place, instead of Set.
scala> List("one","two","three","four").toSet & List("one","two").toSet
res0: scala.collection.immutable.Set[String] = Set(one, two)
Use The difference operator for Set &~
http://www.scala-lang.org/api/current/scala/collection/immutable/Set.html
I use List(1, 2, 3, 4) ::: List(1, 2, 5) distinct for this issue. It returns List(1, 2, 3, 4, 5).
I would suggest using the following for O(m+n) running time (assumes input arrays are sorted).
def mergeUniqueSortedArrays( A: Array[String], B: Array[String] ): Array[String]= {
val n = A.length
val m = B.length
var C = Array[String]()
var i = 0
var j = 0
while (i < n && j < m) {
if (i == n) {
if ( B(j) != A(i-1) ) {
C :+= B(j)
}
j+=1
}
else if (j == m) {
if ( A(i) != B(j-1) ) {
C :+= A(j)
}
i+=1
}
else {
if ( A(i) < B(j) ) {
if (C.length == 0 || A(i) != C(C.length-1)) {
C :+= A(i)
}
i+=1
}
else if ( B(j) < A(i) ) {
if (C.length == 0 || B(j) != C(C.length-1)) {
C :+= B(j)
}
j+=1
}
else {
if (C.length == 0 || A(i) != C(C.length-1)) {
C :+= A(i)
}
i+=1
j+=1
}
}
}
return C
}
--
NOTE: If the input arrays are not sorted, then you can easily sort the input arrays and it will run in in O( max{(n + m), (n log n)}) time, assuming n>m.
NOTE: O(n + m) time technically assumes that string length is bounded by constant k, but you aren't going to get around that anyway.

Swapping array values with for and yield scala

I am trying to swap every pair of values in my array using for and yield and so far I am very unsuccessful. What I have tried is as follows:
val a = Array(1,2,3,4,5) //What I want is Array(2,1,4,3,5)
for(i<-0 until (a.length-1,2),r<- Array(i+1,i)) yield r
The above given snippet returns the vector 2,1,4,3(and the 5 is omitted)
Can somebody point out what I am doing wrong here and how to get the correct reversal using for and yields?
Thanks
a.grouped(2).flatMap(_.reverse).toArray
or if you need for/yield (much less concise in this case, and in fact expands to the same code):
(for {b <- a.grouped(2); c <- b.reverse} yield c).toArray
It would be easier if you didin't use for/yield:
a.grouped(2)
.flatMap{
case Array(x,y) => Array(y,x)
case Array(x) => Array(x)
}.toArray // Array(2, 1, 4, 3, 5)
I don't know if the OP is reading Scala for the Impatient, but this was exercise 3.3 .
I like the map solution, but we're not on that chapter yet, so this is my ugly implementation using the required for/yield. You can probably move some yield logic into a guard/definition.
for( i <- 0 until(a.length,2); j <- (i+1).to(i,-1) if(j<a.length) ) yield a(j)
I'm a Java guy, so I've no confirmation of this assertion, but I'm curious what the overhead of the maps/grouping and iterators are. I suspect it all compiles down to the same Java byte code.
Another simple, for-yield solution:
def swapAdjacent(array: ArrayBuffer[Int]) = {
for (i <- 0 until array.length) yield (
if (i % 2 == 0)
if (i == array.length - 1) array(i) else array(i + 1)
else array(i - 1)
)
}
Here is my solution
def swapAdjacent(a: Array[Int]):Array[Int] =
(for(i <- 0 until a.length) yield
if (i%2==0 && (i+1)==a.length) a(i) //last element for odd length
else if (i%2==0) a(i+1)
else a(i-1)
).toArray
https://github.com/BasileDuPlessis/scala-for-the-impatient/blob/master/src/main/scala/com/basile/scala/ch03/Ex03.scala
If you are doing exercises 3.2 and 3.3 in Scala for the Impatient here are both my answers. They are the same with the logic moved around.
/** Excercise 3.2 */
for (i <- 0 until a.length if i % 2 == 1) {val t = a(i); a(i) = a(i-1); a(i-1) = t }
/** Excercise 3.3 */
for (i <- 0 until a.length) yield { if (i % 2 == 1) a(i-1) else if (i+1 <= a.length-1) a(i+1) else a(i) }
for (i <- 0 until arr.length-1 by 2) { val tmp = arr(i); arr(i) = arr(i+1); arr(i+1) = tmp }
I have started to learn Scala recently and all solutions from the book Scala for the Impatient (1st edition) are available at my github:
Chapter 2
https://gist.github.com/carloscaldas/51c01ccad9d86da8d96f1f40f7fecba7
Chapter 3
https://gist.github.com/carloscaldas/3361321306faf82e76c967559b5cea33
I have my solution, but without yield. Maybe someone will found it usefull.
def swap(x: Array[Int]): Array[Int] = {
for (i <- 0 until x.length-1 by 2){
var left = x(i)
x(i) = x(i+1)
x(i+1) = left
}
x
}
Assuming array is not empty, here you go:
val swapResult = for (ind <- arr1.indices) yield {
if (ind % 2 != 0) arr1(ind - 1)
else if (arr1(ind) == arr1.last) arr1(ind)
else if (ind % 2 == 0) arr1(ind + 1)
}

Scala - Most elegant way of initialising values inside array that's already been declared?

I have a 3d array defined like so:
val 3dArray = new Array[Array[Array[Int]]](512, 8, 8)
In Javascript I would do the following to assign each element to 1:
for (i = 0; i < 512; i++)
{
3dArray[i] = [];
for (j = 0; j < 8; j++)
{
3dArray[i][j] = [];
for (k = 0; k < 8; k++)
{
3dArray[i][j][k] = 1;
}
}
}
What's the most elegant approach to doing the same?
Not sure there's a particularly elegant way to do it, but here's one way (I use suffix s to indicate dimension, i.e. xss is a two-dimensional array).
val xsss = Array.ofDim[Int](512, 8, 8)
for (xss <- xsss; xs <- xss; i <- 0 until 8)
xs(i) = 1
Or, using transform it gets even shorter:
for (xss <- xsss; xs <- xss)
xs transform (_ => 1)
for {
i <- a.indices
j <- a(i).indices
k <- a(i)(j).indices
} a(i)(j)(k) = 1
or
for {
e <- a
ee <- e
i <- ee.indices
} ee(i) = 1
See: http://www.scala-lang.org/api/current/index.html#scala.Array$
You have Array.fill to initialize an array of 1 to 5 dimension to some given value, and Array.tabulate to initialize an array of 1 to 5 dimension given the current indexes:
scala> Array.fill(2,1,1)(42)
res1: Array[Array[Array[Int]]] = Array(Array(Array(42)), Array(Array(42)))
enter code here
scala> Array.tabulate(3,2,1){ (x,y,z) => x+y+z }
res2: Array[Array[Array[Int]]] = Array(Array(Array(0), Array(1)), Array(Array(1), Array(2)), Array(Array(2), Array(3)))

Nested iteration in Scala

What is the difference (if any) between two code fragments below?
Example from Ch7 of Programming i Scala
def grep(pattern: String) =
for (
file <- filesHere
if file.getName.endsWith(".scala");
line <- fileLines(file)
if line.trim.matches(pattern)
) println(file + ": " + line.trim)
and this one
def grep2(pattern: String) =
for (
file <- filesHere
if file.getName.endsWith(".scala")
) for (
line <- fileLines(file)
if line.trim.matches(pattern)
) println(file + ": " + line.trim)
Or
for (i <- 1 to 2)
for (j <- 1 to 2)
println(i, j)
and
for (
i <- 1 to 2;
j <- 1 to 2
) println(i, j)
In this case there is no difference. However when using yield there is:
for (
i <- 1 to 2;
j <- 1 to 2
) yield (i, j)
Will give you a sequence containing (1,1), (1,2), (2,1) and (2,2).
for (i <- 1 to 2)
for (j <- 1 to 2)
yield (i, j)
Will give you nothing, because it generates the sequence (i,1), (i,2) on each iteration and then throws it away.
Sometimes it is also useful to output a multi dimensional collection (for example a matrix of table):
for (i <- 1 to 2) yield for (j <- 1 to 2) yield (i, j)
Will return:
Vector(Vector((1,1), (1,2)), Vector((2,1), (2,2)))