I was working on something similar and here is what I came up with.
You can do this in O(N-1) using some calculations at each step. You begin by picking a random number between the minimum number and max number for each spot. For each spot, max number is calculated by subtracting (Min_Number * Remaining_Spots) from the Remaining Balance.
For example: for the first spot you pick a number between 2 and 38. You get this by subtracting (7-1)*2 from 50. i.e. 50 - 12 = 38.
Once you pick a number, let's say 19, then for the next spot the range is 2-21. i.e. 50-19-(5*2) = 21..
..and so on.
Here is the code snippet:
function splitNumIntoXRandomComponents(num, x, min_num) {
var components = [];
var count = 1;
var cumulative = 0;
var balance = num;
for (var i = 0; i<x-1; i++) {
//max num for this spot
var max_num = balance - ((x-count)*min_num);
//to avoid big numbers in the beginning and min numbers at the end
if (Math.random() > 0.5){ //0.5 can be tuned to your liking
max_num = Math.floor(max_num / 2) + min_num;
}
//generate the number for the spot at 'count'
var c = Math.floor(Math.random()*(max_num-min_num+1)+min_num);
//adjust balances
cumulative += c;
balance -= c;
count++;
//store this number
components.push(c);
}
//push remaining balance into the last spot
components.push(balance);
//print numbers
console.log(components);
}
for (var i=0; i<10; i++) {
splitNumIntoXRandomComponents(50, 7, 2);
}
Here is the sample output:
[34, 2, 4, 3, 3, 2, 2]
[14, 12, 8, 8, 4, 2, 2]
[7, 4, 26, 5, 2, 3, 3]
[8, 2, 16, 4, 4, 9, 7]
[20, 8, 4, 4, 7, 4, 3]
[3, 34, 4, 2, 2, 2, 3]
[10, 5, 15, 2, 7, 5, 6]
[6, 3, 10, 4, 10, 3, 14]
[31, 4, 2, 3, 5, 2, 3]
[7, 5, 2, 9, 9, 2, 16]
Here is the jsFiddle:
http://jsfiddle.net/wj81kvsc/6/
Spl(X,N,M)=..ComplexFormula..
that gives you how many ways you can split a numberX
intoN
subsections havingM
as minimum.Spl(50,7,7)
would be=1
for example. – ypercubeᵀᴹ