3

I do have the following code for taking random int numbers

for (int i=1;i<=5;i++) {
  int rand= new Random().nextInt(10);
  Log.d("Ramdom number", String.valueOf(rand));
}

The problem is that I dont want random numbers to be repeated, mean when I run this code it gives to me 5 numbers but two of them at least repeats. Any advice?

CharlesB
  • 86,532
  • 28
  • 194
  • 218
Daler
  • 1,205
  • 3
  • 18
  • 39

8 Answers8

7

For a small range of numbers to choose from, this should do the trick:

ArrayList<Integer> numbers = new ArrayList<Integer>();
for (int i = 0; i < 20; ++i) {
    numbers.add(i);
}
Collections.shuffle(numbers);
for (int i = 0; i < 5; ++i) {
    Log.d("Random number", numbers.get(i).toString());
}
reima
  • 2,076
  • 15
  • 22
  • Is `Collections.shuffle()` included in the libraries that come with the stock Java install? – Tony Ennis May 28 '12 at 13:55
  • @TonyEnnis: It is part of Java SE: http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#shuffle%28java.util.List%29 – reima May 28 '12 at 14:00
  • Thanks, that's good to know. I like your solution the best, then. – Tony Ennis May 28 '12 at 14:04
  • Yes, thank you very much. It works, I did tests. Im wondering how good is this? Is there any possibility of being repeated numbers?? – Daler May 28 '12 at 14:07
  • @Daler: This algorithm guarantees that no number is repeated. It works like in the lottery: numbered balls are shuffled and then taken out of the bin one by one. – reima May 28 '12 at 14:16
  • Thank you. I read it carefully and got how it works. Thanks. Seems the best solution in my case. – Daler May 28 '12 at 14:19
1

The problem is that you are creating a Random object within the loop. If the loop is a 'tight', as in this case, the Random object will be seeded with the same value. Moving the Random object initialization outside the loop should do the trick.

Random r = new Random();
for (int i=1;i<=5;i++) {
            int rand= r.nextInt(10)

            Log.d("Ramdom number", String.valueOf(rand));  

    }

EDIT:

This should work (at least it did for me)

public static Integer[] getRangedInt(int maxRange, int numCount)
{
    if (maxRange < numCount)
    {
        throw new Exception("maxRange cannot be smaller than numCount");
    }

    Set<Integer set = new HashSet<Integer>();
    Random r = new Random();
    while (Set.size() < numCount)
    {
        int random = r.nextInt(maxRange);  
        while (!set.add(random))
        {
            random = r.nextInt(maxRange); 
        }
    }

    return set.toArray(new Integer[set.size()]);
}
npinti
  • 51,780
  • 5
  • 72
  • 96
1
final int maxnumbers = 5;
final int maxvalue = 10;
final Random generator = new Random();
Set<Integer> numbers = new HashSet<Integer>();
while(numbers.size() < maxnumbers){
    numbers.add(random.nextInt(maxvalue));
}

After this loop you should have maxnumber non-repeating random numbers between 0 and maxvalue in the set numbers. You have to watch out so you don't get too many iterations when using this method, i.e. generating 9999 non-repeating numbers out of 10000 would probably take a long time.

Another more scalable version would be to have a list of numbers:

List<Integer> numbers = new ArrayList<Integer>();
for(int i = 0; i<maxvalue; i++){ numbers.add(i); }
Collections.shuffle(numbers);
List<Integer> randomnums = numbers.subList(0, maxnumbers);
Jave
  • 31,598
  • 14
  • 77
  • 90
0

So what you're looking for isn't a list of random numbers, it's a list of 30 numbers randomly ordered.

One way is to generate a list of all possible values, then order them randomly, then peel them from the front of the list as needed. Here's some pseudocode:

for(int i=1; i<=30; i++) {
    double r = rand();
    while (null != aTreeSet.get(r)) r = rand();
    aTreeSet.put(r, i);
}

