2

I'm currently creating an app and it will generate random numbers. So each time it will generate three numbers num1, num2 and num3. These number should not be duplicate. For example if num1 = 1 than num2 and num3 cannot be equal to 1. I've tried this code where it will display three different number ranging from 0-2. And its working. However I would want to generate random number ranging from 1-3, 2-4, 3-5 and so on. So how can I achieve this by using the code below. Please help me since I'm new to this. Thank you.

for(int i=0; i<images.length; i++)
{
        num[i] = (int)(Math.random()*3);

        if (i == 0)
        {
        if(num[i]== 0)
            images[i].setImageResource(R.drawable.zero);
        else if(num[i]==1)
            images[i].setImageResource(R.drawable.one);
        else
            images[i].setImageResource(R.drawable.two);
        }

        else
        {
            while (num[i] ==  num[i-1] || num[i] == num[0] )
                num[i] = (int)(Math.random()*3);


        if(num[i]==0)
            images[i].setImageResource(R.drawable.zero);
        else if(num[i]==1)
            images[i].setImageResource(R.drawable.one);
        else
            images[i].setImageResource(R.drawable.two);

        }
    }
SOFe
  • 7,867
  • 4
  • 33
  • 61
amln_ndh
  • 617
  • 2
  • 9
  • 30
  • 1
    Your question is not very clear, you must express it better. – Binoy Babu Jan 19 '14 at 05:42
  • I'm almost certain I've seen a duplicate of this. [This question](http://stackoverflow.com/questions/5224877/java-generate-random-range-of-specific-numbers-without-duplication-of-those-nu?rq=1) is also really close. When dealing with this, I'd actually subclass [Random](http://docs.oracle.com/javase/7/docs/api/java/util/Random.html), allowing injection/configuration changes. – Clockwork-Muse Jan 19 '14 at 05:42
  • As @Clockwork-Muse mentioned, you can [shuffle a list of values](http://stackoverflow.com/a/5224922/125562) from required range. – Basilevs Jan 19 '14 at 05:59

10 Answers10

10

Create a list if all numbers in the range, then shuffle the list:

List<Integer> numbers = new ArrayList<>();
// eg for range 3-5
for (int i = 3; i <= 5; i++)
    numbers.add(i);
Collections.shuffle(numbers);

Now use them in their new (random) order.

Unless your range is very large (millions) this will work fine.


Java8 version:

List<Integer> numbers = IntStream.rangeClosed(3, 5).boxed().collect(Collectors.toList());
Collections.shuffle(numbers);
Bohemian
  • 412,405
  • 93
  • 575
  • 722
1

Well, you could store your numbers an an ArrayList<>. Every time you generate a random number, see if the ArrayList<> contains the number. If it does, generate another number and repeat the process.

Better yet, use a Set <>.

An SO User
  • 24,612
  • 35
  • 133
  • 221
1

I know it's late, but could be helpful for future reference. You can create your own custom Random class:

//Generates random integers without repetition between two given numbers both inclusive
public class Random {
    private int start;
    private int end;
    private Stack<Integer> numbers = new Stack<>();
    public Random(int start, int end){
        this.start = start;
        this.end = end;
    }
    private void loadNumbers(){
         for (int i=start;i<=end;i++){
                numbers.push(i);
            }
         Collections.shuffle(numbers);
    }
    public int nextInt(){
        if (numbers.empty()) loadNumbers();
        return numbers.pop();
    }
}

And use it like:

Random rand = new Random(1,20);
for(int i=0; i<100;i++){
    System.out.print(rand.nextInt()+ " ");
}
Addis
  • 2,480
  • 2
  • 13
  • 21
0

To get numbers ranging from 1-3, 2-4, 3-5, etc, change this

num[i] = (int)(Math.random()*3);

to this

num[i] = rand.nextInt(2) + 1 + i;

You'll need to import Random and add Random rand = new Random(); before using it.

LMNOP
  • 151
  • 6
0

The formula to generate random number in the range is :

    Random rn = new Random();
    int range = maximum - minimum + 1;
    int randomNum =  rn.nextInt(range) + minimum;

so in one line you can generate as like this

    int num1 = new Random().nextInt(3-1+1) + 1;
    int num2 = new Random().nextInt(4-2+1) + 1;
    int num3 = new Random().nextInt(5-2+1) + 1;

or

    num[i] = new Random.nextInt(range[i]) + 1 + i;

and then you can do your logic stuff to set the resource. Happy Coding :)

Vikas Rathod
  • 374
  • 2
  • 14
0

The best possible and most efficient way to generate and store unique numbers would be to create a HashSet that holds your data. Generate the number and then try to add it to the HashSet. If the add method returns false, then it means that the number already exists in the set and hence re-generate a number. The advantage of using this method over the ArrayList is that this has a time complexity of O(1) while using the contains() method (from ArrayList) would result in a time complexity of O(n) - efficiency decreases as size increases.

ucsunil
  • 7,378
  • 1
  • 27
  • 32
  • 1
    It is definitely not most efficient way due to failed tries. – Basilevs Jan 19 '14 at 06:01
  • The ideal case would be to generate numbers that are known to be unique but this would not be possible with Math.random(). I think the OP wanted to stick as close as possible to his original code. My priority was the fastest way to find out of the number was unique given that you are using Math.random(). – ucsunil Jan 19 '14 at 06:08
  • There is no point to use Math.random() to get unique integers. Even random ones are recommended to be obtained with Random.nextInt(). – Basilevs Jan 19 '14 at 06:13
0

int base = (int)Math.random(); System.out.print(base);

int change = ((int)Math.random()) % 3;

if(change == 0) { change++; System.out.print(base + 1); System.out.println(base + 2); }

else { System.out.print(base + 2); System.out.println(base + 1); }

alesc3
  • 84
  • 11
0

You can also use Random number generation to fill a HashSet for a fixed range.

akkig
  • 116
  • 7
0
Integer[] a = new Integer[3];
Random r = new Random();
for (int i = 0; i < a.length; i++) { 
        a[i] = r.nextInt(3-1) + 1;  
}
Collections.shuffle(Arrays.asList(a), r);
SOFe
  • 7,867
  • 4
  • 33
  • 61
Suresh
  • 427
  • 1
  • 6
  • 22
0

Reduce the total amount every run, and appropriately increment the result.

static int[] randomRange(Random random, int cap, int count) {
    assert count < cap && count > 0 && cap > 0;
    int[] output = new int[count];
    // initial placeholder. use 0x7FFFFFFF for convenience is also OK.
    Arrays.fill(output, -1);
    for(int i = 0; i < count; i++) {
        // you only have (cap - i) options left
        int r = random.nextInt(cap - i);
        // iterate through a sorted array
        for(int got : output) {
            // ignore placeholders
            if(got != -1 && got <= r) {
                // the generated random int counts number of not-yet-picked ints
                r++;
            }
        }
        // add to array in a sorted manner
        addToArray(output, r);
    }
    return output;
}

static void addToArray(int[] array, int value) {
    for(int i = 1; i <= array.length; i++) {
        if(i == array.length || array[i] >= value) {
            // shift smaller values one place left
            // this includes -1. If you use 0x7FFFFFFF,
            // you may have to sort the array the other way round.
            System.arraycopy(array, 1, array, 0, i - 1);
            array[i - 1] = value;
            return;
        }
    }
}

This algorithm has a disadvantage that its output is sorted. It is, of course, also possible to keep track of two arrays, one sorted (for increment) and one unsorted (for return).

The above code snippet was tested through cap = 20, count = 10 and cap = 20, count = 20 twice each.

SOFe
  • 7,867
  • 4
  • 33
  • 61