I ran into the challenge where I need a function that returns a random number within a given range from 0 - X
. Not only that, but I require the number returned to be unique; not duplicating numbers that have already been returned on previous calls to the function.
Optionally, when this is done (e.g. the range has been 'exhausted'), just return a random number within the range.
How would one go about doing this?
This should do it:
Usage:
Although it works, it has no good performance when the x-th random is generated - it searches the whole list for a free place. This algorithm, a step-by-step Fisher–Yates shuffle, from the question Unique (non-repeating) random numbers in O(1)?, will perform better:
(Demo at jsfiddle.net)
Extended version which does only generate one "group" of unique numbers:
(Demo)
You may try generating the number using the current date and time value which would make it unique. To make it within the range, you may have to use some mathematical function.
I wrote this function. It keeps its own array with a history of generated numbers, preventing initial duplicates, continuing to output a random number if all numbers in the range have been outputted once:
Here's a working Fiddle
I hope this is of use to someone!
Edit: as pointed out by Pointy below, it might get slow with a large range (here is a fiddle, going over a range from 0-1000, which seems to run fine). However; I didn't require a very large range, so perhaps this function is indeed not suited if you look to generate and keep track of an enormous range.
You got some great programming answer. Here's one with a more theoretical flavor to complete your panorama :-)
Your problem is called "sampling" or "subset sampling" and there are several ways you could do this. Let
N
be the range you are sampling frame (i.e.,N=X+1
) andM
be the size of your sample (the number of elements you want to pick).if
N
is much larger thanM
, you'll want to use an algorithm such as the one suggested by Bentley and Floyd in his column "Programming Pearls: a sample of brilliance" (temporarily available without ACM's lock screen here), I really recommend this as they explicitly give code and discuss in terms of hash tables, etc.; there a few neat tricks in thereif
N
is within the same range asM
, then you might want to use the Fisher-Yates shuffle but stop after onlyM
steps (instead ofN
)if you don't really know then the algorithm on page 647 of Devroye's book on random generation is pretty fast.