Creating 5 lists of the 5 same elements in different index order

153 views Asked by At

I'm struggling with a problem that seems so basic and yet drives me crazy as I'm still unable to implement.

Here's the deal: I have a list with 5 elements, for instance :

['A', 'B', 'C', 'D', 'E']

I want the elements in the lists so that each list contains the same element at differents indexes. So for example, the element 'A' will have a different index position in each list. It should be randomize so that each time I run the code, I still have different lists.

like this:

['A', 'B', 'C', 'D', 'E']
['C', 'D', 'E', 'A', 'B']
['B', 'C', 'D', 'E', 'A']
['E', 'A', 'B', 'C', 'D']
['D', 'E', 'A', 'B', 'C']

I tried with itertools, I tried with if statement into for loops into for loops but obviously it didn't work... I feel like the solution is very simple but I'm missing something.

4

There are 4 answers

2
Ester Gjorek On
import random

original_list = ['A', 'B', 'C', 'D', 'E']

# Number of lists you want to generate:
num_lists = 5

# Generate and print the shuffled lists:
for i in range(num_lists):
    shuffled_list = original_list.copy()
    random.shuffle(shuffled_list)
    print(shuffled_list)

You can change the code according to how many lists you want.

6
C.Nivs On

You can use a collections.deque for this:

from collections import deque

d = deque('ABCDE')

for _ in range(len(d)):
    print(d)
    d.rotate()

deque(['A', 'B', 'C', 'D', 'E'])
deque(['E', 'A', 'B', 'C', 'D'])
deque(['D', 'E', 'A', 'B', 'C'])
deque(['C', 'D', 'E', 'A', 'B'])
deque(['B', 'C', 'D', 'E', 'A'])

To randomize, you'd shuffle the end result:

import random

lists = []

for _ in range(len(d)):
    lists.append(list(d))
    d.rotate()

random.shuffle(lists)
2
tobias_k On

Not sure if this is as random as your constrains permit, but it's at least a lot more random than your example while keeping all the constraints: Start with the "shifted" lists as in your example, then randomly shuffle the rows and columns of the matrix (or, maybe simpler, shuffle rows, then transpose, then shuffle rows again).

import random

lst = ['A', 'B', 'C', 'D', 'E']
lsts = [lst[i:] + lst[:i] for i in range(5)]
random.shuffle(lsts)
lsts = list(map(list, zip(*lsts)))
random.shuffle(lsts)

Afterwards, each row and column contains each element exactly once, without any obvious pattern. Sample output:

['C', 'A', 'D', 'E', 'B']
['B', 'E', 'C', 'D', 'A']
['E', 'C', 'A', 'B', 'D']
['A', 'D', 'B', 'C', 'E']
['D', 'B', 'E', 'A', 'C']
1
Matthias On

It's a little bit tricky. You can use itertools.permutations to create all possible permutations and then throw out those that don't match the constraint.

But since you get all permutations you get values like ['B', 'A', 'D', 'E', 'C'] and ['B', 'A', 'E', 'C', 'D'] in that order. Now the second permutation will always be thrown out. So you have to shuffle all permutations first.

import itertools
import random

def has_same_index(list_of_lists, list_to_compare):
    for inner_list in list_of_lists:
        for x, y in zip(inner_list, list_to_compare):
            if x == y:
                return True
    return False


data = ['A', 'B', 'C', 'D', 'E']

combis = list(itertools.permutations(data, 5))
random.shuffle(combis)

result = []
for combi in combis:
    if not has_same_index(result, combi):
        result.append(combi)
print(result)

This will give you results like

[('A', 'C', 'E', 'B', 'D'), ('D', 'E', 'C', 'A', 'B'), ('C', 'B', 'D', 'E', 'A'), ('E', 'A', 'B', 'D', 'C'), ('B', 'D', 'A', 'C', 'E')]

or

[('D', 'C', 'B', 'E', 'A'), ('B', 'A', 'C', 'D', 'E'), ('E', 'D', 'A', 'B', 'C'), ('C', 'B', 'E', 'A', 'D'), ('A', 'E', 'D', 'C', 'B')].

If you need the tuples to be lists it's easy to convert them.