Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

permutations with unique values

itertools.permutations generates where its elements are treated as unique based on their position, not on their value. So basically I want to avoid duplicates like this:

>>> list(itertools.permutations([1, 1, 1])) [(1, 1, 1), (1, 1, 1), (1, 1, 1), (1, 1, 1), (1, 1, 1), (1, 1, 1)] 

Filtering afterwards is not possible because the amount of permutations is too large in my case.

Does anybody know of a suitable algorithm for this?

Thank you very much!

EDIT:

What I basically want is the following:

x = itertools.product((0, 1, 'x'), repeat=X) x = sorted(x, key=functools.partial(count_elements, elem='x')) 

which is not possible because sorted creates a list and the output of itertools.product is too large.

Sorry, I should have described the actual problem.

like image 860
xyz-123 Avatar asked Jun 08 '11 19:06

xyz-123


People also ask

How do you calculate unique permutations?

The number of permutations of n distinct objects, taken r at a time is: Pr = n! / (n - r)! Thus, 210 different 3-digit numbers can be formed from the digits 1, 2, 3, 4, 5, 6, and 7.

What is the time complexity of the sorted unique permutation?

1 Answer. Easy explanation - Best case time complexity of permutation sort occurs when the input array is already sorted. So in such a case we only need to check whether all the elements are sorted which can be done in O(n) time.

How do you enumerate permutations?

A permutation enumeration is to list all permutations in S n . For example, there are 24 permutations of [4]: 1234, 1243, 1324, 1342, 1423, 1432, 2134, 2143, 2314, 2341, 2413, 2431, 3124, 3142, 3214, 3241, 3412, 3421, 4123, 4132, 4213, 4231, 4312, 4321.


2 Answers

class unique_element:     def __init__(self,value,occurrences):         self.value = value         self.occurrences = occurrences  def perm_unique(elements):     eset=set(elements)     listunique = [unique_element(i,elements.count(i)) for i in eset]     u=len(elements)     return perm_unique_helper(listunique,[0]*u,u-1)  def perm_unique_helper(listunique,result_list,d):     if d < 0:         yield tuple(result_list)     else:         for i in listunique:             if i.occurrences > 0:                 result_list[d]=i.value                 i.occurrences-=1                 for g in  perm_unique_helper(listunique,result_list,d-1):                     yield g                 i.occurrences+=1     a = list(perm_unique([1,1,2])) print(a) 

result:

[(2, 1, 1), (1, 2, 1), (1, 1, 2)] 

EDIT (how this works):

I rewrote the above program to be longer but more readable.

I usually have a hard time explaining how something works, but let me try. In order to understand how this works, you have to understand a similar but simpler program that would yield all permutations with repetitions.

def permutations_with_replacement(elements,n):     return permutations_helper(elements,[0]*n,n-1)#this is generator  def permutations_helper(elements,result_list,d):     if d<0:         yield tuple(result_list)     else:         for i in elements:             result_list[d]=i             all_permutations = permutations_helper(elements,result_list,d-1)#this is generator             for g in all_permutations:                 yield g 

This program is obviously much simpler: d stands for depth in permutations_helper and has two functions. One function is the stopping condition of our recursive algorithm, and the other is for the result list that is passed around.

Instead of returning each result, we yield it. If there were no function/operator yield we would have to push the result in some queue at the point of the stopping condition. But this way, once the stopping condition is met, the result is propagated through all stacks up to the caller. That is the purpose of
for g in perm_unique_helper(listunique,result_list,d-1): yield g so each result is propagated up to caller.

Back to the original program: we have a list of unique elements. Before we can use each element, we have to check how many of them are still available to push onto result_list. Working with this program is very similar to permutations_with_replacement. The difference is that each element cannot be repeated more times than it is in perm_unique_helper.

like image 98
Luka Rahne Avatar answered Sep 23 '22 14:09

Luka Rahne


Because sometimes new questions are marked as duplicates and their authors are referred to this question it may be important to mention that sympy has an iterator for this purpose.

>>> from sympy.utilities.iterables import multiset_permutations >>> list(multiset_permutations([1,1,1])) [[1, 1, 1]] >>> list(multiset_permutations([1,1,2])) [[1, 1, 2], [1, 2, 1], [2, 1, 1]] 
like image 35
Bill Bell Avatar answered Sep 22 '22 14:09

Bill Bell