where rand() returns some random value (not the 1-30 you seek, that's i) perhaps between 0 and 1 and aTreeSet is what you think.

The loop prevents sadness in the unlikely event of a dup being returned by rand().

To use this, pull values from aTreeSet in sorted order.

edit - Gross solution

Another way is to generate the 1-30 value, and if it isn't already in a "I have seen this" Set, add it and return the value. if it is there, generate a new random number. Repeat until an unused number is discovered. This performs poorly, relatively speaking, for the last few values. For 30 values on modern processors, it will get done in milliseconds, of course. If your max value was 1,000 instead of 30, I'd start getting concerned.

Tony Ennis
  • 12,000
  • 7
  • 52
  • 73
  • If you want to know if a number has been generated, you have to be able to check it, and that requires data structures. I'll post another solution but it's gross. – Tony Ennis May 28 '12 at 13:45
0

I think you need a SET of random numbers. This hint should suffice.

If not, then please comment.

dharam
  • 7,882
  • 15
  • 65
  • 93
0

You can maintain one list of generated numbers

boolean flag=false;
Vector<int> vec = new Vector<int>();
for (int i=1;i<=5;i++) {
        flag=false;
        int rand= r.nextInt(10);
        for(int j=0;j<vec.size();j++)
        {
             if(vec.get(j)==rand)
             { 
                flag=true;
                break;
             } 
        }
        if(flag)
        {
            continue;
        } 
        else
        {
             Log.d("Ramdom number", String.valueOf(rand));
             vec.add(rand);

        }
}

You can maintain a vector of generated numbers and check

Is that number already generated then generate new one

else display this number

MAC
  • 15,799
  • 8
  • 54
  • 95
0

What you want is a random combination, use a Hash table to avoid repetitions

From the top of my head the code should be something like:

    Ramdom r = new Random();
    Hashtable<Integer, Integer> h = new Hashtable<Integer, Integer>();
    while( h.keys().size() < 5 ) {
            int i = r.nextInt(10);
            h.put(i,i);
    }
    Integer[] k = (Integer[]) h.keySet().toArray();

The line

    h.put(i,i);

just overrides the value if it is repeated, so only different drawn numbers will have entries in the hash table.

ilomambo
  • 8,290
  • 12
  • 57
  • 106
  • 1
    I don't think this is accurate - hash tables to not order values randomly - there is a well-defined algorithm. When you pull the values out, there will be a bias. I'd replace the `h.put(i,i)` with `h.put(aRandomValue(), i)` – Tony Ennis May 28 '12 at 13:59
  • @TonyEnnis The very definition of a hash table is that keys are unique, and they have no predefined order :::: This code just chooses 5 different numbers out of 10, if you want you can order them aftwerwords with any sort algorithm you like. – ilomambo May 28 '12 at 14:03
  • As far as I know, a hashtable is made for efficient putting and fetching of values, not random ordering. Do you think it is a good idea to rely upon a _side-effect_ of black-box code? – Tony Ennis May 28 '12 at 14:17
  • @TonyEnnis Look up Hash table in any university text book. the efficiency comes from having unique keys that can be accessed in O(1). The writer of the post did not ask for a specific order, he just wants 5 different random numbers between 1 and 10 – ilomambo May 28 '12 at 14:23
-1

You can save your generated numbers in a Set and use the random number only if it is not in the set

Random r = new Random();
    Set<Integer> generatedNumbers = new HashSet<Integer>();
    for(int i = 1;i<=5;i++)  {
      int rand = r.nextInt(10)
      if (!generatedNumbers.contains(rand)) {
        Log.d("Ramdom number", String.valueOf(rand));
        generatedNumbers.add(rand);
      } 
    }  
Adelin
  • 18,144
  • 26
  • 115
  • 175
  • Works but won't scale (though the OP says the max value was only 30) Your code has a bug, by the way. On a duplicate, no value is printed. So it doesn't print dups (thumbsup) but in also won't print 5 values in that case. – Tony Ennis May 28 '12 at 13:50