tips for this exercise?
Steven D'Aprano
steve at REMOVETHIScyber.com.au
Tue Mar 28 18:01:43 EST 2006
On Tue, 28 Mar 2006 20:32:32 +0000, John Salerno wrote:
> Brian Quinlan wrote:
>
>> I would just write the function like this:
>>
>> def genNumbers():
>> shuffle_nums = numbers[:] # copy the list to preserve the orginal
>> # order (if it matters)
>> random.shuffle(shuffle_nums) # shuffle the entire list
>> return shuffle_nums[:5] # return the first 5 elements
>
> Thanks. Interesting idea. I did consider copying it, but does that hurt
> performance each time the function is called? I know it may not be
> noticeable, but I don't like the idea of doing unnecessary work like
> that, if it is in fact unnecessary.
Generally, lottery numbers are selected from a range, e.g. one to forty.
So rather than passing a global list, just pass the maximum number:
def getNumbers(maxn=40):
L = range(1, maxn+1)
random.shuffle(L)
return L[0:5]
This recreates the master list as needed. If you are running a lot of
trials, or if your maxn is huge (in the tens of millions perhaps) you
might want to optimize by re-using the list each time:
all_numbers = range(1, maxn+1)
def getNumbers(L):
random.shuffle(L)
return L[0:5]
getNumbers(all_numbers)
Notice that this has the side-effect of shuffling your master list. In
general, side-effects are to be avoided whenever possible, although this
one is fairly benign.
However, and this is important, consider this note from the random.shuffle
__doc__ string:
Note that for even rather small len(x), the total number of
permutations of x is larger than the period of most random number
generators; this implies that "most" permutations of a long
sequence can never be generated.
In other words, this is not a good technique for producing a fair lottery.
The results will be biased.
Here is a method that is less biased:
def genNumbers(maxn=40):
# Warning: untested
L = range(1, maxn+1)
chosen = []
for _ in range(5):
n = random.choice(L)
L.remove(n)
chosen.append(n)
return chosen
If you want to allow duplicates, you can simplify the code:
def genNumbersWithDuplicates(maxn=40):
# Warning: untested
L = range(1, maxn+1)
chosen = []
for _ in range(5):
chosen.append(random.choice(L))
return chosen
Hope this helps.
--
Steven.
More information about the Python-list
mailing list