0

I have a list a=[num1,num2,...,numn]. I am shuffling it with random.shuffle(a). However what I want as a functionality is the shuffle algorithm to take as input a key, and the owner of the key to deterministically produce the same shuffles?

I want an algorithm that takes as input the key, the sequence of elements to be shuffled and it outputs a random permutation thereof, depending on the key. If you apply the shuffle again with input the same key on the same sequence of data you are getting the same result. Otherwise random shuffle. The same key on the same data allows to "un-shuffle"

Is that possible?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
curious
  • 1,524
  • 6
  • 21
  • 45
  • 1
    What is an 'owner of the key'? What do you mean by 'deterministically produce the same shuffles'? – Martijn Pieters Aug 10 '16 at 18:29
  • So you want a non-random random? Is that what you're asking? – Two-Bit Alchemist Aug 10 '16 at 18:29
  • @Two-BitAlchemist. I want an algorithm that takes as input the key, the sequence of elements to be shuffled and it outputs a random permutation thereof, depending on the key. If you apply the shuffle again with input the same key on the same sequence of data you are getting the same result. Otherwise random shuffle. The same key on the same data allows to "un-shuffle" – curious Aug 10 '16 at 18:30
  • Yes I believe the built-in function you are looking for is `sorted`. It takes a key argument, which is a callable, and will produce the same "shuffle" each time it is called. – Two-Bit Alchemist Aug 10 '16 at 18:33
  • 2
    @curious: so you want to set the *random seed*. Create a `random.Random(seed)` instance to keep the seed independent, then use that to shuffle with `randominstance.shuffle(somelist)`. The same `seed` will produce the same shuffle order. – Martijn Pieters Aug 10 '16 at 18:33
  • 2
    @curious: see [random.seed(): What does it do?](http://stackoverflow.com/q/22639587) as well. – Martijn Pieters Aug 10 '16 at 18:35
  • @MartijnPieters how i use the random.Random() with random.shuffle()? shuffle only takes as input the list of elements you want to shuffle – curious Aug 10 '16 at 18:36
  • @curious: `random.shuffle()` (the module function) is really the `random.Random.shuffle()` *method* on a singleton `random.Random()` instance stored in the module. Create your *own* instance and call `instance.shuffle()` on that. – Martijn Pieters Aug 10 '16 at 18:40
  • @MartijnPieters right how stupid. That should work – curious Aug 10 '16 at 18:40

1 Answers1

2

In pseudo-random terminology, that key is called a seed, and you can set the random seed on a new random.Random() instance:

def keyed_shuffle(x, seed=None):
    random_obj = random.Random(seed)
    random_obj.shuffle(x)

You could use random.seed() and random.shuffle() directly too, but using your own random.Random() instance avoids setting the seed on the singleton random.Random() instance that the random module uses, thus not affecting other uses of that module.

The seed can either be an integer (used directly) or any hashable object.

Demo:

>>> a = [10, 50, 42, 193, 21, 88]
>>> keyed_shuffle(a)       # no seed
>>> a
[42, 10, 88, 21, 50, 193]
>>> a = [10, 50, 42, 193, 21, 88]
>>> keyed_shuffle(a)       # again no seed, different random result
>>> a
[88, 50, 193, 10, 42, 21]
>>> b = [10, 50, 42, 193, 21, 88]
>>> keyed_shuffle(b, 42)   # specific seed
>>> b
[193, 50, 42, 21, 10, 88]
>>> b = [10, 50, 42, 193, 21, 88]
>>> keyed_shuffle(b, 42)   # same seed used, same output
>>> b
[193, 50, 42, 21, 10, 88]
>>> c = [10, 50, 42, 193, 21, 88]
>>> keyed_shuffle(b, 81)   # different seed, different random order
>>> c
[10, 50, 88, 42, 193, 21]
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343