1

Sounds simple enough...but I've been plugging away at this, trying to find the one and all solution.

For a range of numbers, say 1-12, I want to generate a random sequence within that range, and include 1 and 12.

I don't want duplicate numbers though.

So I would want something like this - 3,1,8,6,5,4 ..and so on, every number from 1-12.

Then I want to put these random numbers into an Array and use that array to 'randomly' select and display some items (like inventory pulled from database) on a jsp page.

The problem with what I've tried thus far, is that there are a lot of duplicate numbers being generated...or, not ALL of the numbers are chosen.

Is there a simple solution to this problem?


Edit

Test#1 using Collections and shuffle() method -

ArrayList<Integer> list = new ArrayList<Integer>(10);
for(int i = 0; i < 10; i++)
{
  list.add(i);
}
Collections.shuffle(list);

String[] randomNumbers = (String[])list.toArray();

for(int i = 0; i < 10; i++)
{
  out.print(randomNumbers[i]+"<br>");
}

The result was a sequence with duplicate values -
chose = 3
chose = 8
chose = 7
chose = 5
chose = 1
chose = 4
chose = 6
chose = 4
chose = 7
chose = 12

Test #2 - using Random math class

int max = 12;
int min = 1;

int randomNumber = 0;

String str_randomNumber = "";

for(int i=0; i<10; i++) {
    //int choice = 1 + Math.abs(rand.nextInt(11));
    int choice = min + (int)(Math.random() * ((max - min) + 1));

    out.print("chose = "+choice+"<br>");
}

The result was just like using Collections.shuffle().

katura
  • 2,177
  • 14
  • 39
  • 48
  • since the range is 1-12, one can expect a few duplicates. care to show us how you randomize them? – asgs Mar 07 '11 at 20:33
  • @asgs - edited post to add some of the code I've tried – katura Mar 07 '11 at 20:45
  • @katura, like i told 1-12 is a very small range and there will be duplicates whatsoever. what you can do is check to see if the next random number is already generated and if so, discard it and proceed to generate again until it's all done. – asgs Mar 07 '11 at 20:48
  • 2
    The version Test#1 works fine with me (after exchanging String[] by Object[]) and did not yield any duplicates. – Howard Mar 07 '11 at 20:50
  • @Howard - I did the same change as you, replacing String[] with Object[], and that is when it worked correctly, without duplicates. Thank you for bringing this to my attention. – katura Mar 07 '11 at 21:07
  • This has been asked **many times** before: e.g. http://stackoverflow.com/questions/196017/unique-random-numbers-in-o1 http://stackoverflow.com/questions/3395911/how-to-have-unique-random-number – Stephen C Mar 07 '11 at 22:10
  • 1
    Your test #1 would have had to throw an exception when run. Somehow that was swallowed and you wound up still looking at old output. Are you running this inside some kind of web app (I notice the "
    "?) It'd be a lot better to just run directly from the command line.
    – Kevin Bourrillion Mar 09 '11 at 15:19

6 Answers6

3

You can fill an array with all values from 1 to 12 and then shuffle them (see e.g. Why does Collections.shuffle() fail for my array?)

Community
  • 1
  • 1
Howard
  • 38,639
  • 9
  • 64
  • 83
2

You can put all numbers from 1 to 12 in order into array and then use some shuffling algorithm to randomize the order of them e.g. http://www.leepoint.net/notes-java/algorithms/random/random-shuffling.html.

Andrey Adamovich
  • 20,285
  • 14
  • 94
  • 132
  • I followed the link in your post, and that method gives me the results I wanted. I wish I could mark your answer as 'correct' as well! – katura Mar 07 '11 at 21:08
0

Random number generation allows for duplications. If you want a range of random numbers without duplication, I suggest the following:

  1. Generate a random number (I will refer to this a numberX).
  2. Add to a Set object.
  3. Check the size of the Set object, if it is the desired size, you are done. If it is smaller than the desired size, goto step 1
DwB
  • 37,124
  • 11
  • 56
  • 82
  • This would be useful if he wanted fewer than n numbers from the range [m, m+n). Of course, use an order-preserving set like LinkedHashSet. – Kevin Bourrillion Mar 09 '11 at 15:18
0

If you are using MySQL or SQLLite as your database you can do this randomization at the SELECT query level by using ORDER BY RAND() for restricting to 1-12 you can put a where clause WHERE ID >=1 AND ID <=12 ORDER BY RAND()

guru
  • 667
  • 5
  • 13
0

This is a utility method for creating a random Integer number :

public static int randomInteger(int min, int max) {
    Random rd = new Random();
    return rd.nextInt((max - min) + 1) + min;
}

This is an algorithm that always produces a unique Set of integers:

public static Set<Integer> makeRandomSet(int howManyNumber, int startNumber, int endNumber){
    Set<Integer> integerSet = new HashSet<>();

    boolean couldBeAdded = false;
    for(int i=0; i< howManyNumber; i++) {
        while (!couldBeAdded) {
            Integer randomInt = randomInteger(startNumber, endNumber);
            couldBeAdded = integerSet.add(randomInt);
        }

        couldBeAdded = false;
    }

    return integerSet;
}

We made use of add method return type to check the duplicate value within our Set.

And here is the test code:

public static void main(String[] args) {
    Set<Integer> randomSet = makeRandomSet(6, 1, 54);
    System.out.println(randomSet);
}

The output of the above code is 6 random unique integers number between 1 and 54

Mehdi
  • 3,795
  • 3
  • 36
  • 65
-1

You could just put all the numbers you want in a List and then order the List randomly and then convert the randomly ordered list to an array, e.g.

List<Integer> list = new ArrayList<Integer>();

for (int i = 1; i <= 12; i++) {
    list.add(i);
}

Collections.sort(list, new Comparator<Integer>() {

    @Override
    public int compare(Integer o1, Integer o2) {
          return Math.random() > 0.5 ? 1 : -1;
    }
);
Integer[] array = list.toArray(new Integer[list.size()]);
brent777
  • 3,369
  • 1
  • 26
  • 35