Print a word with numbers substituted for characters I wrote the following Python program to take 1 word from the user and return certain characters replaced by numbers. Given a dictionary, the program should print all possible combinations of the same word with various characters substituted:

import sys

def main(argv):

    if len(argv) != 2:
        print(f"USAGE: {argv[0]} [word]")
        return

    replacements = {}

    # Populate the known replacements
    replacements['i'] = ['1']
    replacements['e'] = ['3']
    replacements['m'] = ['/v\\']
    replacements['a'] = ['4']
    replacements['r'] = ['2']
    replacements['o'] = ['0']

    print_possibilities(argv[1], replacements, [])


def print_possibilities(s: str, replacements: dict, dupes: list):
    ctr = 0
    tally = 0
    for c in s:
        if c.lower() in replacements:
            tally += 1
    if tally == 0:
        return

    for c in s:
        if c.lower() in replacements:
            for r in replacements[c.lower()]:
                tmp = list(s)
                tmp[ctr] = r
                as_str = ''.join(tmp)
                if as_str in dupes:
                    continue
                print(as_str)
                dupes.append(as_str)
                print_possibilities(as_str, replacements, dupes)
        ctr += 1
    return


if __name__ == '__main__':
    main(sys.argv)


I've tested with python3 replace_word.py mondoman and I get this output:

/v\ondoman
/v\0ndoman
/v\0nd0man
/v\0nd0/v\an
/v\0nd0/v\4n
/v\0nd0m4n
/v\0ndo/v\an
/v\0ndo/v\4n
/v\0ndom4n
/v\ond0man
/v\ond0/v\an
/v\ond0/v\4n
/v\ond0m4n
/v\ondo/v\an
/v\ondo/v\4n
/v\ondom4n
m0ndoman
m0nd0man
m0nd0/v\an
m0nd0/v\4n
m0nd0m4n
m0ndo/v\an
m0ndo/v\4n
m0ndom4n
mond0man
mond0/v\an
mond0/v\4n
mond0m4n
mondo/v\an
mondo/v\4n
mondom4n


I feel that this could be improved to be more performant and more idiomatic and would like a code review.
Think about the problem as a repeated Cartesian product. It allows us
to use the very useful product function from the itertools module:

&gt;&gt;&gt; list(product('ab', 'AB', 'xy'))
[('a', 'A', 'x'), ('a', 'A', 'y'), ('a', 'B', 'x'),
('a', 'B', 'y'), ('b', 'A', 'x'), ('b', 'A', 'y'),
('b', 'B', 'x'), ('b', 'B', 'y')]


So your problem can be solved by replacing each character in the
string with its possible replacemnets and running product on the
result:

import itertools
import sys

def alternatives(ch, repls):
    key = ch.lower()
    if key in repls:
        return [ch, repls[key]]
    return [ch]

def main(argv):
    if len(argv) != 2:
        print(f"USAGE: {argv[0]} [word]")
        return

    # Populate the known replacements
    replacements = {'a' : '4', 'e' : '3', 'i' : '1',
                    'm' : '/v\\', 'o' : '0', 'r' : '2'}

    s = [alternatives(ch, replacements) for ch in argv[1]]
    for it in itertools.product(*s):
        print(''.join(it))

if __name__ == '__main__':
    main(sys.argv)


Note that this version is not exactly identical to your original. If
you enter "mondoman" the program will output "mondoman" as one
combination.