Click here to Skip to main content
15,884,388 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Dear All,

I have a Windows application for test. Where I have to select questions(items) randomly and it's selecting randomly but not all questions.

Whenever I select some questions randomly I'm saving that in a data-base, where some items get selected more than items which get select only 1s or twice.

I want to select items randomly but should be selected equally with one another.

For example, if I have 100 items and I selected items randomly 10 times, means, all items should be selected equally.

What I have tried:

List<QuestionInfo> allQuestions = QuestionController.Instance.GetByOutcome(outcome.ID).ToList();
                    List<QuestionInfo> outcomeQuestions = allQuestions.Cast<QuestionInfo>().ToList();

                    int outcomeQuestionNumber = (outcome.PercentageOfQuestions ?? 0) * module.TotalQuestions / 100;
                    if (outcomeQuestionNumber == 0)
                        notConsideredOutcomeList.Add(outcome.ID);

                    if (outcomeQuestions.Count < outcomeQuestionNumber)
                        throw new Exception("Something wrong in generating questions. Not enough questions in Outcome :" + outcome.NameEN);

                    List<QuestionInfo> easyQuestions = outcomeQuestions.FindAll(item => item.DifficultyLevel.DifficultyLevel == DifficultyLevel.Easy).ToList();
                    List<QuestionInfo> mediumQuestions = outcomeQuestions.FindAll(item => item.DifficultyLevel.DifficultyLevel == DifficultyLevel.Medium).ToList();
                    List<QuestionInfo> hardQuestions = outcomeQuestions.FindAll(item => item.DifficultyLevel.DifficultyLevel == DifficultyLevel.Hard).ToList();

                    int easyQuestionsNumber = outcomeQuestionNumber * module.ModuleQuestionDifficultyLevel.FindAll(item => item.DifficultyLevel == DifficultyLevel.Easy).FirstOrDefault().PercentageOfQuestions / 100;
                    int mediumQuestionsNumber = outcomeQuestionNumber * module.ModuleQuestionDifficultyLevel.FindAll(item => item.DifficultyLevel == DifficultyLevel.Medium).FirstOrDefault().PercentageOfQuestions / 100;
                    int hardQuestionsNumber = outcomeQuestionNumber * module.ModuleQuestionDifficultyLevel.FindAll(item => item.DifficultyLevel == DifficultyLevel.Hard).FirstOrDefault().PercentageOfQuestions / 100;

                    if (easyQuestions.Count < easyQuestionsNumber)
                        throw new Exception("Something wrong in generating questions. Not enough easy questions in Outcome :" + outcome.NameEN);

                    if (mediumQuestions.Count < mediumQuestionsNumber)
                        throw new Exception("Something wrong in generating questions. Not enough medium questions in Outcome :" + outcome.NameEN);

                    if (hardQuestions.Count < hardQuestionsNumber)
                        throw new Exception("Something wrong in generating questions. Not enough hard questions in Outcome :" + outcome.NameEN);

                    for (int count = 0; count < easyQuestionsNumber; count++)
                    {
                        int randomIndex = new Random().Next(0, easyQuestions.Count - 1);
                        questions.Add(easyQuestions[randomIndex]);
                        easyQuestions.Remove(easyQuestions[randomIndex]);
                    }

                    for (int count = 0; count < mediumQuestionsNumber; count++)
                    {
                        int randomIndex = new Random().Next(0, mediumQuestions.Count - 1);
                        questions.Add(mediumQuestions[randomIndex]);
                        mediumQuestions.Remove(mediumQuestions[randomIndex]);
                    }

                    for (int count = 0; count < hardQuestionsNumber; count++)
                    {
                        int randomIndex = new Random().Next(0, hardQuestions.Count - 1);
                        questions.Add(hardQuestions[randomIndex]);
                        hardQuestions.Remove(hardQuestions[randomIndex]);
                    }

                    processedQuestions.AddRange(easyQuestions);
                    processedQuestions.AddRange(mediumQuestions);
                    processedQuestions.AddRange(hardQuestions);


Can anyone please help me.

Thanks
Posted
Updated 17-Jun-19 22:05pm

The whole idea of random numbers is that they don't "select equally" as that forces a bias onto the stream of numbers. When you read random numbers between 0 and 9, the odds of a 5 on the first number is the same as the odds of a 5 on the second number regardless of the value selected as the first number. The same thing applies to the third, the fourth, the fifth, ... previous values are irrelevant, they do not affect the next number.

If you want to prevent duplicates, you need to keep a record yourself of which numbers have been selected; then use that to eliminate them from the next draw.

Oh, and do yourself a favour: create a single Random instance as a private static variable and use that instead of creating a new one each time you want a random value: they are initialised from the system tick count when the instance is created, so new instances can easily repeat the same value sequence if created quickly, particularly on modern, fast machines.
 
Share this answer
 
v2
Comments
Maciej Los 18-Jun-19 4:17am    
5ed!
I'm not entirely sure what you mean by "equally".

If you mean that you want a uniform distribution of the random values (i.e. every value has the same chance of happening):

Random is uniformly distributed. This already happens. But as OriginalGriff said, you better re-use one Random instance instead of creating a new one every time.

If you mean that you want to obtain all values in a certain collection, but in a random order:

  1. Create a list of indices, like this:
    C#
    List<int> indices = Enumerable.Range(0, 100).ToList(); // 100 is the count, replace it by the value you need
  2. Shuffle the list[^].
  3. When you want a new value from your collection, obtain it based on the next index in indices (so keep track of where you are in that list).
 
Share this answer
 
v5
Comments
Maciej Los 18-Jun-19 4:17am    
5ed!
Thomas Daniels 18-Jun-19 4:20am    
Thank you!
Quote:
I want to select items randomly but should be selected equally with one another.

the 2 ideas are mutually exclusive, you can't have both at the same time. Random imply not equal.
Your question fall in category 'Shuffling a deck of cards' and remember between sessions.
Shuffling - Wikipedia[^]
Basically, with a deck of cards:
Draw randomly a card in the desk of 52, then swap it with card 52.
Draw randomly a card in the first 51 cards, then swap it with card 51.
Draw randomly a card in the first 50 cards, then swap it with card 50.
and repeat until last card.
Then save the order of cards to keep track between sessions.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900