0

this is my problem

I've a variable number of items in an array

array (x, y, z, ..., n)

And i've a fixed total assigned to a variable

$min_int = 0;
$max_int = 8;
$total = 8;

I need to assign to every item in the array a random int from $min_int to $max_int and the total of the items in the array has to be always =8.

For example:

array (red, green, blue);
$min_int = 0;
$max_int = 8;
$total = 8;

the result could be

Array
(
    [0] => 3
    [1] => 5
    [2] => 0
)

OR

Array
    (
        [0] => 3
        [1] => 3
        [2] => 2
    )

I would develop in javascript.

Any suggestions please?

Here's the link of the table i've to populate with random int. Checking the client's checkboxes and the columns of days you want to populate, the loop has to generate the random int for the selected clients in the selected day and the total has to be =8 (col-# SUMMA), so for every days you select.

  • do u only have three elements in the array ? – m0bi5 Feb 13 '15 at 16:33
  • 1
    Pick a random number in the range `[$min, min($total, $max)]`, assign it to the first element. Subtract this from `$total`. Repeat this for the next element, and so on. – Barmar Feb 13 '15 at 16:35
  • Or in reverse order: take total and subtract random(0, total) from it as many times as you need. – Andrei Nikolaenko Feb 13 '15 at 16:38
  • To get the greatest variation in possible assignments, look up an integer partitioning algorithm. Choose a random partition and fill the remaining values with 0's. – jpriebe Feb 13 '15 at 16:43
  • The items in the array could be variable. Could you help me with some example, please. – Alessio Masucci Feb 13 '15 at 16:49
  • You actually have an inherent issue in your problem . . . what if your numbers are `$min_int = 0; $max_int = 8; $total = 13;` and your array length is 3, and your first two values come up as 0? You now need the total to equal 13, but the largest random number you can generate is 8. – talemyn Feb 13 '15 at 17:09
  • No. $min_int is always 0 and max_int is always 8 and $total is always 8. So the total of the random generated int in the array have to be always 8 – Alessio Masucci Feb 13 '15 at 17:11
  • Oh, I see . . . I thought you were saying that they were stored as variables and could be changed. – talemyn Feb 13 '15 at 18:05

2 Answers2

0

My most intuitive guess would be

var max_int = 8;
var first = Math.floor(Math.random() * max_int) + 1;
var second = Math.floor(Math.random() * (max_int - first)) + 1;
var third = max_int - first - second;

But there is probably some mathematical bias here. I'm not a mathematician, so this is an invitation to anyone who knows statistics to take a closer look at this. This does work, though, since you always end up with max_int if you sum first, second and third.

Gijs
  • 84
  • 10
  • [jsfiddle](http://jsfiddle.net/masterhead/jsfq8rm7/1/#&togetherjs=2hrgvBTEPQ) Anyone wanto to partecipate? :D – Alessio Masucci Feb 13 '15 at 17:00
  • Here, this be a fully functional version of what I just suggested: http://jsfiddle.net/fabt5643/ Couldn't get in your collaborative JSFiddle, so I attempted it myself :) Just click the randomize button and it should work. Note that I made a small error in the first attempt: the "+1" in calculating the second variable should not be there. This lead to the third one becoming -1 occasionally. – Gijs Feb 13 '15 at 17:16
  • It looks perfet!! :D but if i would use the array? :P – Alessio Masucci Feb 13 '15 at 17:18
  • You'd have to put the whole thing in a for-loop and let the for loop create a number of elements on your document containing the values. Give me a second, I might be able to put something together. – Gijs Feb 13 '15 at 17:28
  • Update JSFiddle: http://jsfiddle.net/fabt5643/1/ The problem here is that the last element will always be the one with the remaining value in it, but you could solve that by for example shuffling the elements of your array afterwards. Also, there seems to be a limited number of combinations if you make your array too long, but again, that's for a statistician to analyze :p – Gijs Feb 13 '15 at 17:43
0

This solution should do what you are looking for:

var $min_int = 0;
var $max_int = 8;
var $total = 8;

var array = new Array(3);
var sum = 0;
var currentMax = $max_int;

for (i = 0; i < array.length; i++) {
    if ((i !== (array.length - 1)) && (currentMax > 0)) {
        var randomNum = parseInt(Math.random() * currentMax);
        array[i] = randomNum;
        currentMax -= randomNum;
    }
    else {
        array[i] = currentMax;
    }
}

console.log(array);

This approach: 1. loops through the length of the array, 2. for each array element, it creates a random integer, based on the maximum value and stores it 3. it then reduces the maximum value by the value of the number that was just generated and repeats for the next array element

Note #1: It will also skip the processing, if the "new maximum" has reached 0 (i.e., the generated random number will always be 0, so no need to calculate) or the logic has reached the last element in the array (i.e., the value for that element, should be the remaining "maximum" value).

Note #2: var $min_int and var $total are never actually used in this solution.

Here are some test values:

For var array = new Array(3);

[3, 3, 2]
[0, 2, 6]
[8, 0, 0]
[1, 4, 3]
[0, 4, 4]

For var array = new Array(5);

[4, 0, 1, 0, 3]
[7, 1, 0, 0, 0]
[1, 2, 0, 4, 1]
[3, 4, 1, 0, 0]
[4, 3, 0, 0, 1]

For var array = new Array(8);

[7, 0, 1, 0, 0, 0, 0, 0]
[3, 2, 3, 0, 0, 0, 0, 0]
[5, 3, 0, 0, 0, 0, 0, 0]
[2, 4, 1, 0, 1, 0, 0, 0]
[7, 0, 1, 0, 0, 0, 0, 0]
talemyn
  • 7,822
  • 4
  • 31
  • 52
  • It is awesome! i think your solution could be the best one. But in case of Array(8) most times the latest elements in the array has 0 as value. Howit could be solved? what about select a random item in the array and assign the value? – Alessio Masucci Feb 14 '15 at 17:07
  • This is exactly what i've to do. [http://jsfiddle.net/masterhead/ewdnhh3f/23/](http://jsfiddle.net/masterhead/ewdnhh3f/23/) i need to fill the table, selecting the client and the day, and the function has to fill the col and the row with the random int – Alessio Masucci Feb 14 '15 at 19:31
  • Yeah, and that is happening because the group of potential numbers will (generally) get smaller, since the totals have to add up to 8. If a bigger numbers get chosen early, then you only have smaller numbers to pick from later in the array building process. Having `array(8)` makes it even more noticable, because there are so many array elements that need to add up to such a small number. The good thing is, there is a great "shuffle" function that you can use to mix up the results, here: http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array?s=2|2.4845 – talemyn Feb 17 '15 at 15:59