Reputation: 769
Seq.fill(n)(math.pow(Random.nextFloat,2) + math.pow(Random.nextFloat,2)).filter(_<1).size.toFloat/n*4
Basically this scala code checks number of times a random points comes out of first quadrant of a unit circle. For large values of n
this code gives memory limit exceeded error as it requires too big sequence. I can write this java way. But is there some functional way to achieve this task?
Upvotes: 2
Views: 77
Reputation: 14825
Instead of filtering the values which are less than 1 after filling the sequence, consider adding valid numbers (i.e numbers greater or equal to 1) to the list. Thus saving unnecessary iteration on the collection.
def nums(n: Int): Iterator[Float] = {
import scala.util.Random
def helper(items: Iterator[Float], counter: Int): Iterator[Float] = {
val num = math.pow(Random.nextFloat,2) + math.pow(Random.nextFloat,2)
if (counter > 0) {
if (num >= 1) helper( items ++ Iterator(num.toFloat), counter - 1) else helper(items, counter - 1)
} else items
}
helper(Iterator[Float](), n)
}
final answer
nums(n).toFloat/(n * 4)
Scala REPL
scala> def nums(n: Int): Iterator[Float] = {
| import scala.util.Random
| def helper(items: Iterator[Float], counter: Int): Iterator[Float] = {
| val num = math.pow(Random.nextFloat,2) + math.pow(Random.nextFloat,2)
| if (counter > 0) {
| if (num >= 1) helper( items ++ Iterator(num.toFloat), counter - 1) else helper(items, counter - 1)
| } else items
| }
| helper(Iterator[Float](), n)
| }
nums: (n: Int)Iterator[Float]
scala> nums(10000).size.toFloat/(10000 * 4)
res1: Float = 0.053925
Upvotes: 0
Reputation: 15086
If you use an Iterator
no intermediate collection has to be created in memory.
Iterator.fill(n)(math.pow(Random.nextFloat,2) + math.pow(Random.nextFloat,2)).filter(_<1).size.toFloat/n*4
Upvotes: 3