Skip to content

Instantly share code, notes, and snippets.

@heyalexej
Created July 2, 2014 18:11
Show Gist options
  • Save heyalexej/2f74a9bda5bceec9ad02 to your computer and use it in GitHub Desktop.
Save heyalexej/2f74a9bda5bceec9ad02 to your computer and use it in GitHub Desktop.
create all unique permutations of a word. please comment if you know of more efficient ways to do it.
#!/usr/bin/env python2
import sys
from itertools import permutations
str1 = sys.argv[1]
str2 = int(len(str1))
def uniques(iterable, r=None):
'''weird behavior in itertools permutations.
returns same values multiple times in many cases.
>>> [ ''.join(i) for i in itertools.permutations('to') ]
['to', 'ot']
>>> print(len([ ''.join(i) for i in itertools.permutations('to') ]))
2
>>> [ ''.join(i) for i in itertools.permutations('tol') ]
['tol', 'tlo', 'otl', 'olt', 'lto', 'lot']
>>> print(len([ ''.join(i) for i in itertools.permutations('tol') ]))
6
>>> [ ''.join(i) for i in itertools.permutations('toll') ] # incorrect
['toll', 'toll', 'tlol', 'tllo', 'tlol', 'tllo', 'otll', 'otll', 'oltl',
'ollt', 'oltl', 'ollt', 'ltol', 'ltlo', 'lotl', 'lolt', 'llto',
'llot', 'ltol', 'ltlo', 'lotl', 'lolt', 'llto', 'llot']
>>> print(len([ ''.join(i) for i in itertools.permutations('toll') ])) # incorrect
24
this is due to the chosen algorithm (which in many cases makes sense).
in order to to use it correctly on text, we can store the permutations in a tuple,
check for multiples and return unique value only. it's certainly not the sexiest
way in terms of performance but it gets the job done up to a few million iterations
on commodity hardware.
$ echo qwertzuiop | wc -m
11
$ time ./unique-permutations.py qwertzuiop | wc -l
3628800
real 0m2.208s
user 0m2.221s
sys 0m0.059s
$ echo qwertzuiopa | wc -m
12
$ time ./unique-permutations.py qwertzuiopa | wc -l
479001600
real 5m13.190s
user 5m15.362s
sys 0m7.821s
if you need bigger numbers or more performance, use bigger guns.
more infos:
https://docs.python.org/2/library/itertools.html#itertools.permutations
'''
existent = tuple()
for e in permutations(sorted(iterable), r):
if e > existent:
existent = e
yield e
for p in uniques(str1, str2):
print ''.join(p)
#help(uniques)
@heyalexej
Copy link
Author

$ wget https://gist.githubusercontent.com/heyalexej/2f74a9bda5bceec9ad02/raw/unique-permutations.py -O unique-permutations.py && chmod u+x unique-permutations.py && ./unique-permutations.py test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment