Scala stream behaves counterintuitive - scala

I am playing with Scala's streams and I'm not sure I catch the idea.
Let's consider following code
def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head, fun(s.tail))
executing this
val f = fun(Stream.from(7))
f take 14 foreach println
results with
7 8 9 10 ... up to 20
Let's say I understand this.
Now, changing slightly code (adding 2 to head)
def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head + 2, fun(s.tail))
results in
9 10 11 ... up to 22
Again I think I understand. Problems starts with next example (d
def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head / 2, fun(s.tail))
3 4 4 5 5 6 6 7 7 8 8 9 9 10
This I do not get, please explain why it results this way?
Similar, subtracting also does not behave as I expect
def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head - 2, fun(s.tail))
Output
5 6 7 8 9 10 ... up to 18

Given your "take": 7 8 9 10 ... up to 20,
what happens when you + 2 on each element?
what happens when you / 2 on each element (int arithmetic)?
what happens when you - 2 on each element?

Is it more intuitive if you think of it as mapping the Stream?
scala> val s1 = Stream.from(10)
s1: scala.collection.immutable.Stream[Int] = Stream(10, ?)
scala> val s2 = s1 map (_ * 2)
s2: scala.collection.immutable.Stream[Int] = Stream(20, ?)
scala> s2.take(5).toList
res0: List[Int] = List(20, 22, 24, 26, 28)
scala> val s3 = s1 map (_ / 2)
s3: scala.collection.immutable.Stream[Int] = Stream(5, ?)
scala> s3.take(5).toList
res1: List[Int] = List(5, 5, 6, 6, 7)
scala> val s4 = s1 map (_ - 2)
s4: scala.collection.immutable.Stream[Int] = Stream(8, ?)
scala> s4.take(5).toList
res2: List[Int] = List(8, 9, 10, 11, 12)

Ok, let's try and break it down...
def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head, fun(s.tail))
is a function that takes a Stream and separates its head and tail, applies itself recursively on the tail, and then recombines the two results with the cons operator.
Since the head is not touched during this operation, the Stream is rebuilt element by element as it was before.
val f = fun(Stream.from(7))
f it's the same as Stream.from(7) [i.e. an infinite sequence of increasing integers starting from 7]
Printing f take 14 in fact shows that we have the first 14 numbers starting from 7 [i.e. 7,8,9,...,20]
What happens next is that, while rebuilding the stream with the cons, each element is modified in some way
def fun(s: Stream[Int]): Stream[Int] = Stream.cons(s.head + 2, fun(s.tail))
This adds 2 to the head before recombining it with the modified tail. The latter is modified in the same way, its first element being added to 2 and then recombined to its own tail, and so own.
If we assume again that s contains the number from 7 on, what happens looks like
fun(s) = cons(7 + 2, cons(8 + 2, cons(9 + 2, ... ad infinitum ... )))))
This is the same as adding 2 to each and every element of the stream s.
The code confirms that by printing "9 to 22", which is exactly "7 to 20" with 2 added to every element.
The others examples are analogous:
the stream with each element divided by 2 (and rounded to the floor
integer value, since the Stream is typed with Int values)
the stream where each element is decremented by 2

Related

How to compare two integer array in Scala?

Find a number available in first array with numbers in second. If number not found get the immediate lower.
val a = List(1,2,3,4,5,6,7,8,9)
val b = List(1,5,10)
expected output after comparing a with b
1 --> 1
2 --> 1
3 --> 1
4 --> 1
5 --> 5
6 --> 5
7 --> 5
8 --> 5
9 --> 5
Thanks
You can use TreeSet's to() and lastOption methods as follows:
val a = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
val b = List(1, 5, 10)
import scala.collection.immutable.TreeSet
// Convert list `b` to TreeSet
val bs = TreeSet(b.toSeq: _*)
a.map( x => (x, bs.to(x).lastOption.getOrElse(Int.MinValue)) ).toMap
// res1: scala.collection.immutable.Map[Int,Int] = Map(
// 5 -> 5, 1 -> 1, 6 -> 5, 9 -> 5, 2 -> 1, 7 -> 5, 3 -> 1, 8 -> 5, 4 -> 1
// )
Note that neither list a or b needs to be ordered.
UPDATE:
Starting Scala 2.13, methods to for TreeSet is replaced with rangeTo.
Here is another approach using collect function
val a = List(1,2,3,4,5,6,7,8,9)
val b = List(1,5,10)
val result = a.collect{
case e if(b.filter(_<=e).size>0) => e -> b.filter(_<=e).reverse.head
}
//result: List[(Int, Int)] = List((1,1), (2,1), (3,1), (4,1), (5,5), (6,5), (7,5), (8,5), (9,5))
Here for every element in a check if there is a number in b i.e. which is greater than or equal to it and reverse the filter list and get its head to make it a pair.

