0

I am trying to get the possible combinations of a list consists of 4 elements e.g: ('E', 'J', 'M', 'Z'), the condition to have for a valid combination is to change the positions of all 4 elements in every combination

Possible combinations are:

('J', 'E', 'Z', 'M')
('M', 'Z', 'E', 'J')
('Z', 'M', 'J', 'E').....

I tried itertools.permutations (('E', 'J', 'M', 'Z'), 4) and the results are not satisfactory at all. can someone help please?

Anas Rzq
  • 53
  • 6
  • 1
    It is not clear which language you are referring to and why the results are not satisfactory. – unknown_boundaries Jun 05 '21 at 09:54
  • `itertools.permutations` and `.combinations` are _intentionally_ providing results in a sequential/incremental manner. If you want "successive" items in the result to not have elements in the same position, then be clear about that and **show what code you've written** to try and get the results you want. Also, use a smaller list like 'EJM' and show what you consider valid results. – aneroid Jun 05 '21 at 12:20
  • Perhaps you're trying to ["rotate" the list](https://stackoverflow.com/a/9457864/1431750). – aneroid Jun 05 '21 at 12:23
  • what language is this ? would you mind to use a tag for the language ? Python obviously – user1767316 Jun 05 '21 at 17:26
  • I am using python to code this. – Anas Rzq Jun 06 '21 at 12:05
  • I will try to explain this again. I have a list which consists of 4 string elements. I would like to have all possible combinations of these element. any valid combination won't have elements sitting on the same index as the original list. for ('E', 'J', 'M', 'Z'), the following are acceptable ('J', 'E', 'Z', 'M'), ('M', 'Z', 'E', 'J') while ('E', 'J', 'Z', 'M'), ('J', 'J', 'E', 'Z') are not. – Anas Rzq Jun 06 '21 at 12:10
  • Why aren't these two items `('M', 'Z', 'E', 'J')` & `('Z', 'M', 'J', 'E')` _these_ instead of `('M', 'Z', 'J', 'E')` & `('Z', 'M', 'E', 'J')`? What logic do you have that makes `('M', 'Z', 'E', 'J')` valid instead of `('M', 'Z', 'J', 'E')` ? – aneroid Jun 06 '21 at 20:03
  • aneroid, all 6 combinations you mention are valid. you got it. – Anas Rzq Jun 07 '21 at 06:36
  • 1
    All 6 can't be valid because `('M', 'Z', 'E', 'J')` and `('M', 'Z', 'J', 'E')` have M and Z in the same locations. And then can't be merely _swapped_ because then it would conflict with `('Z', 'M', 'E', 'J')` and `('Z', 'M', 'J', 'E')`. Do you mean "either/or" for the alternatives or do you want your 3 in the question, plus the 2 I mentioned (5), along with the original 1 (total 6)? **Still puts 2 options with letters in the same position.** So _once again_ **what's the logic for ordering**? Pick an input and write down **all** the expected results - permutations gives 24 possibilities. – aneroid Jun 07 '21 at 08:52
  • Does this answer your question? [How to compute derangement (permutation) of a list with repeating elements](https://stackoverflow.com/questions/52854146/how-to-compute-derangement-permutation-of-a-list-with-repeating-elements) – Stef Oct 13 '21 at 10:31

1 Answers1

2
import itertools


def get_permutations_whose_all_elems_are_in_a_different_place_than_the_original(original_elems):
    for permutation in itertools.permutations(original_elems):
        if any(left == right for left, right in zip(permutation, original_elems)):
            continue
        else:
            yield permutation

initial_list = ('E', 'J', 'M', 'Z')
print(str(initial_list) + "\n--------------------")
solutions = get_permutations_whose_all_elems_are_in_a_different_place_than_the_original(initial_list)
print("\n".join(str(solution) for solution in solutions))

output :

('E', 'J', 'M', 'Z')
--------------------
('J', 'E', 'Z', 'M')
('J', 'M', 'Z', 'E')
('J', 'Z', 'E', 'M')
('M', 'E', 'Z', 'J')
('M', 'Z', 'E', 'J')
('M', 'Z', 'J', 'E')
('Z', 'E', 'J', 'M')
('Z', 'M', 'E', 'J')
('Z', 'M', 'J', 'E')

There is no E in the first column, no J in the second, no M in the third, no Z in the fourth.

Lenormju
  • 4,078
  • 2
  • 8
  • 22
  • 1
    thanks a million. exactly what I am looking after – Anas Rzq Jun 07 '21 at 15:32
  • 1
    your question was not very clear, @aneroid asked a lot of questions because of that, in the future please provide the expected output. – Lenormju Jun 07 '21 at 16:55
  • @Lenormju Yeah, one of the many suspected possibilities of what the OP wanted. There's even an option to do it by sequential rules only. Btw, you can modify the `if` clause to have only a single branch by flipping the condition: `if all(left != right ...): yield permutation` without needing an `else` branch or a `continue`. – aneroid Jun 08 '21 at 11:27
  • @aneroid indeed, your solution seems to work, but I wrote it the way I thought it, and I like it explicit :) – Lenormju Jun 08 '21 at 11:33