-1

I am working on a simple project and I have this method:

public int generatePeople(float luck, int min, int max) {
    SecureRandom sr = new SecureRandom();
    int people = 0;
    // generate random people
    return people;
}

I would like to generate an amount of people between min and max, but the number of people increases or decreases depending on the variable luck, this should be similar to a Gaussian but I have no idea on how to do it on Java.

Depending on the value of luck the center of the interval will be different for example having luck = 0.5f it will be more likely to have values around (min + max)/2 (the center of the interval) while having a luck = 0.25f or luck = 0.75f will move the center of values on the left side (min + max)/4 or on the right side 3*(min+max)/4 meaning that it will be more likely to have values from the left side or the right side.

DRE
  • 263
  • 8
  • 35
  • 1
    `depending on the variable luck,` how exactly it should depend? – Iłya Bursov Jun 10 '21 at 19:09
  • @IłyaBursov The higher luck is the higher is the chance of having a high value on people for example – DRE Jun 10 '21 at 19:14
  • https://www.tutorialspoint.com/java/util/random_nextgaussian.htm ? – spi Jun 10 '21 at 19:15
  • generate a random number with the range of 0-luck, then generate another random number within the range of min-max, then add them together. check if the new value is bigger than max. if it is return max, if it isn't return the value – Shazniq Jun 10 '21 at 19:16
  • @spi I have seen it, but I don't understand how that should help me – DRE Jun 10 '21 at 19:16
  • @Shazniq I am sorry I might have not entirely understood what you have suggested, but that doesn't seem to use the luck variable – DRE Jun 10 '21 at 19:18
  • @AndreaDattero int luckRandom = random number 0-luck, int randomWithoutLuck=random number min-max, int randomWithLuck = luckRandom+randomWithoutLuck, if randomWithLuck > max return max, else return randomWithLuck – Shazniq Jun 10 '21 at 19:23
  • 1
    What does the value of `luck` mean? E.g. very bad luck you mean you always get `min` back, but what value of `luck` is "bad luck"? `0`? `-Infinity`? Similarly, very good luck means always get `max` back, but is that `1` or `100` or `+Infinity` or something else? – Andreas Jun 10 '21 at 19:32
  • @Andreas Both definitions you have said are good, I use 0 for bad luck and 100 for top luck – DRE Jun 10 '21 at 20:47
  • Then you should say that in the question. What does 50 then mean? All values between `min` and `max` are equally likely? 0 means always return `min`, and 100 means always return `max`? Then what does 25 mean? Please explain, in the question, how you expect the value of `luck` to affect the result. – Andreas Jun 10 '21 at 22:51
  • @Andreas I have added the details in the question, if you have any other questions on what I mean please ask me, thanks for the support! – DRE Jun 11 '21 at 13:53

2 Answers2

1

We can generate a random int number from min to max with

int randomInt = sr.nextGaussian() * (max - min) + min;

Then to add the influence of luck we can add the shift value. Considering luck a float number from 0 to 1 and that if luck is 0.5 it has to have no influence, we can achive this with something like this:

int people = randomInt + (luck - 0.5f) * (sr.nextGaussian() * (max - min) + min);

However, by adding something we can exceed min or max value. To avoid that we can then add a check for exceeding and assign min or max value in case of exceeding:

people = Math.min(people, max);
people = Math.max(people, min);
Noughtmare
  • 9,410
  • 1
  • 12
  • 38
  • Rejection sampling (rejecting out-of-range values and trying again) might be better than clamping out-of-range values. Otherwise, the minimum and maximum values might occur too frequently. – Peter O. Jun 11 '21 at 16:58
0

Assuming the min,max range is inclusive there are span = max-min+1 possible values. One approach would be define a Gaussian Probability Density Function (PDF), centered on luck * span, with a sigma of, for example, span/2 - you could vary this to alter the tightness of the distribution around the center.

You'd then use the PDF to calculate a 'weight' for each possible value within the range of span - values near the center of the distribution will get a higher weight - and use a standard technique for selecting a random value within a range, where each value has an associated weight.

Here's some Java code to illustrate.

static int generatePeople(double luck, int min, int max) 
{
    int span = max - min + 1;
    
    double mean = luck * span;
    double sigma = span / 2;
    
    double[] weights = new double[span];
    double totWeight = 0;
    for(int i=0; i<span; i++) 
    {
        weights[i] = pdf(mean, sigma, i+0.5);
        totWeight += weights[i];
    }
    
    double rnd = Math.random()*totWeight;
    for(int i=0; i<span; i++) 
    {
        if(rnd < weights[i]) return min+i;
        rnd -= weights[i];
    }   
    
    return max;
}
    
static double pdf(double mean, double sigma, double x)
{
    double e = (mean - x) / sigma;
    return Math.exp(-(e*e)/2)/(sigma*Math.sqrt(2*Math.PI));
}

We can illustrate the behavior of this approach by generating a large number of values and examining the distribution between min and max for a given value of `luck'.

static void test(double luck, int min, int max)
{
    int[] score = new int[max-min+1];
    for(int i=0; i<1000*score.length; i++)
        score[generatePeople(luck, min, max)-min]++;
    for(int i=0; i<score.length; i++)
    {
        System.out.println(min+i + " : " + score[i]);
    }
}

Output:

test(0.5, 0, 9);

Gives:

0 : 786
1 : 878
2 : 1059
3 : 1110
4 : 1152
5 : 1162
6 : 1106
7 : 1020
8 : 962
9 : 765

While

test(0.25, 0, 9);

Gives:

0 : 1195
1 : 1236
2 : 1285
3 : 1284
4 : 1146
5 : 1078
6 : 904
7 : 771
8 : 610
9 : 491
RaffleBuffle
  • 5,396
  • 1
  • 9
  • 16