4
\$\begingroup\$

This code was created for a game project in which 10 houses need to be populated with 16 people. I wanted the distribution to be random, with no more than 3 and no less than 1 person per house and no remaining people or houses.

JSbin link

function getRandomPartitionsFromNumber(number, parts, min, max) {
 var result = [];
 for (var i = 0; i < parts; i++) {
 var part = randomIntFromInterval(min, max);
 result.push(part);
 }
 var sum = result.reduce(add, 0);
 // If the sum is greater than the number, we need to iterate through
 // the result and remove some numbers until it's equal
 while (sum > number) {
 for (i = 0; i < result.length; i++) {
 if (result[i] > min) {
 result[i]--;
 sum = result.reduce(add, 0);
 if (sum === number) {
 break;
 }
 }
 }
 sum = result.reduce(add, 0);
 }
 while (sum < number) {
 for (i = 0; i < result.length; i++) {
 if (result[i] < max) {
 result[i]++;
 sum = result.reduce(add, 0);
 if (sum === number) {
 break;
 }
 }
 }
 }
 return result;
}
function randomIntFromInterval(min, max) {
 return Math.floor(Math.random() * (max - min + 1) + min);
}
function randomFromArray(array) {
 return array[randomIntFromInterval(0, array.length - 1)];
}
function add(a, b) {
 return a + b;
}
console.log(getRandomPartitionsFromNumber(16, 10, 1, 3));
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jan 13, 2016 at 7:49
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

The way you have done your algorithm, you could just apply the same operation to your sum variable, rather than reducing the entire array.

 while (sum > number) {
 for (i = 0; i < result.length; i++) {
 if (result[i] > min) {
 result[i]--;
 sum--
 if (sum === number) {
 break;
 }
 }
 }
 sum = result.reduce(add, 0);
 }

Additionally, the last sum = result.reduce is not needed here, as any change in the result array is subsequently reflected in the sum variable a row lower.

 while (sum > number) {
 for (i = 0; i < result.length; i++) {
 if (result[i] > min) {
 result[i]--;
 sum--
 if (sum === number) {
 break;
 }
 }
 }
 }

Lastly, keep in mind if you were to feed your code an impossible situation ("stuff 5 people into 1 house where each house can only contain 3 people at most"), you will get an infinite loop. It's up to you to decide how to handle this.

answered Jan 13, 2016 at 10:15
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.