python shuffling with a parameter to get the same result

Python

Python Problem Overview


import random
x = [1, 2, 3, 4, 5, 6]
random.shuffle(x)
print x

I know how to shuffle a list, but is it possible to shuffle it with a parameter such that the shuffling produces the same result every time?

Something like;

random.shuffle(x,parameter)

and the result is the same for this parameter. Say parameter is 4 and the result is [4, 2, 1, 6, 3, 5] every time.

Python Solutions


Solution 1 - Python

As the documentation explains:

> The functions supplied by this module are actually bound methods of a hidden instance of the random.Random class. You can instantiate your own instances of Random to get generators that don’t share state.

So, you can just create your own random.Random instance, with its own seed, which will not affect the global functions at all:

>>> import random
>>> x = [1, 2, 3, 4, 5, 6]
>>> random.Random(4).shuffle(x)
>>> x
[4, 6, 5, 1, 3, 2]
>>> x = [1, 2, 3, 4, 5, 6]
>>> random.Random(4).shuffle(x)
>>> x
[4, 6, 5, 1, 3, 2]

(You can also keep around the Random instance and re-seed it instead of creating new ones over and over; there's not too much difference.)

Solution 2 - Python

You can set the seed (which accepts the parameter) of your random generator, which will determinize your shuffling method

import random
x = [1, 2, 3, 4, 5, 6]
random.seed(4)
random.shuffle(x)
print x

and the result should be always

[2, 3, 6, 4, 5, 1]

In order to "rerandomize" the rest of the code you can simply reseed your random number generator with system time by running

random.seed()

after your "deterministic" part of code

Solution 3 - Python

Shuffling with a fixed value for random does NOT work well! Example:

from random import shuffle
v = sum([[k] * 100 for k in range(10)], [])
print v[:40]
shuffle(v, random = lambda: 0.7)
print v[:40]

Gives the output:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 8, 0, 0, 9, 0, 0, 0, 9, 0, 0, 8, 0, 0, 7, 0, 0, 0, 9, 0, 0, 7, 0, 0, 8, 0, 0, 0, 7, 0, 0, 7, 0, 0, 8, 0, 0, 0, 9]

It's similar for other seeds - not very random (at first sight anyway... hard to prove). This is because random is not a seed - it is reused many times. Demonstration:

def rand_tracker():
	rand_tracker.count += 1
	return random()
rand_tracker.count = 0
shuffle(v, random = rand_tracker)
print 'Random function was called %d times for length %d list.' % (rand_tracker.count, len(v))

Which shows:

Random function was called 999 times for length 1000 list.

What you should do instead is @abarnert's suggestion:

from random import Random
Random(4).shuffle(x)

In that case a fixed value is perfectly fine.

TLDR: Use the answer by @abarnert, do not use a fixed-value function for random!

Solution 4 - Python

From the python reference:

> The optional argument random is a 0-argument function returning a > random float in [0.0, 1.0); by default, this is the function random()

You can use a lambda function that always returns the same value as a seed for shuffle:

In [7]: l = [1,2,3,4]
In [8]: random.shuffle(l, lambda: .5)

In [9]: l
Out[9]: [1, 4, 2, 3]

In [10]: l = [1,2,3,4]

In [11]: random.shuffle(l, lambda: .5)

In [12]: l
Out[12]: [1, 4, 2, 3]  # same order as Out[9]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCo KoderView Question on Stackoverflow
Solution 1 - PythonabarnertView Answer on Stackoverflow
Solution 2 - PythonlejlotView Answer on Stackoverflow
Solution 3 - PythonMarkView Answer on Stackoverflow
Solution 4 - PythonEmmett ButlerView Answer on Stackoverflow