0

I am asking this question for my JS code, but it's actually a problem that I'm having in every programming language.

Let's say I have 5 names for dogs in my simulation, I can hold them in an array and choose a random name for every dog like this

var NAMES = ["Scafy","Shimshon","WoofWoof","Mitzy","AnotherDogName"]//possible names for the dogs

dog.name = NAMES[Math.floor(Math.random()*NAMES.length)] // chooses a random name from for the dog

So this is simple. but my problem is when I want some of the sames to have higher or lower chance, with 5 names is not that difficult to do this:

give WoofWoof much higher chance of getting chosen than the other names by doing this ugly mess:

var NAMES = ["Scafy","Shimshon","WoofWoof","Mitzy","AnotherDogName"]//possible names for the dogs


function choose(){
   var random = Math.random()*100
   var name = NAMES[0]
   if (random>20)
      name = NAMES[1]
   if (random>30)
      name = NAMES[2]
   if (random>80)
      name = NAMES[3]
   if (random>90)
      name = NAMES[4]

   return name
}

This method works, but it's ugly, and becomes unbelievably complicated when there are a lot of options to choose from and many different chances.

I am sure than I am not the only one who had encounter this problem, and I feel like I'm missing a very elegant solution that hides just below my nose (I hope this sentence makes sense in english too)

This is a general question, I asked it in JS, but I have the same problem in any programming language.

My question is what's the most elegant way of doing it

Thank you

  • 1
    Adding repeated values to the array would also increase their "weight". – Taplar Nov 24 '20 at 21:47
  • 1
    Put the weights in an array, one for each name, and then run your logic by a loop instead of repeated `if`/`else` statements. – Bergi Nov 24 '20 at 21:48
  • 1
    @Taplar, I was going to suggest this too. Maybe even "neaten" it up by creating an object with the names as key and weightings as the values. Then generate the Names array from the object. – mykaf Nov 24 '20 at 21:48
  • You can always create a loop to implement your approach for variable number of names. – PM 77-1 Nov 24 '20 at 21:53
  • thanks for the suggestions. repeated values cannot work for me, because sometimes I need to give something a very little chance to get chosen and then I can't do it. about the array of weights, it works if I have few options, but later it becomes complicated for me, because if I have 99 names, and I want to change the weight of the 56th name then I need to manualy count to 56 twice so I know that I change the right value in the weights array – Stack error pro Nov 24 '20 at 21:53
  • 1
    https://stackoverflow.com/questions/8435183/generate-a-weighted-random-number – epascarello Nov 24 '20 at 22:00

1 Answers1

1

You wish to make your code look better and be more scalable? If so, this answer will help you.

//dog names and chances
var NAMES = [
    {
        name: "Scafy",
        chance: 0.2
    },
    {
        name: "Shimshon",
        chance: 0.1
    },
    {
        name: "WoofWoof",
        chance: 0.5
    },
    {
        name: "Mitzy",
        chance: 0.1
    },
    {
        name: "AnotherDogName",
        chance: 0.1
    }
]

//In chances dont add up to 1
var maxChance = 0;
for (let i = 0; i < NAMES.length; i++) {
    maxChance += NAMES[i].chance;
}



function choose() {
    //to make chance range fair.
    var random = Math.random() * maxChance

    var name;
    //keeps track of were one is in the chancing
    let randomTrack = 0;

    //chancing
    for (let i = 0; i < NAMES.length; i++) {
        randomTrack += NAMES[i].chance;
        if (random <= randomTrack) {
            name = NAMES[i].name;
            //stop when you dog got lucky
            break;
        }
    }

    return name;
}
Jaime Argila
  • 408
  • 3
  • 13
  • Thank you soooooooooooooo much! I'm gonna use this method for my project! I didn't know I can even make arrays that look like this it's amazing! for c# I would have to make a json for a similar format, won't I? – Stack error pro Nov 24 '20 at 22:13