1

So lets say i have a list of tuples

l=[(1,2),(3,4),(5,6),(7,8),(9,10)]

I want to shuffle the values after a specific rule, so that after i shuffle the list i can unshuffle it back using the same method.

One example would be that i shift the entire list to the right with 1 position and then i can shift the shuffled list with one position to the left so i can get the original list.

But this seems kinda simple so i was wondering if they're more creative methods of doing this

Edit: The idea would be that if i send someone the shuffled list, he could unshuffle it without knowing the original list,only knowing the method used for shuffle

Tenshi
  • 77
  • 2
  • 9
  • Its time to get your hands dirty. What have you tried so far? (Also note, the word shuffle can be misleading here, "shift" might be better) – Paritosh Singh Feb 16 '19 at 15:03
  • Please show us what you have tried? – Jab Feb 16 '19 at 15:03
  • 1
    Why not keep a copy of the original list, so you can easily revert to it? – trincot Feb 16 '19 at 15:07
  • 1
    There are too many ways to approach this problem. The answers would just turn into a straw-poll for which one people liked. The best thing is to do some research on the topic yourself, find two or three, _analyze_ them, determine if they work for you or not, and _try them out_. Come to us when you have a specific question about something you have attempted to do. – Patrick Artner Feb 16 '19 at 15:11
  • The idea would be that if i send someone the shuffled list, he could unshuffle it without knowing the original list, only knowing the method used for shuffle, thats why i cant keep a copy of the original list. I was only asking for some ideas, i wasn't trying to ask for you guys to write me the code, sorry. – Tenshi Feb 16 '19 at 15:25
  • The problem with your question is that it is formulated in a way that gives an infinite amount of equally valid solutions. You have to decide what specifically you want to happen with your problem. But hey, here's a suggestion: Take the leftmost tuple, and if the first item is odd, move it n*some_value to the right. If the second item is not odd, move it m*some_other_vale further to the right. Handle looping. Then take the tuple that now is second from left, and do the same. And so on, until number of tupled in list is exhausted. It's not the best, it's just an example. – RoyM Feb 16 '19 at 15:59
  • *"...only knowing the method used for shuffle"*: how would you transfer that knowledge, or would the method always be the same and be like a contract? – trincot Feb 16 '19 at 17:26

4 Answers4

3

You could choose some algorithm to determine a seed that can be derived from the list itself and does not depend on its order.

For the example data structure, the seed could for instance be the sum of all values. Then with that seed you would generate a random (but deterministic) permutation of the numbers from 0 to n-1. That permutation can then be used as a basis for the shuffle and unshuffle functions:

import random

def getperm(l):
    seed = sum(sum(a) for a in l)
    random.seed(seed)
    perm = list(range(len(l)))
    random.shuffle(perm)
    random.seed() # optional, in order to not impact other code based on random
    return perm

def shuffle(l):
    perm = getperm(l)
    l[:] = [l[j] for j in perm]

def unshuffle(l):
    perm = getperm(l)
    res = [None] * len(l)
    for i, j in enumerate(perm):
        res[j] = l[i]
    l[:] = res

Example call:

l=[(1,2),(3,4),(5,6),(7,8),(9,10)]   
print(l)    
shuffle(l)
print(l) # shuffled
unshuffle(l)
print(l)  # the original
trincot
  • 317,000
  • 35
  • 244
  • 286
2

I suppose you could apply any shuffle you like, so long as you can seed your random source.

Take a list with the numbers 0 to n, and shuffle it. Use the order of this list to shuffle your list of tuples, e.g. if the first element of your list after shuffling is 5, then the first element in your shuffled list of tuples is l[5]. You can then do the inverse: the first element in your shuffled list of tuples is the 5th element in your list of unshuffled tuples.

If you seed your random source, you can recreate your list of shuffled numbers just by running the same shuffle on the same list of 0 to n. You can then use this to unshuffled your list of shuffled tuples, as before.

Edit: trincot's answer implements this idea, but with working sample code.

canton7
  • 37,633
  • 3
  • 64
  • 77
1

Are you looking for deque?

from collections import deque

d = deque([(1,2),(3,4),(5,6),(7,8),(9,10)])

d.rotate(1)
deque([(9, 10), (1, 2), (3, 4), (5, 6), (7, 8)])

d.rotate(-1)
deque([(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)])
gold_cy
  • 13,648
  • 3
  • 23
  • 45
1

If you don't want a seed you can do:

shuffler = np.random.permutation(len(l)) # returns indices to shuffle the list
undo_shuffler = np.argsort(shuffler) # returns indices to undo the shuffle

# Shuffle the list
shuffled_list = [l[j] for j in shuffler]

# Undo shuffle
unshuffled_list = [shuffled_list[j] for j in undo_shuffler]

'''

James Kl
  • 177
  • 9