1

Number permutations function, creates a list of all possible arrangements. Worked on this code for a while, it works well and I'm trying to find a shorter an more efficient way of writing it.

a = [3,7,9]
perms = lambda a:list(sorted(z) for z in map(lambda p:dict.fromkeys([str(sum(v* (10**(len(p) -1 - i)) for i,v in enumerate(item))).zfill(len(a)) for item in itertools.permutations(p)]).keys(), [[int(x) for x in ''.join(str(i) for i in a)]]))[0]

The code returns:

['379', '397', '739', '793', '937', '973']

You can also input numeric string variable

a = '468'
perms(a)
['468', '486', '648', '684', '846', '864']

This is code is different, instead of returning tuples or list. It returns a list of results in string format. Also, you are allowed to input numeric strings, tuples or lists. Trust me I've checked any duplicates before posting.

The triple digits work pretty well

perms('000')
['000']

Other codes produces this

['000', '000', '000', '000', '000', '000']

Also, this code returns an ordered list.

QuantumTraveler
  • 271
  • 1
  • 8
  • 1
    Possible duplicate of [How to generate all permutations of a list in Python](http://stackoverflow.com/questions/104420/how-to-generate-all-permutations-of-a-list-in-python) – Saeid Dec 04 '15 at 22:05
  • 2
    If you are allowed to use modules, then : https://docs.python.org/2/library/itertools.html?highlight=itertools#itertools.permutations – Iron Fist Dec 04 '15 at 22:07
  • I found this article extremely helpful for learning how to generate permutations. http://sahandsaba.com/combinatorial-generation-using-coroutines-in-python.html – Marcel Wilson Dec 04 '15 at 22:14
  • @ Marcel Wilson The article is simple and easy to follow, I provided examples and results, and what I am looking for. The list is sorted from smallest to largest, don't you notice that in the results. My objective is to find a more efficient way at writing this code. What isn't there to understand about this article. – QuantumTraveler Dec 04 '15 at 22:42

1 Answers1

1

You are already using itertools.permutations, why not just:

def perms(iterable):
    return [''.join(p) for p in (map(str, perm) for perm in itertools.permutations(iterable))]

>>> perms('123')
# Result: ['123', '132', '213', '231', '312', '321']

Update: If you wish to avoid duplicates, you can extend the functionality like so by using a set, as elaborated on in Why does Python's itertools.permutations contain duplicates? (When the original list has duplicates)

def unique_perms(iterable):
    perm_set = set()
    permutations = [i for i in itertools.permutations(iterable) if i not in perm_set and not perm_set.add(i)]
    return [''.join(p) for p in (map(str, perm) for perm in permutations)]

This is still significantly faster than the posters original method, especially for examples like '000' and is stable (preserves permutation order).

Community
  • 1
  • 1
lemonhead
  • 5,328
  • 1
  • 13
  • 25
  • ok, what's the issue? Seems to fit your spec and example use cases – lemonhead Dec 04 '15 at 22:22
  • Code works for me. And it's more than 2x faster. x 100000: 2.33799177202 perms x 100000: 0.75015824786 – Marcel Wilson Dec 04 '15 at 22:24
  • @Marcel Wilson, awesome thanks for checking that. I think OP was perhaps saying in comment that they didn't want duplicates, but I'll wait to hear confirmation on that before updating my answer. – lemonhead Dec 04 '15 at 22:28
  • Confirmed in question update, I'll update my answer. – lemonhead Dec 04 '15 at 22:29
  • iter is probably not the best variable name, probaby better to also yield each value – Padraic Cunningham Dec 04 '15 at 22:36
  • @lemonhead Just wrap the returned list in set() – Marcel Wilson Dec 04 '15 at 22:40
  • 1
    @MarcelWilson, doing the `list(set(x))` trick certainly works, but I updated with another way which preserves the original order given by `itertools.permutations` – lemonhead Dec 04 '15 at 22:45
  • @PadraicCunningham, for the general case I would certainly agree that it makes sense to return a generator instead of a list but I was just matching the interface for the OPs original function. – lemonhead Dec 04 '15 at 22:47
  • The second code should be put in a dark hole and never allowed surface again! Don;t use list comps for side effects and creating another list is now keeps almost two full copies of the data – Padraic Cunningham Dec 04 '15 at 22:51
  • That was just my choice for an efficient way of removing duplicates while preserving order without using something like an ordered set, e.g. see http://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-in-python-whilst-preserving-order for whichever style you feel is most clear. – lemonhead Dec 04 '15 at 23:01