简体   繁体   中英

random - adding bias to incorrect answers in a quiz (javascript)

I wanted to make a relatively simple algorithm, that isn't just randomly choosing a question. So for each question I have a value called numOfCorrect, when the user gets the answer correct it adds 1, if the user gets it wrong it subtracts 1. like this:

const questions = [
    {question: "what is 9 + 10?", numOfCorrect: -5 ...},
    {question: "what is the meaning of life?", numOfCorrect: -5 ...},
    {question: "how do I get a bias for the incorrect?", numOfCorrect: 0 ...},
    {question: "1 + 1 = 4?", numOfCorrect: 10 ...}

]

so if each numOfCorrect is 0, I would want each question to have an even chance of getting picked, so that's just picking a random question normally.

The questions will be sorted from the least numOfCorrect to the most. I don't want to just decrease the range to bias the first indexes. Instead I want the probability for the questions to increase or decrease based on the numOfCorrect value, so there should be a non zero chance for any of the questions to be picked.

I was thinking something like:

  • for a question with a negative numOfCorrect => 1 / questions.length * ( 1 + ( (1/question.numOfCorrect) * -1)), so for a value -5 it would be 0.25 * 1.2 which would be 0.3. So instead of 25% chance it would be 30%.

  • for a question with positive numOfCorrect. If numOfCorrect was 1, then it would be 0.25 * 0.9, 2 would be 0.25 * 0.8...

Problem is they won't add to 1 (obviously). I don't know what I'm doing, I'm no mathematician.

So main question. How can pick a random question and bias the ones with a lower numOfCorrect, that will preferably exponentially increase/decrease their probability of being picked as the value numOfCorrect increases/decreases??

  1. Generate a (positive) weight for each question with a formula based on numOfCorrect (no need to consider questions.length in the formula).

  2. Sum up the weights.

  3. Generate a random number between 0 and the sum of the weights.

  4. Loop over the questions and pick one like this:

// randomValue is between 0 and the sum of the weights

let totalWeightSoFar = 0;
for (let i = 0; i < questions.length; i++) {
    let question = questions[i];
    if (randomValue >= totalWeightSoFar && randomValue < totalWeightSoFar + question.weight) {
        // found it!
        return question;
    }

    totalWeightSoFar += question.weight;
}

UPDATE:

Tes, it does mean that the weights can't be negative.

Imagine that you put sheets of papers of different sizes and different colors next to each other. Then toss a coin so that it lands on a perfectly-random spot in the area covered by the papers.

The chance of the coin landing on a specific color is proportional to the size of the paper of that color compared to the sum of the sizes of all the papers together (ie the total area covered by papers).

For example, if the area is comprised of a blue paper and a red paper twice its size - then the blue would cover 1/3 of the area, and the red would cover 2/3. The chance of the coin landing on blue would be 1/3 (ie ~33%).

Similarly, if your array has two questions, and one is assigned a weight of 7 (I'm just giving an arbitrary number), and the other is assigned a weight of 14 - the chances of the random number "falling" between 0 and 6 would be ~33%, and the chances of it falling between 7 and 20 would be ~66%).

How "sensitive" the weight is and whether it's affected by the number of questions depends on how you calculate it. This just depends on your requirements.

For example, you could define the weight as 100 + numOfCorrect . In such case, if all questions where answered correctly the same number of times - the weights would be equal, and the coin would have the same probability of landing on any of the questions.

BTW, if it simplifies your calculation logic, you could allow negative weights, but just offset all weights by the absolute value of the smallest weight afterwards. Eg if you end up with weights [ 2, -37, 84, -12 ] , then you find the minimum (ie -37 ) and add it to each of the weights, resulting in [ 39, 0, 121, 25 ] . Then you sum up these weights and run the loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM