0

Ok, so the scenario is, I want to generate a list of 4 distinct random numbers which will represent 4 random choices for a quiz application. One of the 4 random choices will be the correct answer, so we will already know the index of the correct choice. This correct index or number must be included in the random number list.

For example: Consider that we have an array of length 100, containing string values representing 100 choices for a question, and the index of correct choice is 45. Now we want 4 random choices for this question including the index 45, so that the index list will be something like {2, 91, 45, 17}. Also the list shouldn't contain duplicate numbers.

Any idea how to achieve this in Java ?

3
  • You could get three random numbers as described in stackoverflow.com/questions/363681/… and add the "right index" to your array of possible answers. To avoid to have the right answer always at the same position you could shuffle the array. Commented Jan 22, 2017 at 10:09
  • Generate 3 random number with min 0 and max array size-1 and check if the given value is already picked. 3 because you know your answer. we did something similar this way. Commented Jan 22, 2017 at 10:10
  • Possible duplicate of How to generate 6 different random numbers in java Commented Jan 22, 2017 at 10:13

3 Answers 3

4

For Java 6 and newer:

final int maxNumber = 100;
final int numbersToGenerate = 4;
final int correctAnswer = 45;

Set<Integer> possibleAnswers = new HashSet<>();
Random random = new Random();

// add correct answer
possibleAnswers.add(correctAnswer);

// add as much random answers as needed, the usage of a set prevents duplicates
while(possibleAnswers.size() < numbersToGenerate) {
    possibleAnswers.add(random.nextInt(maxNumber));
}

// convert set to list and shuffle it
List<Integer> answers = new ArrayList<Integer>(possibleAnswers);
Collections.shuffle(answers, new Random(System.nanoTime()));

For Java versions below 6 you have to write your own shuffle method, because Collections.shuffle was introduced in Java 6, as far as I know.

I first suggested to use the random api of Java 8, but found an bug in my idea. If the array of generated random numbers contains the correct answer it will not work. For your understanding:

NOT WORKING!!!

final int minNumber = 1;
final int maxNumber = 100;
final int numbersToGenerate = 3;

final int[] ints = new Random().ints(minNumber, maxNumber)
.distinct().limit(numbersToGenerate).toArray();

List<Integer> possibleAnswers = asList(ints);
possibleAnswers.add(correctAnswerIndex);
Collections.shuffle(possibleAnswers, new Random(System.nanoTime()));

NOT WORKING !!!

Sign up to request clarification or add additional context in comments.

7 Comments

According to your answer it works in Java 8. You need to describe what will you do in older Java, there are situations when there is a legitimate reason to use older Java. Also, you need to generalize, the number of possible answers is not necessarily constant. As you can see, your answer has several shortcomings, but that is not a reason to down-vote it, as it is helpful in the limited use-cases it can be used in.
Anton your answer should be as general as possible. You should never assume that the current reader AND the future readers are ALL using Java 8. Your solution is good for a small number of use-cases. People can use it if its limited number o use-cases applies to them. If not, then they need something else. You need to edit your answer and make your code more general, preferably with variable number of possible responses and a solution for viewers using older Java. Unless you do that, your answer is incomplete.
Your answer assumes that the number of elements is 100. It shuffles all the items, so if the number of attributes get bigger and the operation is repeated in a cycle many times, then your code will be slow and in a multithreaded environment it will not scale well. The answer is not explained at all, it just copies a code which is not understandable to the op (that's why he asked) and leaves a mystery to the users about what happens. So this answer is bleeding from 1000 wounds.
Oh thats nice. I never knew Random was bound to the streaming api as well. Learned something new today
Hi Anton, I could be wrong, but I guess this code doesn't generate a random number list that contain distinct numbers. It may have numbers that could be duplicates.
|
1

This class could help you

public class RandomQuiz {

    //The number of possible answers
    private int size;
    //The number of possible indexes
    private int n;
    //The correct index
    private int correct;

    //Constructor
    public RandomQuiz(int size, int n, int correct) {
        this.size = size;
        this.n = n;
        this.correct = correct;
    }

    //Returns size number of shuffled random indexes
    public int[] getRandomIndexes() {
        //The result set
        int[] result = new int[size];
        //We start with the correct index in the first place, so random values will be entered starting from the second place
        int index = 1;
        //First thing's first
        result[0] = correct;
        Random random;
        while (index < size) {
            //We always decrease the number of seeds
            random = new Random(n - index);
            //Getting a random value
            int randomized = random.nextInt();
            //Ensuring the numbers are not duplicate
            for (int i = 0; i < index; i++) if (randomized >= result[i]) randomized++;
            result[index++] = randomized;
        }
        //Randomize where correct will be at the end:
        random = new Random(size);
        int newIndex = random.getNextInt();
        //If the new index of correct is bigger than 0
        //than swap it with the item located on newIndex
        if (newIndex > 0) {
            result[0] = result[newIndex];
            result[newIndex] = correct;
        }
        return result;
    }
}

EDIT:

In a private chat with Anton he told me that some parts are unclear, namely:

  • why did I decrease the number of seeds
  • why did I increase randomized in a cycle

The number of seeds is decreased since we can use any number once maximum. If the seed was 100, then after the first item was chosen, it becomes 99 and so on. To answer the second question: if 45 was chosen and then a number at least of 45 is chosen, then we need to add 1 to that number to cope with the gap left when we have chosen 45. If there were some numbers chosen and we choose a new number, then we need to add to that number the number of gaps below it, that is, the number of already chosen smaller or equal numbers to cope with all the gaps.

Note that nothing was taken personally, I would leave the kind of comments I have left here if somebody else's correct answer was down-voted as well. I am not against my answer being down-voted, but against down-voting correct answers in general.

8 Comments

far to complicated and needs to many lines of code. As proven the amount of bugs is not rising with the complexity of the code but with the lines of code!
@Anton "to complicated" is not a reason to down-vote an answer. Down-vote means that the answer is unhelpful. So, please tell me how was my answer unhelpful and suggest improvements. Or revoke your down-vote.
Well in my opinion we should not give just an answer "that works", furthermore we should give a good answer to help people improve their programming. And in my eyes is a too complicated solution/answer not helpful for the improvement of development skills. And in addition to that i would like to see a bit more explanation that just pasting a class.
@Anton, this answer shows the algorithm, so it IS improving the programming abilities of readers. And it is perfectly illegitimate to down-vote an answer which is solving the problem. Your criticism is welcome, but unless you can show the shortcomings of this answer (a bug, for example) you are being incorrect in down-voting it. Also, my answer is explained in comments (adding to the "many lines"), not just a copy-paste as in your answer.
@Anton you are saying that the code is complicated for you. Can you tell me which part is difficult to understand so I can elaborate it? I will be a gentleman and will not assume that the reason of your down-vote was to improve the chances of your answer to be accepted. I have no problem with your answer being accepted if its quality is improved. Yet, as matters stand right now, my answer was given earlier, it should work in many environments, it is explained in the comments. Your answer lacks all these qualities, yet you down-vote mine.
|
0

I wrote a full program based on your needs. However please take a look at what I am doing. With just a little context, this is what I created:

     // initialize a random object once.
     Random random = new Random();
     // the question
     String question = "With what letter does the name start of the new president of the USA?";
     // here are some basic answers
     String[] answers = new String[] {
      "a",
      "b",
      "c",
      "d",
      "e",
      "f",
      "g",
      "h",
      "i",
      "j",
      "k"
     };
     // you already know the correct index of the array above, in this case it's d
     int index = 3;
     // this array will contain four answers, including correct one!
     String[] four = new String[4];
     // get answer index, we will place correct value in that index
     int answerIndex = random.nextInt(four.length);
     // now lets pick 4 answers!
     for (int i = 0; i < four.length; i++) {
      // we are at the answer index!
      if (i == answerIndex) {
       four[i] = answers[index];
       continue;
      }
      int randomIndex = random.nextInt(answers.length);
      for (int j = 0; j < four.length; j++) {
       // we got duplicate here!
       if (answers[randomIndex].equals(four[j])) {
        randomIndex = random.nextInt(answers.length);
        // redo this current iteration
        j = j - 1;
       }
      }
      four[i] = answers[randomIndex];
     }

Output:

e, c, d, h
g, d, d, h
d, g, e, f
d, f, b, i
g, d, a, b
c, d, g, b
h, d, e, k
e, f, d, c
k, d, e, h
i, d, e, d

It will help if you explain where you are using it for, as well as a short demonstration at what you have already coded.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.