I want to split 10 into an array of 4 random numbers, but neither can be 0 or higher than 4. For example [1,2,3,4],
A litte late to the show, but I found this a fun task to think about so here you go. My approach does not need to create all partitions, it also does not rely on pure luck of finding a random match, it is compact and it should be unbiased.
It works efficiently even when large values are used, as long as max is not too limiting.
const len = 4;
const total = 10;
const max = 4;
let arr = new Array(len);
let sum = 0;
do {
// get some random numbers
for (let i = 0; i < len; i++) {
arr[i] = Math.random();
}
// get the total of the random numbers
sum = arr.reduce((acc, val) => acc + val, 0);
// compute the scale to use on the numbers
const scale = (total - len) / sum;
// scale the array
arr = arr.map(val => Math.min(max, Math.round(val * scale) + 1));
// re-compute the sum
sum = arr.reduce((acc, val) => acc + val, 0);
// loop if the sum is not exactly the expected total due to scale rounding effects
} while (sum - total);
console.log(arr);