0

Let's say I have these two arrays

let players = ["ryan", "austin", "julian", "kelso", "mitch", "adam", "dwight", "edwin", "connor", "george"] let roles = [] 

I would like to populate roles with, let's say 30% of 'Good' and 70% 'Bad' strings in a random order, but always 30% of 'Good' roles.

example: roles: ['Bad','Bad','Bad','Bad','Good','Bad','Bad','Bad','Good','Good'] 

I am currently running this scenario which randomly creates an array, but without the percent requirements of 'Good' vs 'Bad'.

players: [ ] roles: [] while (good === false || bad === false) { roles = [] for (i = 0; i < players.length; i++) { let randomise = Math.floor(Math.random() * 2) if (randomise === 0) { roles.push("Good") innocent = true } else { roles.push("Bad") traitor = true } }; } 

Can't wrap my head around how I could achieve my goal.

2 Answers 2

2

Identify how many players must be good by multiplying by 3 / 10 ceil'd. In the loop, push a random good or bad value to the array. But, also check if you've reached the limit of good or bad values to push, in which case push the other value

const players = ["ryan", "austin", "julian", "kelso", "mitch", "adam", "dwight", "edwin", "connor", "george"] let goodCount = Math.ceil(players.length * 3 / 10); console.log('Need total of', goodCount, 'good'); const roles = [] for (let i = 0; i < players.length; i++) { if (goodCount === 0) { // Rest of the array needs to be filled with bad: roles.push('Bad'); continue; } if (goodCount === players.length - roles.length) { // Rest of the array needs to be filled with good: roles.push('Good'); goodCount--; continue; } if (Math.random() < 0.3) { roles.push('Good'); goodCount--; } else { roles.push('Bad'); } }; console.log(roles);

Remember to use const instead of let when possible, and remember to always declare your variables before using them (such as the i in the for loop), else you'll implicitly create global variables, and throw errors in strict mode.

Sign up to request clarification or add additional context in comments.

5 Comments

This doesn't consistently result in 30% of Good roles.
You said you wanted the roles to be random. Randomness is not guaranteed to result in the average ratio.
I guess I should have better clarified. I need 30% to always be Good, but in a random order. I will modify my question to include that.
Ok, see edit, figure out how many Goods you need first, then subtract on each iteration
This is beautiful. Thank you for leaving comments as well so It's easier to understand and learn from!
0

Why don't you just generate an array of 70% "bad" and 30% "good", then shuffle that array:

const players = ["ryan", "austin", "julian", "kelso", "mitch", "adam", "dwight", "edwin", "connor", "george"]; const roles = []; const badNum = Math.floor(0.7 * players.length); const goodNum = players.length - badNum; for (let i = 1; i <= players.length; i++) { roles.push(i <= badNum ? "bad" : "good"); } //Shuffle roles for (let i = 0; i < roles.length; i++) { var randomIndex = Math.floor(Math.random() * (roles.length - i)) + i; var selection = roles[randomIndex]; var extract = roles[i]; roles[i] = selection; roles[randomIndex] = extract; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.