tags:

views:

270

answers:

6

This is how i am generating a unique no in between 1 to 6 and getting appropriate images from the drawable folder.

Random rand = new Random();
// n = the number of images, that start at idx 1
rndInt = rand.nextInt(6) + 1; 
String imgName = "card" + rndInt;
int id = getResources().getIdentifier(imgName, "drawable", getPackageName());
imgView.setImageResource(id);

What i want is, I have to call this method 7 times, and each time this method should return a unique random no. so that none of the already chosen numbers will come up again.

+34  A: 

The usual approach to this kind of problem is to create a list containing each of the possible values and shuffle it (use Collections.shuffle). You then consume one item from the list each time you need a value. This will ensure that you don't use the same value more than once but still allows for a random order.

Dan Dyer
It looks like you're using this to shuffle cards. Wouldn't it be better to load all of the cards, and then shuffle them? The approach is similar to this answer.
Erick Robertson
+1 Much better than the accepted answer. I wonder if yours had been accepted if it had code.
MAK
A: 

Create a static list of possibilities you've already gotten.

static ArrayList<int> listIdontWantAnymore = new ArrayList<int>();

int NextRandomNumber() {
    Random random = new Random();
    int myRandomInt;

    do {
        myRandomInt = random.NextInt(6) + 1;
    } while(listIdontWantAnymore.Contains(myRandomInt));

    listIdontWantAnymore.Add(myRandomInt);

    // now your 'myRandomInt' is what you want it to be.
    return myRandomInt;
}
Snake
I think any solution like this should have failsafe-system to avoid nasty deadlocks. It could end bad ;)
monoceres
That was perfect, man..dat wat i waz looking for, now i am able to create a unique random numberthanks a lot.
shishir.bobby
@shishir.bobby: no, that was not perfect. That was absolutely horrible. Please, please do not use this "solution".
Michael Borgwardt
Try running it on... lets say 1000 limit and you will notice that it is slow. After it generates lets say 999 numbers, it will statistically need 1000 more tries to get the last one. That means that the complexity of this algorithm will be O(n^2) - and that's horrible for such a simple task.
Max
@Max: That assumes a perfect distribution. I fear that it would be much worse than than O(n^2).
Arafangion
@Arafangion No, it will be exactly n^2 (statistically at least). I've just calculated it. For n-th number you need n tries to get it. So you will need 1+2+3+...n tries to get full set. And that's approximately O(n*n/2) -> O(n^2).
Max
-1 for (hopefully) a joke gone horribly wrong the moment it was accepted.
Greg D
than wat u guys suggest?????
shishir.bobby
@shishir.bobby: Scroll down and choose ANY other answer.
Max
@Max: For the sake of argument... Suppose you have a random number generator that always returns 4. Now, how slow will that be for N=0? (Pretty instantanious, I hope). What about N=1? Pretty dang fast, actually. N=2? You might be waiting for the sun to cool down!The better the random number distribution, the closer to O(n^2) you will get. The more "spiky" the random number generation, the worse it will get.
Arafangion
Do _NOT_ call this code more than 6 times...
Thorbjørn Ravn Andersen
@shishir.bobby: The wonder thing about this site is that you can see what we suggest without even asking us! Just check out the answers with the most upvotes.
Greg D
@Arafangion: Knowing that someone will start arguing about the randomness of random generators, I explicitly specified "*statistically at least*". Did you notice that part? So *statistically* this algorithm is O(n^2), that is true and you cant prove it is wrong. In reality though, it may vary from O(n) to (infinity).
Max
@Max: Sorry, I'd missed that. I'm used to seeing "Amortized" in that context, but even so, using the mathematical definition of 'statistically' is correct.
Arafangion
@Max: "For n-th number you need n tries to get it." <- Nope. Assuming a perfectly uniform generator, the expected number of tries to get the kth number (1 <= k <= n) from a sample of size n will be n/(n + 1 - k). So the expected total number of random samples needed is O(n log n), which isn't actually too bad.
Mark Dickinson
@Mark Dickinson: Yeah, you are right. I've always been bad in statistics xD
Max
+6  A: 

