If an order of strings in the result array doesn't matter and all chars from the initial string are in the substitution array then:
#!/usr/bin/env python
from itertools import product
def allreplacements(seed, replacement_chars):
assert all(c in replacement_chars for c in seed)
for aset in product(replacement_chars, repeat=len(seed)):
yield ''.join(aset)
print(list(allreplacements('ba', 'a b c d'.split())))
# ['aa', 'ab', 'ac', 'ad', 'ba', 'bb', 'bc', 'bd', 'ca', 'cb', 'cc',
# 'cd', 'da', 'db', 'dc', 'dd']
Here's a solution for a general case. Replacements are performed in a lexicographic order:
#!/usr/bin/env python
from itertools import product
def allreplacements(seed, replacement_chars):
"""Generate all possible replacements (with duplicates)."""
masks = list(product(range(2), repeat=len(seed))) # e.g., 00 01 10 11
for subs in product(replacement_chars, repeat=len(seed)):
for mask in masks:
# if mask[i] == 1 then replace seed[i] by subs[i]
yield ''.join(s if m else c for s, m, c in zip(subs, mask, seed))
def del_dups(iterable):
"""Remove duplicates while preserving order.
http://stackoverflow.com/questions/89178/in-python-what-is-the-fastest-algorithm-for-removing-duplicates-from-a-list-so#282589
"""
seen = {}
for item in iterable:
if item not in seen:
seen[item] = True
yield item
print(list(del_dups(allreplacements('ba', 'abcd'))))
print(list(del_dups(allreplacements('ef', 'abcd'))))
# ['ba', 'aa', 'bb', 'ab', 'bc', 'ac', 'bd', 'ad', 'ca', 'cb', 'cc',
# 'cd', 'da', 'db', 'dc', 'dd']
# ['ef', 'ea', 'af', 'aa', 'eb', 'ab', 'ec', 'ac', 'ed', 'ad', 'bf',
# 'ba', 'bb', 'bc', 'bd', 'cf', 'ca', 'cb', 'cc', 'cd', 'df', 'da',
# 'db', 'dc', 'dd']