0

I hope it's Monday-itis kicking in at the moment, but something I feel should be quite easy - or at least elegant - is giving me a brain fart. The use case is this:

Find all possible combinations of a specific word, where letters can be any case or replaced with letters. For instance:

Word: 'Password' Combinations: 'PASSWORD', 'P@ssw0rd', 'p@55w0rD' ...

I do not want to write 7 loops to find this out, even though it's a once off script we'll never ever use again.

Josh Smeaton
  • 47,939
  • 24
  • 129
  • 164
  • Does this answer your question? [Find all upper, lower and mixed case combinations of a string](https://stackoverflow.com/questions/11144389/find-all-upper-lower-and-mixed-case-combinations-of-a-string) – iacob Mar 27 '21 at 15:07

4 Answers4

5
import itertools

places = [
    "Pp",
    "Aa@",
    "Ss5",
    "Ss5",
    "Ww",
    "Oo0",
    "Rr",
    "Dd",
]

for letters in itertools.product(*places):
    print "".join(letters)

If you need to handle arbitrary words, then you'll need to write code to create the places list from the string.

Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • I had tried `itertools.product`, but didn't realise it could take several iterables. I knew it was this easy, thank you. – Josh Smeaton Jun 25 '12 at 01:42
3

The main issue with this problem, is that not all letters can be translated to symbols or numbers. You have to create a dictionary where the key is a lower case letter and the value is a list of all possible replacement of that letter:

{'a':['a','A','@'],...,'s':['s','S','5'],...,}

Once your dictionary is built, the rest is just a matter of a simple Cartesian product of the different lists in the right order.

Samy Arous
  • 6,794
  • 13
  • 20
2

I'd use itertools.product:

import itertools
symbols = dict(a="@", s="5", o="0")  # char -> str
text = "password"
print list(itertools.product(*[[letter, letter.upper()] + list(symbols.get(letter, "")) for letter in text.lower()])
ecatmur
  • 152,476
  • 27
  • 293
  • 366
1

itertools.product is what you're searching for:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from itertools import product

def getAllCombinations(password):
    leet = ["Aa@","Bb","Cc", "Dd","Ee","Ff","Gg","Hh","Ii","Jj","Kk",
            "Ll","Mm","Nn","Oo0","Pp","Qq","Rr","Ss5","Tt","Uu","Vv",
            "Ww","Xx","Yy","Zz"]

    getPlaces = lambda password: [leet[ord(el.upper()) - 65] for el in password]

    for letters in product(*getPlaces(password)):
        yield "".join(letters)

for el in getAllCombinations("Password"):
    print el

If you are curious what the asterisk * means, here you are: foggy on asterisk in python

Community
  • 1
  • 1
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958