How to make immutable 2D Array in Scala

I have the following class:
class Matrix(val matrix: Array[Array[Int]]) {
// some other methods
override def toString: String = {
return matrix.map(_.mkString(" ")).mkString("\n")
}
}
I have declared class variable as val to prevent further modification in matrix.
object Main {
def main(args: Array[String]) {
val > = Array
val x: Array[Array[Int]] = >(
>(1, 2, 3),
>(4, 5, 6),
>(7, 8, 9))
val m1 = new Matrix(x)
println("m1 -->\n" + m1)
x(1)(1) = 101 // Need to prevent this type of modification.
println("m1 -->\n" + m1)
}
}
After doing x(1)(1) = 101 the output of the program is
m1 -->
1 2 3
4 101 6
7 8 9
But I want to prevent this modification and get the original matrix as
m1 -->
1 2 3
4 5 6
7 8 9
Instead of using Array, maybe you could use List instead, and it is immutable :
scala> val num:List[Int] = List(1,2,3)
num: List[Int] = List(1, 2, 3)
scala> num(1) = 3
<console>:13: error: value update is not a member of List[Int]
num(1) = 3
^
There's a difference between a mutable/immutable variable (e.g. var x and val x) and a mutable/immutable collection. Declaring one (the variable) doesn't effect the other (the collection).
The Scala Array is inherited from Java and, as such, is mutable. There are many fine immutable collections. Array isn't one of them.

Is there a Round Robin/Circular Queue available in Scala Collections

Is there a Round Robin Queue available in Scala Collections?
I need to repeatedly iterate a list that circles through itself
val x = new CircularList(1,2,3,4)
x.next (returns 1)
x.next (returns 2)
x.next (returns 3)
x.next (returns 4)
x.next (returns 1)
x.next (returns 2)
x.next (returns 3)
... and so on
It's pretty easy to roll your own with continually and flatten:
scala> val circular = Iterator.continually(List(1, 2, 3, 4)).flatten
circular: Iterator[Int] = non-empty iterator
scala> circular.take(17).mkString(" ")
res0: String = 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
There's also a continually method on Stream—just be careful not to hold onto a reference to the head of the stream if you're going to be generating lots of elements.
You can very easily create a circular list using a Stream.
scala> val l = List(1, 2, 3, 4).toStream
l: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> def b: Stream[Int] = l #::: b
b: Stream[Int]
scala> b.take(20).toList
res2: List[Int] = List(1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4)
Edit: you want to make sure to define the repeated part beforehand, once and only once, to avoid blowing the heap (structural sharing in Stream). As in:
def circular[A](a: Seq[A]): Stream[A] = {
val repeat = a.toStream
def b: Stream[A] = repeat #::: b
b
}
Version more concentrated on getting new element on every execution.
val getNext: () => Int = {
def b: Stream[Int] = List(1, 2, 3, 4).toStream #::: b
var cyclicIterator: Stream[Int] = b
() => {
val tail = cyclicIterator.tail
val result = tail.head
cyclicIterator = tail
result
}
} // could be written more sexy?
In your problem you can use it like:
for(i <- 1 to 10) yield getNext()
This is ugly in having an external mutable index, but it does do what's requested:
scala> var i = 0
scala> val ic4 = Iterator.continually { val next = IndexedSeq(1, 2, 3, 4)(i % 4); i += 1; next }
i: Int = 0
ic4: Iterator[Int] = non-empty iterator
scala> ic4 take 10 foreach { i => printf("ic4.next=%d%n", i) }
ic4.next=1
ic4.next=2
ic4.next=3
ic4.next=4
ic4.next=1
ic4.next=2
ic4.next=3
ic4.next=4
ic4.next=1
ic4.next=2
At least it illustrates Iterator.continually. There is also Stream.continually, which has the same signature.

