I'm very new to Scala and I have to find primes for numbers in range [i;j].
This is how I fill stream:
val stream = (i to j).toStream
and then I call this function which supposed to find primes:
def findPrimes(s: Stream[Int]): Stream[Int] = {
println("HEAD: " + s.head)
return findPrimes(s.tail)
// s.head #:: findPrimes(s.tail.filter( _ % s.head != 0 ))
}
Outputting stream to console, I am surprised why am I getting exception:
Exception in thread "main" java.util.NoSuchElementException: head of empty stream
at scala.collection.immutable.Stream$Empty$.head(Stream.scala:1104)
at scala.collection.immutable.Stream$Empty$.head(Stream.scala:1102)
at com.example.anna.app.HelloWorld$.findPrimes(HelloWorld.scala:43)
STREAM SIZE IS 100
at com.example.anna.app.HelloWorld$.prime(HelloWorld.scala:32)
HEAD: 1
at com.example.anna.app.HelloWorld$.delayedEndpoint$com$example$anna$app$HelloWorld$1(HelloWorld.scala:11)
HEAD: 2
HEAD: 3
at com.example.anna.app.HelloWorld$delayedInit$body.apply(HelloWorld.scala:3)
HEAD: 4
at scala.Function0.apply$mcV$sp(Function0.scala:34)
HEAD: 5
HEAD: 6
at scala.Function0.apply$mcV$sp$(Function0.scala:34)
HEAD: 7
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
HEAD: 8
HEAD: 9
at scala.App.$anonfun$main$1$adapted(App.scala:76)
HEAD: 10
HEAD: 11
at scala.collection.immutable.List.foreach(List.scala:389)
HEAD: 12
at scala.App.main(App.scala:76)
HEAD: 13
at scala.App.main$(App.scala:74)
HEAD: 14
HEAD: 15
at com.example.anna.app.HelloWorld$.main(HelloWorld.scala:3)
HEAD: 16
at com.example.anna.app.HelloWorld.main(HelloWorld.scala)
HEAD: 17
starting from 17 up to end there's no single exception.
And also this commented line doesn't work - it throws same exception.
Any help & advice would be appreciated.
Stream that you pass to findPrimes is of limited size and is getting exhausted when you call findPrimes.
Create infinite stream using Stream.from method.
Scala REPL
scala> :paste
// Entering paste mode (ctrl-D to finish)
def primeStream(s: Stream[Int]): Stream[Int] =
Stream.cons(s.head, primeStream(s.tail filter { _ % s.head != 0 }))
val primes = primeStream(Stream.from(2))
// Exiting paste mode, now interpreting.
primeStream: (s: Stream[Int])Stream[Int]
primes: Stream[Int] = Stream(2, ?)
scala> primes.take(100).toList
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541)
Problem with your code.
scala> val primes = primeStream((1 to 100).toStream)
primes: Stream[Int] = Stream(1, ?)
scala> primes.take(100).toList
java.util.NoSuchElementException: head of empty stream
at scala.collection.immutable.Stream$Empty$.head(Stream.scala:1104)
at scala.collection.immutable.Stream$Empty$.head(Stream.scala:1102)
at .primeStream(<console>:12)
at .$anonfun$primeStream$1(<console>:12)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1169)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1159)
at scala.collection.immutable.Stream.$anonfun$take$2(Stream.scala:789)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1169)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:1159)
at scala.collection.generic.Growable.loop$1(Growable.scala:54)
at scala.collection.generic.Growable.$plus$plus$eq(Growable.scala:58)
at scala.collection.generic.Growable.$plus$plus$eq$(Growable.scala:50)
at scala.collection.mutable.ListBuffer.$plus$plus$eq(ListBuffer.scala:186)
at scala.collection.mutable.ListBuffer.$plus$plus$eq(ListBuffer.scala:44)
at scala.collection.TraversableLike.to(TraversableLike.scala:590)
at scala.collection.TraversableLike.to$(TraversableLike.scala:587)
at scala.collection.AbstractTraversable.to(Traversable.scala:104)
at scala.collection.TraversableOnce.toList(TraversableOnce.scala:294)
at scala.collection.TraversableOnce.toList$(TraversableOnce.scala:294)
at scala.collection.AbstractTraversable.toList(Traversable.scala:104)
... 28 elided
Why this throws an exception? The reason for this is the head method called on empty stream in the println statement.
So we can pattern-match this stream to return empty stream when the tail is empty as follows (there are better ways to traverse stream, but I tried not to change your code very much):
def findPrimes(s: Stream[Int]): Stream[Int] = s match {
case Stream.Empty =>
println("END") //consider removing println statements
Stream.Empty
case h #:: tl =>
println(s"HEAD: $h")
h #:: findPrimes(tl)
}
Related
Suppose I have two Streams which could be finite or infinite:
val a = Stream(1, 2, 3)
val b = Stream(95, 96, 97, 98, 99)
I can zip them together like so:
left.zip(right).flatMap { case (a, b) => Stream(a, b) }
However, the end result would merge three elements from a and three from b (1, 95, 2, 96, 3, 97). What I'd like to achieve is to zip those two Streams and if one's bigger in size, append the remainder. So the output would be 1, 95, 2, 96, 3, 97, 98, 99.
Is there a nice functional way to achieve this?
You can use zipAll + Option to do that.
def join[A](s1: Stream[A], s2: Stream[A]): Stream[A] =
s1.map(a => Some(a)).zipAll(s2.map(a => Some(a)), None, None).flatMap {
case (Some(a1), Some(a2)) => Stream(a1, a2)
case (Some(a1), None) => Stream(a1)
case (None, Some(a2)) => Stream(a2)
case (None, None) => Stream.empty
}
join(Stream(1, 2, 3), Stream(95, 96, 97, 98, 99))
// res: Stream[Int] = Stream(1, 95, 2, 96, 3, 97, 98, 99)
(PS: If you are in Scala 2.13 use LazyList instead of Stream)
We have the following sequence of numbers: [19, 23, 24, 31, 126, 127, 155, 159, 160, 161]. We need to group this sequence according to difference between the neighboring values such that difference of values in each group would be equal to 1 if group size is > 1.
In Python, I would write something like:
outliers = [19, 23, 24, 31, 126, 127, 155, 159, 160, 161]
chains = [[i for i in list(map(itemgetter(1), g))]
for _, g in itertools.groupby(enumerate(outliers),
lambda x: x[0]-x[1])]
# [[19], [23, 24], [31], [126, 127], [155], [159, 160, 161]]
Pretty neat. But how can this be done in Scala without falling back to loops with conditions? I have been trying to do something with zipWithIndex and groupBy methods by so far to no avail :(
You can fold over the sequence, building the result as you go.
outliers.foldRight(List.empty[List[Int]]) {case (n, acc) =>
if (acc.isEmpty) List(List(n))
else if (acc(0)(0) == n+1) (n :: acc.head) :: acc.tail
else List(n) :: acc
}
//res0: List[List[Int]] = List(List(19), List(23, 24), List(31), List(126, 127), List(155), List(159, 160, 161))
Not sure if recursion can match with your conditions but it at last O(n).
def rec(source: List[Int], temp: List[Int], acc: List[List[Int]]): List[List[Int]] = source match {
case Nil => acc
case x :: xs => {
if (xs.nonEmpty && xs.head - x == 1) rec(xs, temp :+ x, acc)
else rec(xs, List(), acc :+ (temp :+ x))
}
}
val outliers = List(19, 23, 24, 31, 126, 127, 155, 159, 160, 161)
rec(outliers, List[Int](), List[List[Int]]())
output : prime numbers
2
3
()
5
()
7
()
()
i want as
2
3
5
7
def primeNumber(range: Int): Unit ={
val primeNumbers: immutable.IndexedSeq[AnyVal] =
for (number :Int <- 2 to range) yield{
var isPrime = true
for(checker : Int <- 2 to Math.sqrt(number).toInt if number%checker==0 if isPrime) isPrime = false
if(isPrime) number
}
println("prime numbers")
for(prime <- primeNumbers)
println(prime)
}
so the underlying problem here is that your yield block effectively will return an Int or a Unit depending on isPrime this leads your collection to be of type AnyVal because that's pretty much the least upper bound that can represent both types. Unit is a type only inhabited by one value which is represented as an empty set of round brackets in scala () so that's what you see in your list.
As Puneeth Reddy V said you can use collect to filter out all the non-Int values but I think that is a suboptimal approach (partial functions are often considered a code-smell depending on what type of scala-style you do). More idiomatic would be to rethink your loop (such for loops are scarcely used in scala) and this could be definitely be done using a foldLeft operation maybe even something else.
You can use collect on your output
primeNumbers.collect{
case i : Int => i
}
res2: IndexedSeq[Int] = Vector(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)
The reason is if else returning two types of value one is prime value and another is empty. You could return 0 in else case and filter it before printing it.
scala> def primeNumber(range: Int): Unit ={
|
| val primeNumbers: IndexedSeq[Int] =
|
| for (number :Int <- 2 to range) yield{
|
| var isPrime = true
|
| for(checker : Int <- 2 to Math.sqrt(number).toInt if number%checker==0 if isPrime) isPrime = false
|
| if(isPrime) number
| else
| 0
| }
|
| println("prime numbers" + primeNumbers)
| for(prime <- primeNumbers.filter(_ > 0))
| println(prime)
| }
primeNumber: (range: Int)Unit
scala> primeNumber(10)
prime numbersVector(2, 3, 0, 5, 0, 7, 0, 0, 0)
2
3
5
7
But we should not write the code the way you have written it. You are using mutable variables. Try to write code in an immutable way.
For example
scala> def isPrime(number: Int) =
| number > 1 && !(2 to number - 1).exists(e => e % number == 0)
isPrime: (number: Int)Boolean
scala> def generatePrimes(starting: Int): Stream[Int] = {
| if(isPrime(starting))
| starting #:: generatePrimes(starting + 1)
| else
| generatePrimes(starting + 1)
| }
generatePrimes: (starting: Int)Stream[Int]
scala> generatePrimes(2).take(100).toList
res12: List[Int] = List(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101)
I would like to convert every single word into decimal ascii.
for example "RESEP" :
R = 82,
E = 69,
S = 83,
E = 69,
P = 80
my code is:
val LIST_KEYWORD = List("RESEP",
"DAGING SAPI",
"DAGING KAMBING")
val RUBAH_BYTE = LIST_KEYWORD.map(_.split(",")).map
{
baris =>
(
baris(0).getBytes
)
}
and then, I get stuck and I don't know what I am supposed to do next.
scala> "RESEP".map(_.toByte)
res1: scala.collection.immutable.IndexedSeq[Byte] = Vector(82, 69, 83, 69, 80)
scala> "RESEP".map(x => x -> x.toByte)
res2: scala.collection.immutable.IndexedSeq[(Char, Byte)] = Vector((R,82), (E,69), (S,83), (E,69), (P,80))
scala> val LIST_KEYWORD = List("RESEP",
| "DAGING SAPI",
| "DAGING KAMBING")
LIST_KEYWORD: List[String] = List(RESEP, DAGING SAPI, DAGING KAMBING)
scala> LIST_KEYWORD.map(_.map(_.toByte))
res3: List[scala.collection.immutable.IndexedSeq[Byte]] = List(Vector(82, 69, 83, 69, 80), Vector(68, 65, 71, 73, 78, 71, 32, 83, 65, 80, 73), Vector(68, 65, 71, 73, 78, 71, 32, 75, 65, 77, 66, 73, 78, 71))
scala> LIST_KEYWORD.map(_.map(x => x -> x.toByte))
res4: List[scala.collection.immutable.IndexedSeq[(Char, Byte)]] = List(Vector((R,82), (E,69), (S,83), (E,69), (P,80)), Vector((D,68), (A,65), (G,71), (I,73), (N,78), (G,71), ( ,32), (S,83), (A,65), (P,80), (I,73)), Vector((D,68), (A,65), (G,71), (I,73), (N,78), (G,71), ( ,32), (K,75), (A,65), (M,77), (B,66), (I,73), (N,78), (G,71)))
I have elements from an Enumerator[A], and want to group/batch the elements to get an Enumerator[Seq[A]]. Here's code I wrote which groups A to Seq[A], but doesn't produce an Enumerator[Seq[A]].
val batchSize = 1000
dogsEnumerator
.run(
Iteratee.fold1[Dog, Vector[Dog]](Future.successful(Vector[Dog]())){
(r, c) =>
if (r.size > batchSize)
processBatch(r).map(_ => Vector[Dog]())
else
Future.successful(r :+ c)
}.map(_ => ())
)
This can be done pretty straightforwardly with the help of some of the Enumeratee combinators:
import play.api.libs.iteratee._
def batch[A](n: Int): Enumeratee[A, List[A]] = Enumeratee.grouped(
Enumeratee.take(n) &>> Iteratee.getChunks[A]
)
We can then use this enumeratee to transform any enumerator into a new enumerator of lists:
val intsEnumerator = Enumerator(1 to 40: _*)
intsEnumerator.through(batch(7)).run(Iteratee.foreach(println))
This will print the following:
List(1, 2, 3, 4, 5, 6, 7)
List(8, 9, 10, 11, 12, 13, 14)
List(15, 16, 17, 18, 19, 20, 21)
List(22, 23, 24, 25, 26, 27, 28)
List(29, 30, 31, 32, 33, 34, 35)
List(36, 37, 38, 39, 40)
As expected.