Generate sets of numbers with a predefined sum
For a rhythmic sequence generator, I want to generate sets of (semi)random integers which each have the same predefined sum. For example, if 10 is my target sum, the generator might output "2 5 2 1" or "1 1 4 1 3."
How could I achieve this? I could loop the generator and reject number sets that don't add up to the target sum until one does, but that seems inefficient.
In a step sequencer, you're just counting the delay times between beats:
1 2 3 4 5 6 7 8 9 10
- x - - - - x - x - x
- 2- - - - 5 - 2 - 1
Here's one way to implement it (a bitmap would also work):
1. Generate N-1 sorted, unique random numbers (urn) from 1 to 9. E.g., 1 4 7
2. Pad w/ 0 and 10; 1 4 7 -> 0 1 4 7 10.
3. Take the deltas: 0 1 4 7 10 -> 1 3 3 3
and a quick-and-dirty patcher.
Of course, any set thus generated can be shuffled, reversed, etc. w/ zl list ops to make variations.
Thank you for the reply! In the patcher you posted though, the resulting sets of numbers often have different sums. My goal is to have each generated set have a uniform, user-definable sum. Does that make sense?
I also want the quantity of numbers in each set be (semi)randomly determined
These add up to 10 (check you have the patcher I just uploaded, not the first one):
print: 7 1 1 1
print: 1 5 1 3
print: 4 2 3 1
print: 1 1 1 7
print: 1 4 2 3
print: 1 2 1 6
print: 4 4 1 1
print: 5 1 1 3
print: 2 1 2 5
print: 1 1 2 6
print: 1 2 3 4
or, with groups of 7:
print: 2 1 1 1 1 3 1
etc.
Or change two numbers and make 'em add up to 5:
print: 2 2 1
print: 2 1 2
print: 1 3 1
Randomized group sizes:
outputs
print: 5 3 2
print: 3 3 2 2
print: 2 3 1 2 2
print: 1 4 2 1 2
print: 7 2 1
print: 1 5 1 3
etc.
Here is another approach (javascript function to be used in js object):
// num - given number
// step - incremental step
// cnt - counter (next location in array)
// arr - array to store the combination
function getNumbers(num, step, cnt, arr) {
if (cnt > num || step > num) {
return;
} else if (cnt == num) {
// if counter cnt reached num print the list
console.log(arr);
return;
} else {
// else append the step size to list
arr.push(step);
// increment the cnt by step and recurse
getNumbers(num, step, cnt + step, arr);
// remove the last step item from list
arr.pop();
// increment the step size and recurse
getNumbers(num, step + 1, cnt, arr);
}
}
Here is the output of getNumbers(10, 1, 0, []) (to be shuffled, reversed, etc. with zl list ops to make variations):
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
[ 1, 1, 1, 1, 1, 1, 1, 1, 2 ]
[ 1, 1, 1, 1, 1, 1, 1, 3 ]
[ 1, 1, 1, 1, 1, 1, 2, 2 ]
[ 1, 1, 1, 1, 1, 1, 4 ]
[ 1, 1, 1, 1, 1, 2, 3 ]
[ 1, 1, 1, 1, 1, 5 ]
[ 1, 1, 1, 1, 2, 2, 2 ]
[ 1, 1, 1, 1, 2, 4 ]
[ 1, 1, 1, 1, 3, 3 ]
[ 1, 1, 1, 1, 6 ]
[ 1, 1, 1, 2, 2, 3 ]
[ 1, 1, 1, 2, 5 ]
[ 1, 1, 1, 3, 4 ]
[ 1, 1, 1, 7 ]
[ 1, 1, 2, 2, 2, 2 ]
[ 1, 1, 2, 2, 4 ]
[ 1, 1, 2, 3, 3 ]
[ 1, 1, 2, 6 ]
[ 1, 1, 3, 5 ]
[ 1, 1, 4, 4 ]
[ 1, 1, 8 ]
[ 1, 2, 2, 2, 3 ]
[ 1, 2, 2, 5 ]
[ 1, 2, 3, 4 ]
[ 1, 2, 7 ]
[ 1, 3, 3, 3 ]
[ 1, 3, 6 ]
[ 1, 4, 5 ]
[ 1, 9 ]
[ 2, 2, 2, 2, 2 ]
[ 2, 2, 2, 4 ]
[ 2, 2, 3, 3 ]
[ 2, 2, 6 ]
[ 2, 3, 5 ]
[ 2, 4, 4 ]
[ 2, 8 ]
[ 3, 3, 4 ]
[ 3, 7 ]
[ 4, 6 ]
[ 5, 5 ]
[ 10 ]