How can I find repeated items in a Scala List?

I have a Scala List that contains some repeated numbers. I want to count the number of times a specific number will repeat itself. For example:
val list = List(1,2,3,3,4,2,8,4,3,3,5)
val repeats = list.takeWhile(_ == List(3,3)).size
And the val repeats would equal 2.
Obviously the above is pseudo-code and takeWhile will not find two repeated 3s since _ represents an integer. I tried mixing both takeWhile and take(2) but with little success. I also referred code from How to find count of repeatable elements in scala list but it appears the author is looking to achieve something different.
Thanks for your help.
This will work in this case:
val repeats = list.sliding(2).count(_.forall(_ == 3))
The sliding(2) method gives you an iterator of lists of elements and successors and then we just count where these two are equal to 3.
Question is if it creates the correct result to List(3, 3, 3)? Do you want that to be 2 or just 1 repeat.
val repeats = list.sliding(2).toList.count(_==List(3,3))
and more generally the following code returns tuples of element and repeats value for all elements:
scala> list.distinct.map(x=>(x,list.sliding(2).toList.count(_.forall(_==x))))
res27: List[(Int, Int)] = List((1,0), (2,0), (3,2), (4,0), (8,0), (5,0))
which means that the element '3' repeats 2 times consecutively at 2 places and all others 0 times.
and also if we want element repeats 3 times consecutively we just need to modify the code as follows:
list.distinct.map(x=>(x,list.sliding(3).toList.count(_.forall(_==x))))
in SCALA REPL:
scala> val list = List(1,2,3,3,3,4,2,8,4,3,3,3,5)
list: List[Int] = List(1, 2, 3, 3, 3, 4, 2, 8, 4, 3, 3, 3, 5)
scala> list.distinct.map(x=>(x,list.sliding(3).toList.count(_==List(x,x,x))))
res29: List[(Int, Int)] = List((1,0), (2,0), (3,2), (4,0), (8,0), (5,0))
Even sliding value can be varied by defining a function as:
def repeatsByTimes(list:List[Int],n:Int) =
list.distinct.map(x=>(x,list.sliding(n).toList.count(_.forall(_==x))))
Now in REPL:
scala> val list = List(1,2,3,3,4,2,8,4,3,3,5)
list: List[Int] = List(1, 2, 3, 3, 4, 2, 8, 4, 3, 3, 5)
scala> repeatsByTimes(list,2)
res33: List[(Int, Int)] = List((1,0), (2,0), (3,2), (4,0), (8,0), (5,0))
scala> val list = List(1,2,3,3,3,4,2,8,4,3,3,3,2,4,3,3,3,5)
list: List[Int] = List(1, 2, 3, 3, 3, 4, 2, 8, 4, 3, 3, 3, 2, 4, 3, 3, 3, 5)
scala> repeatsByTimes(list,3)
res34: List[(Int, Int)] = List((1,0), (2,0), (3,3), (4,0), (8,0), (5,0))
scala>
We can go still further like given a list of integers and given a maximum number
of consecutive repetitions that any of the element can occur in the list, we may need a list of 3-tuples representing (the element, number of repetitions of this element, at how many places this repetition occurred). this is more exhaustive information than the above. Can be achieved by writing a function like this:
def repeats(list:List[Int],maxRep:Int) =
{ var v:List[(Int,Int,Int)] = List();
for(i<- 1 to maxRep)
v = v ++ list.distinct.map(x=>
(x,i,list.sliding(i).toList.count(_.forall(_==x))))
v.sortBy(_._1) }
in SCALA REPL:
scala> val list = List(1,2,3,3,3,4,2,8,4,3,3,3,2,4,3,3,3,5)
list: List[Int] = List(1, 2, 3, 3, 3, 4, 2, 8, 4, 3, 3, 3, 2, 4, 3, 3, 3, 5)
scala> repeats(list,3)
res38: List[(Int, Int, Int)] = List((1,1,1), (1,2,0), (1,3,0), (2,1,3),
(2,2,0), (2,3,0), (3,1,9), (3,2,6), (3,3,3), (4,1,3), (4,2,0), (4,3,0),
(5,1,1), (5,2,0), (5,3,0), (8,1,1), (8,2,0), (8,3,0))
scala>
These results can be understood as follows:
1 times the element '1' occurred at 1 places.
2 times the element '1' occurred at 0 places.
............................................
............................................
.............................................
2 times the element '3' occurred at 6 places..
.............................................
3 times the element '3' occurred at 3 places...
............................................and so on.
Thanks to Luigi Plinge I was able to use methods in run-length encoding to group together items in a list that repeat. I used some snippets from this page here: http://aperiodic.net/phil/scala/s-99/
var n = 0
runLengthEncode(totalFrequencies).foreach{ o =>
if(o._1 > 1 && o._2==subjectNumber) n+=1
}
n
The method runLengthEncode is as follows:
private def pack[A](ls: List[A]): List[List[A]] = {
if (ls.isEmpty) List(List())
else {
val (packed, next) = ls span { _ == ls.head }
if (next == Nil) List(packed)
else packed :: pack(next)
}
}
private def runLengthEncode[A](ls: List[A]): List[(Int, A)] =
pack(ls) map { e => (e.length, e.head) }
I'm not entirely satisfied that I needed to use the mutable var n to count the number of occurrences but it did the trick. This will count the number of times a number repeats itself no matter how many times it is repeated.
If you knew your list was not very long you could do it with Strings.
val list = List(1,2,3,3,4,2,8,4,3,3,5)
val matchList = List(3,3)
(matchList.mkString(",")).r.findAllMatchIn(list.mkString(",")).length
From you pseudocode I got this working:
val pairs = list.sliding(2).toList //create pairs of consecutive elements
val result = pairs.groupBy(x => x).map{ case(x,y) => (x,y.size); //group pairs and retain the size, which is the number of occurrences.
result will be a Map[List[Int], Int] so you can the count number like:
result(List(3,3)) // will return 2
I couldn't understand if you also want to check lists of several sizes, then you would need to change the parameter to sliding to the desired size.
def pack[A](ls: List[A]): List[List[A]] = {
if (ls.isEmpty) List(List())
else {
val (packed, next) = ls span { _ == ls.head }
if (next == Nil) List(packed)
else packed :: pack(next)
}
}
def encode[A](ls: List[A]): List[(Int, A)] = pack(ls) map { e => (e.length, e.head) }
val numberOfNs = list.distinct.map{ n =>
(n -> list.count(_ == n))
}.toMap
val runLengthPerN = runLengthEncode(list).map{ t => t._2 -> t._1}.toMap
val nRepeatedMostInSuccession = runLengthPerN.toList.sortWith(_._2 <= _._2).head._1
Where runLength is defined as below from scala's 99 problems problem 9 and scala's 99 problems problem 10.
Since numberOfNs and runLengthPerN are Maps, you can get the population count of any number in the list with numberOfNs(number) and the length of the longest repitition in succession with runLengthPerN(number). To get the runLength, just compute as above with runLength(list).map{ t => t._2 -> t._1 }.

Using Stream as a substitute for loop

scala> val s = for(i <- (1 to 10).toStream) yield { println(i); i }
1
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> s.take(8).toList
2
3
4
5
6
7
8
res15: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8)
scala> s.take(8).toList
res16: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8)
Looks like Scala is storing stream values in memory to optimize access. Which means that Stream can't be used as a substitute for imperative loop as it will allocate memory. Things like (for(i <- (1 to 1000000).toStream, j <- (1 to 1000000).toStream) yield ...).reduceLeft(...) will fail because of memory. Was it wrong idea to use streams this way?
You should use Iterator instead of Stream if you want a loop-like collection construct. Stream is specifically for when you want to store past results. If you don't, then, for instance:
scala> Iterator.from(1).map(x => x*x).take(10).sum
res23: Int = 385
Methods continually, iterate, and tabulate are among the more useful ones in this regard (in the Iterator companion object).