0

I have a simple program written in C++. It generates random numbers, and stop when the sum of those numbers equal or greater than 100. The code looks like:

vector<int> container; while(container.sum() <100) { int new_number = rand()%10 + 1 ;// generate a number in range 1 to 10 container.push_back(new_number); // add new number to the container } 

What is the best way to handle the task in Scala? (without using while loop?)

It seems that FoldLeft or FoldRight function doesn't have ability to break at a condition?

2
  • 1
    What have you tried by yourself? Commented Dec 21, 2017 at 1:07
  • what do you want to do with those numbers ? do you need to store those numbers in memory ? Commented Dec 21, 2017 at 13:16

4 Answers 4

3

Create an infinite Stream of random numbers (requires very little CPU and memory), take only what you need, then turn the result Stream into the desired collection type.

val randoms = Stream.continually(util.Random.nextInt(10)+1) val container = randoms.take(randoms.scan(0)(_+_).indexWhere(_>=100)).toVector 

Added bonus is that the sums are calculated as you go, i.e. added to the previous sum, not summing from the beginning each time.

Sign up to request clarification or add additional context in comments.

Comments

2

Here's one approach to handle a while loop using a tail-recursive function as follows:

@scala.annotation.tailrec def addToContainer(container: Vector[Int], max: Int): Vector[Int] = { val newContainer = container ++ Vector(scala.util.Random.nextInt(10) + 1) if (newContainer.sum >= max) container else addToContainer(newContainer, max) } addToContainer(Vector[Int](), 100) // res1: Vector[Int] = Vector(9, 9, 5, 9, 3, 5, 2, 5, 10, 7, 6, 4, 5, 5, 9, 3) res1.sum // res2: Int = 96 

1 Comment

In general, it should be noted that while loops and tail recursive functions are exactly equivalent. So if you've got a while loop in another language (even pseudocode), you can translate it into scala as a tail recursive function (and Scala will compile it as if you'd written a while loop).
1

Here's one way to do it:

 val randomNumberGenerator = new scala.util.Random def sumUntil(list: List[Int]): List[Int] = list match { case exceeds if list.filter(_ > 0).sum > 100 => list case _ => sumUntil(list :+ (randomNumberGenerator.nextInt(10) + 1)) } 

To explain the solution:

  1. Create an instance of scala.util.Random which will help us generate random numbers
  2. sumUntil will pattern match; if the sum of the list exceeds 100, return it.
  3. In the event that the sum does not exceed 100, call sumUntil again, but with another random number generated between 10 and 1 (inclusive). Keep in mind that the _ means, "I don't care about the value, or even the type." _ is anything else but the case where the sum of all the integers in our list is greater than 100.

If you're new to Scala, I understand that it may be a bit rough on the eyes to read. Below is a refined version:

 val randomNumberGenerator = new scala.util.Random def sumUntil(list: List[Int]): List[Int] = list match { case exceeds if sumList(list) > 100 => list case _ => sumUntil(appendRandomNumberToList(list)) } private def sumList(list: List[Int]): Int = { list.filter(_ > 0).sum } private def appendRandomNumberToList(list: List[Int]): List[Int] = { list :+ randomNumberGenerator.nextInt(10) + 1 } 

Comments

0
  • If your loop just scans through the collection, use fold or reduce.
  • If it needs some custom terminate condition, recursion is favored.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.