0

I need to generate a random list of numbers of a given size whose total is less than a given fixed threshold using ScalaCheck. In other words, do something like:

val threshold = 3000    
val listGenerator = Gen.listOfN(2000, Gen.choose(1,2000)) suchThat { _.sum < theshold }

While the above expresses exactly what I want to achieve, it doesn't work as the suchThat clause ends up discarding the vast majority of generated values.

Ben
  • 1,414
  • 2
  • 13
  • 18
jjst
  • 2,631
  • 2
  • 22
  • 34
  • 1
    Are you sure you need to do this? Every constraint you put on a ScalaCheck generator means more potential inputs that aren't being checked. – Travis Brown Feb 20 '16 at 23:14

2 Answers2

0

Well, given your maximum is 3k and you want a list of 2000 with the minimum value of 1, I'd expect a list of mostly 1s and 2s. One solution is below (With current numbers will only generate a list of 1s),

val threshold = 3000

val max = 2000
val max = threshold / n

val listGenerator = Gen.listOfN(max, Gen.choose(1,max))

The math would change a bit if you allow 0s.

0

Assuming the threshold is T, and the length of the list is N, You can generate this list by picking N + 1 distinct sorted random numbers within 0 until T, and then compute the differences between adjacent numbers.

For example, let T = 10 and N = 3, generate 4 distinct sorted numbers first:

1, 4, 6, 9

By computing the differences of adjacent numbers, you get:

3, 2, 3

whose sum is 8, less than 10.

Following this, you can have the following generator:

  def gen(T: Int, N: Int): Gen[collection.Seq[Int]] =
    Gen.pick(N + 1, 0 until T).map(_.sortBy(-_)).map { sorted =>
      (sorted.init, sorted.tail).zipped.map(_ - _)
    }
Cheng Lian
  • 633
  • 4
  • 9