Search code examples
javaarraysrandomprobability

Using a number array to adjust the chances of a specific return value?


I am creating a method called getRandomLetter() that I want to randomly return a single letter from the English alphabet. I want the method to be more likely to return a letter with a higher number associated with it.

I have two arrays. One has chars for each letter in the alphabet. The second has doubles, each representing the chances, that the letter with the same index, in the other array, will be the letter returned by my method.

I am trying to get the method to have different chances to return different letters according to the values in the arrays.

Unfortunately, my method only returns z and y.

How can I make getRandomLetter() return specific letters/chars according to the numbers I specify for each?

My Code Example:

public class MCVE {
    // each letter's frequency is represented in the next array by
    // the double value at the same index as the letter
    final private static char[] CharArr = "abcdefghijklmnopqrstuvwxyz".toCharArray();
    // Holds each letter's percentage-chance to be chosen
    // For Example: 0.1 is equal to 10%
    // All-together, they add up to 1.0
    final private static double[] DoubleArr = new double[] {
            0.087248322147651, 0.035722017752760335, 0.08010391859709894,
            0.05520675470881143, 0.046763368694522627, 0.018618748646893266,
            0.028144620047629357, 0.021866204806235117, 0.016020783719419788,
            0.07101104135094176, 0.06040268456375839, 0.08703182507036156,
            0.10002164970772895, 0.027711625893050443, 0.009742368478025547,
            0.021433210651656202, 0.0012989824637367395, 0.0458973803853648,
            0.07988742151980949, 0.05260878978133795, 0.0015154795410261962,
            0.022515696038103484, 0.009309374323446633, 0.0012989824637367395,
            0.011690842173630657, 0.006927906473262611};

    private static char getRandomLetter() {
        double randomDouble = ThreadLocalRandom.current().nextDouble(0.0, 1.0);

        char retVal = ' ';
        // subtract each value in DoubleArr from randomDouble until,
        // randomDouble would be < 0, then return the char that is
        // associated with that double
        for(int i = 0; i < CharArr.length; i++) {

            double subtract = DoubleArr[i];
            if (randomDouble - subtract <= 0.0)
                retVal = CharArr[i];
            else
                randomDouble -= subtract;
        }
        return retVal;
    }

    public static void main(String[] args) {
        // get a large sample of chars to test thoroughness
        char[] sampleChars = new char[1000];
        for(int i = 0; i < 1000; i++) {
            sampleChars[i] = getRandomLetter();
        }

        // print 10 characters per line
        int ct = 0;
        for(char c: sampleChars) {
            System.out.print(c + " ");
            ct++;
            if(ct == 10) {
                ct = 0;
                System.out.println();
            }
        }
    }
}

Sample of what is returned:

z z z z z z z z z z

z z y z z y z z z z

z z y z z z z z z z

z y z z z z z z z z

z z z z z z z z z z

z z z z z z z z y y

z z z z z z z z z z

z y z z z z z z z z

z z z z y z y z z z


Solution

  • It seems you didn't "jump out" from the for loop when you get right answer. Maybe your getRandomLetter should be changed to :

    for(int i = 0; i < CharArr.length; i++) {
    
            double subtract = DoubleArr[i];
            if (randomDouble - subtract <= 0.0) {
                 retVal = CharArr[i];
                 break;
            }
            else
                randomDouble -= subtract;
        }