views:

461

answers:

2

how does one use code to do this:

produce 15 random numbers [EDIT: from 1 - 15] that are not in any order, and that only occur once eg.

1 4, 2, 5, 3, 6, 8, 7, 9, 10, 13, 12, 15, 14, 11

rand() or arc4rand() can repeat some, which is not what im after.

Thanks

+3  A: 

Generate the full list, then shuffle it.

Python:

import random
r = range(1, 16)
random.shuffle(r)

A random number generator by itself can, almost by definition, not do what you want. It would need to keep track of all the numbers already generated, which would be as memory-hungry as the solution sketched above.

Thomas
dont use python.
Sam Jarman
Maybe you should've mentioned that, then. Either way, Python is usually a nice way to provide executable pseudo-code.
Thomas
+4  A: 

The simplest way is to produce a collection (e.g. an array) of the numbers 1-15, and then shuffle it. (EDIT: By "collection of the numbers 1-15" I mean 1, 2, 3, 4, 5... 15. Not a collection of random numbers in the range 1-15. If I'd meant that, I'd have said so :)

You haven't given details of which platform you're on so we can't easily give sample code, but I'm a big fan of the modern variant of the Fisher-Yates shuffle. For example, in C#:

public static void Shuffle<T>(IList<T> collection, Random rng)
{
    for (int i = collection.Count - 1; i > 0; i--)
    {
        int randomIndex = rng.Next(i + 1);
        T tmp = collection[i];
        collection[i] = collection[randomIndex];
        collection[randomIndex] = tmp;
    }
}

If you want to produce "more random" numbers (e.g. 15 distinct integers within the entire range of integers available to you) then it's probably easiest just to do something like this (again, C# but should be easy to port):

HashSet<int> numbers = new HashSet<int>();
while (numbers.Count < 15)
{
    numbers.Add(rng.Next());
}
List<int> list = numbers.ToList();
// Now shuffle as before

The shuffling at the end is to make sure that any ordering which might come out of the set implementation doesn't affect the final result.

Jon Skeet
This does not ensure that it is unique. No duplicates??
astander
@astander: In what way? You've got a collection with the numbers 1-15 in, and then you shuffle it - how can you get duplicates? I'll clarify the answer just in case you misunderstood it, but I think it's fine...
Jon Skeet
Generating 15 random numbers by default **should be random**, but we all know it is not. There should be at least some check that it does not exists already... From the OPs q *produce 15 random numbers that are not in any order, and that only occur once*
astander
@astander: Where did I ever claim I'd generate 15 random numbers? I said the numbers 1-15. That's entirely different.
Jon Skeet
See the question body, what you said and what was asked might not be the same...
astander
@astander: See the example in the question body, which *does* use the numbers 1-15. There's no concrete indication that he wants 15 arbitrary random numbers from a larger range. However, I've edited my answer to explain how to do that as well...
Jon Skeet
OK, the OP has edited the question *produce 15 random numbers [EDIT: from 1 - 15]*, that makes it a different ball game.
astander
yes sorry ... i saw that was confusing you all. numbers 1 - 15, in an order that is different everytimeperhaps... chuck them all into an array, then call//fromIndex:randomIntthen remove from index:randomIntrepeat?
Sam Jarman
@Sam Jarman: I don't know about the code that you've provided, but typically shuffling is a matter of swapping elements, not removing and adding them. See my sample C# code, which should be reasonably easy to port to Objective-C. Note that I haven't addressed "no sequential numbers" from your title, as you haven't elaborated on it in the post - do you really want to forbid 8 following 7 for example?
Jon Skeet
" Im not concerned with the order as such, more so, everytime i run through it, its different "
Sam Jarman
@Sam: Note that it's not guaranteed to be different *every* time you generate it. That's impossible, as there's only a finite number of possible sequences, but you could run it a theoretically infinite number of times. The order is unpredictable, however - is that good enough? If you *really* need the order to be unique, you'd probably have to record all previous runs, generate a new one and see whether it's the same as an existing one. (If you didn't care about predictability you could do this more easily of course.)
Jon Skeet
`rng.Next(i)` generates a number *r* such that 0 <= *r* < *i* http://msdn.microsoft.com/en-us/library/aa329892(VS.71).aspx For an unbiased shuffle, we want *r* such that 0 <= r <= *i* so that there is a chance that each element will remain where it started. It should be `rng.Next(i+1)`. Also, one should also check the RNG itself for bias, which can easily happen if its range limiting is done by taking the remainder against a larger random value.
Chris Johnsen
@Chris: Oops, yes. Will fix.
Jon Skeet