0

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

Sam Jarman
  • 7,277
  • 15
  • 55
  • 100
  • OK, what language are you using? – Adriaan Stander Apr 10 '10 at 08:44
  • Do you really want 15 numbers between 1 and 15 in any order? – gbn Apr 10 '10 at 08:47
  • Im not concerned with the order as such, more so, everytime i run through it, its different – Sam Jarman Apr 10 '10 at 08:50
  • 1
    @Sam Jarman: Guaranteed to be different, or just highly likely to be different? – Jon Skeet Apr 10 '10 at 09:20
  • possible duplicate of http://stackoverflow.com/questions/1617630/non-repeating-random-numbers – kennytm Apr 10 '10 at 09:32
  • @Sam That should be fine then - it's very unlikely that you'll get duplicates. – Jon Skeet Apr 10 '10 at 09:57
  • Ok guys I got it I ended up doing it a long, but working way firstly, made an NSMutableArray with Strings, @"1", @"2", etc used a random gen to find a number from a random object from that index, took the int value from that, used it, then using the same (index of the)object, removed it from the array. repeat over and over, until array is empty refilled array when necc. this ensured, NO REPEATES, DIFFERENT EVERYTIME. YAY. Thanks to @Astander and @Jon Skeet and others for your help - although I didnt go with your solutions really :) Thanks Guys, and good night! – Sam Jarman Apr 10 '10 at 10:38

2 Answers2

4

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
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @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 Apr 10 '10 at 08:47
  • 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* – Adriaan Stander Apr 10 '10 at 08:48
  • @astander: Where did I ever claim I'd generate 15 random numbers? I said the numbers 1-15. That's entirely different. – Jon Skeet Apr 10 '10 at 08:48
  • @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 Apr 10 '10 at 08:52
  • OK, the OP has edited the question *produce 15 random numbers [EDIT: from 1 - 15]*, that makes it a different ball game. – Adriaan Stander Apr 10 '10 at 08:54
  • yes sorry ... i saw that was confusing you all. numbers 1 - 15, in an order that is different everytime perhaps... chuck them all into an array, then call //fromIndex:randomInt then remove from index:randomInt repeat? – Sam Jarman Apr 10 '10 at 08:57
  • @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 Apr 10 '10 at 09:09
  • " Im not concerned with the order as such, more so, everytime i run through it, its different " – Sam Jarman Apr 10 '10 at 09:16
  • @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 Apr 10 '10 at 09:19
  • `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 Apr 10 '10 at 10:02
2

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
  • 174,939
  • 50
  • 355
  • 478
  • Maybe you should've mentioned that, then. Either way, Python is usually a nice way to provide executable pseudo-code. – Thomas Apr 10 '10 at 13:56