randomly generate n of each of two types

Steven D'Aprano steve at REMOVEME.cybersource.com.au
Mon Feb 12 01:13:00 EST 2007


On Mon, 12 Feb 2007 00:57:35 +0000, Alan Isaac wrote:

> "Stargaming" <stargaming at gmail.com> wrote in message
> news:eqo184$2u7e$1 at ulysses.news.tiscali.de...
>> ...   types *= n
>> ...   shuffle(types)
> 
> This again has the "costs" I referred to:
> creating a potentially large sequence,
> and shuffling it.  (Additionally, shuffle
> cannot achieve many of the possible
> shuffles of a large list, but I doubt this
> is easily evaded.)

Whether that second issue is a problem or not really depends on what you
intend doing with the random objects. But notice that Python uses the
Mersenne Twister PRNG, which has a period of 2**19937-1. That's *roughly*
equivalent to the number of permutations of a list with 2080 items.

If you really care about shuffling large lists, you can chain PRNGs. For
instance, you might use shuffle() to generate a random batch of items,
then use a completely different PRNG to shuffle the list again.



As for the first issue:

def random_values(n, valuelist=[True, False]):
    for _ in range(n):
        values = valuelist[:]
        random.shuffle(values)
        for item in types:
            yield item

Notice that the default objects in the list aren't types, so the name
random_types is inappropriate. The user can pass any objects they like,
not just a list of types like [int, str].

Note also that this code isn't limited to lists of just two objects. You
can pass as many or as few as you like.

It also doesn't build a large list, but any regularities in the shuffle
algorithm will show up in here. Unless you're doing cryptography, that
probably doesn't matter.

If you want to avoid shuffle, here's an alternative:

def random_values(n, valuelist=[True, False]):
    N = len(valuelist)
    for _ in range(N*n):
         yield valuelist[random.randrange(0, N)]




-- 
Steven D'Aprano 




More information about the Python-list mailing list