amln_ndh
amln_ndh

Reputation: 617

Generate random number without duplicate in certain range

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);

        }
    }

Upvotes: 2

Views: 13801

Answers (10)

Suresh
Suresh

Reputation: 427

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);

Upvotes: 0

Bohemian
Bohemian

Reputation: 424993

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);

Upvotes: 10

SOFe
SOFe

Reputation: 8214

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.

Upvotes: 0

Addis
Addis

Reputation: 2530

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()+ " ");
}

Upvotes: 1

An SO User
An SO User

Reputation: 24998

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 <>.

Upvotes: 1

akkig
akkig

Reputation: 116

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

Upvotes: 0

alesc3
alesc3

Reputation: 84

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); }

Upvotes: 0

ucsunil
ucsunil

Reputation: 7494

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.

Upvotes: 0

Vikas Rathod
Vikas Rathod

Reputation: 384

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 :)

Upvotes: 0

LMNOP
LMNOP

Reputation: 151

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.

Upvotes: 0

Related Questions