Here is an example class which creates a random permutation using the approach Dan Dyer suggested. It ensures that each .next() calls gives a new number up to the number given in the constructor. After that it wraps around and gives the same sequence again. This can be useful for shuffling a playlist.

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class RandomPermutation{
    private List<Integer> list;
    private int index;

    /**
     * Create a random permutation the sequence of numbers 0, 1, ... , n - 1.
     * @param n Range specifier, must be positive
     */
    public RandomPermutation(int n) {
        if (n <= 1) {
            throw new IllegalArgumentException(
                    "Positive number expected, got: " + n);
        }
        list = new ArrayList<Integer>();
        newList(n);
    }

    /**
     * Creates a new list
     */
    public void newList(int n) {
        index = -1;
        list.clear();
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
        Collections.shuffle(list);
    }

    /**
     * Retrieve the next integer in sequence. 
     */
    public int next() {
        index = (index + 1) % list.size();
        return list.get(index);
    }
}

Btw. do not use the approach Snake used. It is not only because it will freeze once all numbers have been used. That can be fixed. The problem is more that the procedure runs slower and slower as more and more numbers are in the listIdontWantAnymore. With just 6 numbers it's not a problem, but it can cause quite a significant slowdown if the range is large. Consider choosing between 10000 numbers. After 9900 numbers have been chosen there is a 1% chance of hitting a good number. after 9990 numbers there is a 0.1% chance of hitting a good number and etc.

Here is an example of how you can use the class:

static RandomPermutation randomPerm = new RandomPermutation(7)

int NextRandomNumber() {
    return randomPerm.next() + 1;
}
Zeriab
thanks zeriab, i implemeneted ur approach, and its working f9.can u plz tell me one more thing,like u must hv seen a timer, countdown timer, showing values from 10 to 0 , visible on view.how can i show random number keeps on changing on my view. thanks again mate
shishir.bobby
A: 

For your particular use-case, this should do the trick.

Random rand = new Random();
// n = the number of images
List<String> imgNames = new ArrayList<String>(n);
for (int i = 0; i < n; i++) { 
    imgNames.add("card" + (i + 1)) 
}
while (!imageNames.isEmpty()) {
    String imgName = imgNames.remove(rand.next(imageNames.size());
    int id = getResources().getIdentifier(imgName, "drawable", getPackageName());
    imgView.setImageResource(id);
}

Beware that this does not scale well as n gets large. The remove operation is O(n) for an ArrayList or a LinkedList. But for n in the hundreds or thousands, this is probably insignificant compared with loading and displaying the images.

Also, as the comments noted "unique random numbers" is a contradiction in terms. What you are after is a random permutation of the set of numbers from 1 to n. My solution gives you this without an explicit "shuffling" step, and that's sufficient for your use-case.

Stephen C
I would say it's quite clear that "unique random numbers" means that the same sample should not be picked more than once.On a side-note: The removeFirst() operation on a LinkedList is O(1).
Zeriab
@Zeriab - *"The removeFirst() operation on a LinkedList is O(1)"*. How is that relevant? The algorithm doesn't use that method.
Stephen C
@Zeriab - "unique random number" might be clear to you, but it is nonsense from a mathematical perspective. Sort of like talking about sets that allow duplicates.
Stephen C
A number that is unique (and) random.Unique in respect to other calls.Random in that the number should be picked randomly among 1,2,...,6,7.I do not see why it is nonsense from a mathematical perspective to consider the conjunction of the two constraints.Am I missing some ambiguity?
Zeriab
You are right that my mention of removeFirst() is irrelevant for your example.You can use a Red-Black tree (TreeSet) whose remove operations runs in O(lg).
Zeriab
Sets don't have a `remove(int)` method.
Stephen C
@Zeriab - yes you are missing something. Simply, a real random number does not depend on previous numbers in the sequence. But the uniqueness constraint means that there has to be a dependency; i.e. no number can be repeated.
Stephen C
A: 

Generate a list of numbers containing every number you will use. (Which is fine, given that we are talking about a small range, where "N" is "somewhere less than a thousand")

When you choose a number, select a random index between 0 and sizeof(list), that number becomes the index of that list.

Delete that list index and return the number.

(It is an exercise to the reader to determine what kind of "list" is appropriate here.)

Arafangion
A: 

Use a linear congruential generator with appropriately chosen parameters.

tc.