1

I've a list, let's say [(1,1,1),(0,0,0),(0,0,0)] and I want to generate all the permutations of n elements in the q lenght list, discarding the equivalent. I mean:

Input

[1,1,1,0,0,0,0,0,0] 

Output

[[(1,1,1),(0,0,0),(0,0,0)], <----- keep this
[(1,1,0),(1,0,0),(0,0,0)], <----- keep this
[(1,1,0),(0,1,0),(0,0,0)], <----- disgard this
[(1,1,0),(0,0,1),(0,0,0)], <----- disgard this
[(1,1,0),(0,0,0),(1,0,0)], <----- keep this
...
...
...
...
[(0,0,0),(1,0,0),(1,0,1)], <----- keep this
[(0,0,0),(1,0,0),(0,1,1)], <----- disgard this
[(0,0,0),(0,1,0),(1,0,1)], <----- disgard this
[(0,0,0),(0,1,0),(0,1,1)], <----- disgard this
[(0,0,0),(0,0,1),(1,0,1)], <----- disgard this
[(0,0,0),(0,0,1),(0,1,1)], <----- disgard this
[(0,0,0),(0,0,0),(1,1,1)]] <----- keep this

This is a quite simple task with some nested for cicle, and sum for function, but I can't figure out a way to achieve this using ipertools. Any suggestion?

Thanks.

2
  • 5
    What is the rule for discarding ? Could you clarify ? Feel unclear for me^^ Commented Dec 21, 2019 at 14:27
  • You want 3 sub_list of 3 in the list of 9; if two list of nine differs only for the position (and not for the sum) of the "1" in one of the sub_list of 3, you discard it. Is like having 3 balls (the "1") that can be in 3 pots (the list of 3). You just want to keep the "real" different combination: [(1,1,0)(1,0,0)(0,0,0)] and [(1,0,1)(0,1,0)(0,0,0)] means both of them 2 balls in the first pot, 1 ball in the second pot, 0 ball in the third pot, so you discard ont of them. Commented Dec 21, 2019 at 19:28

2 Answers 2

1

It seems like you want to list all the possible ways to perform 3 discards from you list of items, each consisting of 3 cards. I suggest you to do a better mapping of your choices, like for example [3, 2, 0] instead of [(0,0,0),(1,0,0),(1,0,1)] where [3, 2, 0] means starting indices of your list for each discard. This case can be illustrated as follows:

  • [1,1,1,0,0,0,0,0,0], take out items starting from index=3
  • [1,1,1,0,0,0], take out items starting from index=2 ->
  • [1,1,0], take out items starting from index=0 ->
  • []

The next step of solutions is to consider how all the possible choices of indices looks like. It's quite clear that:

  • first index doesn't exceed 6 (since list has 9 items),
  • second index doesn't exceed 3 (since list has 6 items)
  • third index is 0 (since list has 0 items)

In general I suggest to generate all the possible choices and do discards manually for each choice:

from itertools import product
d = [1,1,1,0,0,0,0,0,0]
n = 3
starting_indices = [range(len(d)-(n-1)-n*m) for m in range(len(d)//n)]
choices = []
for idx_sequence in product(*starting_indices):
    current_d = d.copy()
    current_choice = []
    for id in idx_sequence:
        current_choice.append(current_d[id: id+n])
        del current_d[id: id+n]
    choices.append(current_choice)
print(choices)

Note:

Some of the choices might be duplicated

Update:

You can eliminate duplicated choices if you add these rows to your script:

choices = set([tuple(tuple(m) for m in n) for n in choices]) #if you need to remove duplicates
choices = [list(list(m) for m in n) for n in choices] #if you need to set type back

Output:

[[0, 0, 0], [1, 1, 1], [0, 0, 0]]
[[0, 0, 0], [1, 0, 0], [1, 1, 0]]
[[0, 0, 0], [1, 1, 0], [1, 0, 0]]
[[0, 0, 0], [0, 0, 0], [1, 1, 1]]
[[1, 1, 1], [0, 0, 0], [0, 0, 0]]
[[1, 0, 0], [0, 0, 0], [1, 1, 0]]
[[1, 0, 0], [1, 1, 0], [0, 0, 0]]
[[1, 1, 0], [1, 0, 0], [0, 0, 0]]
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
[[1, 1, 0], [0, 0, 0], [1, 0, 0]]
Sign up to request clarification or add additional context in comments.

6 Comments

Tkx. Yes, plenty of duplicates here. The ideal solution should skip each "1" every 3 places to avoid duplicates...
It's not a big deal. I can eliminate them if I form a set of these elements. Unfortunately, it's possible to form a set only if all these elements are hashable. To resolve it, I need to replace all the lists with tuples.
Tks, seems perfect now :-)
The following problem you posted seems quite interesting because it seems hard for me to create iterations with no repetitions included. I feel like little bit cheating while using these del and set commands. Just try to be more clear to attract more opinions on this answer next time.
Well, I've tried different set, and doesn't work :-(, but the speed seems fantastic to me. I've tried your script with n=6 (six "1" in the d list, and d lenght = 24 (so, 6 times "1" and 18 times "0"). I've tried to change the numer "2" in the instruction range(len(d)-2-n*m with different values, and don't work. Where this "2" come from? I guessd it was (n-1) of the first example I gave, with n=3, but it seems I'm wrong. Can you clarify, pls?
|
1

Thet's how you can get permutations:

from itertools import permutations 
permut = permutations([1,1,1,0,0,0,0,0,0]) 

for i in list(permut): 
    print(i)

If you just want to delete all duplicates you may use sumpy:

from sympy.utilities.iterables import multiset_permutations
list(multiset_permutations([1,1,1,0,0,0,0,0,0]))

If something other needed - feel free to ask.

1 Comment

Using permutations, I get all of the permutations. Maybe I need to explain the problem better. Let's say I have 3 pot, and each pot can contains up to 3 balls. So I can have 3 balls in the first pot (=(1,1,1,0,0,0,0,0,0), 2 balls in the first pot, 1 ball in the second pot, 0 ball in the first pot, 2 balls in the second pot, and so on.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.