2

I have an array of numbers that can range from zero to infinity. I need to generate random numbers lower than that of the numbers in the array, one for each number. For example if i have the numbers:

[10, 5, 0, 7]

An output could be any of:

[5, 3, 0, 6] or [1, 0, 0, 7] or [10, 5, 0, 7]

This is simple enough, but my problem lies with the next part. I have to make sure these numbers add up to a specified value. For example, the same first array could produce:

[4, 3, 0, 1] or [8, 0, 0, 0]

with the total value being 8.

After doing some research, i found this post but sadly, it does not incorporate per-value limits. Rather it has one total, and generates a set of numbers according to that. I need all of these numbers to be less an that of an inputted array. Using Jquery's each loop, you can create a vale less than that of the number corresponding, but how would i incorporate the total value?

If someone could modify that post to have a three values, being total, max, and min, it would be very appreciated. At this point, i am clueless.

Community
  • 1
  • 1
Ozay34
  • 107
  • 1
  • 3
  • 9

3 Answers3

2

Here is a basic solution. Note that I set maxLoops or else this function could potentially run forever.

function randomize(array, total){
    var maxLoops = 100, randomized;
    do{
        randomized = array.map(function(value){
           return Math.floor(Math.random()*(value+1)); 
        });
        maxLoops--;
    }while(maxLoops > 0 && randomized.reduce(function(a, b){ return a+b; }) !== total);

    return randomized;
}

var test = randomize([10, 5, 0, 7], 8);
console.log(test);

http://jsfiddle.net/fx7a1w28/

EvilZebra
  • 1,072
  • 8
  • 18
  • if I change the array going in to anything other than the one provided and change the total this no longer works – btm1 May 29 '15 at 18:52
  • Hmm I just tested my code again and it seems to work just fine. What did you enter as array and total? – EvilZebra May 30 '15 at 00:24
  • This works great! However when I tried using this to create a total number that had a decimal, the result always equaled the rounded value. Any ideas? – Brad Adams Aug 27 '15 at 13:19
  • Certainly, note on the 5th line of my example I am using `Math.floor()`, this causes all values to always be a whole number. The code would need to be changed a bit to support decimal values. – EvilZebra Aug 27 '15 at 19:53
1

I solved this in a single pass, by constraining the limits of each digit.

<html><body><script language="javascript">
var arry = [10, 5, 0, 7];
var ansa = [];
var required = 8;
var sum = 0;
for (i=0; i<arry.length; i++) {
    max = required - sum;
    if (max > arry [i])
        max = arry [i];
    min = required - sum;
    for (j=i+1; j<arry.length; j++)
        min = min - arry [j];
    if (min < 0) min = 0;
    if (min > max) {
        ansa [i] = 'Impossible';
        break;
        }
    num = min + Math.floor (Math.random () * (max - min + 1));
    ansa [i] = num;
    sum = sum + num;
    }
document.writeln (ansa);
</script></body></html>
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
0

I will give you the steps. It's quite simple.

First create a function which takes an array of numbers as an argument and generates an array of random numbers less than or equal to every element of the input array. Return an associative array with the first key mapping to the sum you desire and the second key mapping to the randomly generated array.

Second create a do while loop which continues to call the function until the first key is equal to the sum of the elements you desire. The solution will then be the second key.

function generateRandomArray(input){

output = [];
for(i = 0; i <input.length; i++){ 
      output.push(Math.floor((Math.random() * input[i]) + 1))
     }

      output_sum = 0
      for(i=0; i < output.length; i++){
      output_sum += output[i]   
     }

    return {'output_sum':output_sum, 'output_array':output}

}

desired sum = 8
example_input = [10, 5, 0, 7]
do {test_output = generateRandomArray(example_input)['output_sum']} while 
(test_output != desired_sum)

correct_array = test_output['output_array]
Encinoman818
  • 231
  • 1
  • 2
  • 5