The task: Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.

and my solution:

import itertools
letters_stack = list('abcdefghijklmnopqrstuvwxyz')
keypad_dict = {}
for num in range(2, 10):
    size = 3
    if num in [7, 9]:
        size = 4
    keypad_dict[str(num)] = letters_stack[:size]
    letters_stack = letters_stack[size:]

def aux(numbers):
    if len(numbers) == 1:
        return keypad_dict[numbers[0]]
    return itertools.product(keypad_dict[numbers[0]],  iletters(numbers[1:]))    

def iletters(numbers):
    assert len(numbers) > 0
    return [''.join(x) for x in aux(numbers)]

print list(iletters('234'))
# ['adg', 'adh', 'adi', 'aeg', 'aeh', 'aei', 'afg', 'afh', 'afi', 'bdg', 'bdh', 'bdi', 'beg', 'beh', 'bei', 'bfg', 'bfh', 'bfi', 'cdg', 'cdh', 'cdi', 'ceg', 'ceh', 'cei', 'cfg', 'cfh', 'cfi']
  • \$\begingroup\$ Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers. \$\endgroup\$
    – Vogel612
    Jul 24, 2018 at 19:54
  • \$\begingroup\$ I know. but it was actually a typo, I copied the solution from leetcode which requires a strange scaffold class \$\endgroup\$ Jul 24, 2018 at 20:01

2 Answers 2


You can set the keypad lookup as a constant instead of computing it dynamically. Setting it up as constant makes it clearer that what your intent is.

    '2': 'abc',
    '3': 'def',
    '4': 'ghi',
    '5': 'jkl',
    '6': 'mno',
    '7': 'pqrs',
    '8': 'tuv',
    '9': 'wxyz'}

itertools.product can accept multiple lists. And in python, you can use * to unpack an iterable into positional arguments, and ** to unpack as keyword arguments.

To sum up:

def t9_mode(numbers):
    if len(numbers) == 1:
        return KEYPAD[numbers[0]]
    maps = map(KEYPAD.get, numbers)
    return [''.join(_) for _ in itertools.product(*maps)]

does the job.


Python allows indexing of strings, for instance 'abcdefghijklmnopqrstuvwxyz'[3] returns 'd', so you don't need to turn your string into a list. I would just hardcode the keys: keypad = {1:'abc',2:'def' ...]. You spent more code generating keypad_dict than it would take to just declare it.

Having aux and iletters be programs that recursively call each other is making things way more complicated than they need to be. You can just do [''.join(_) for _ in itertools.product(keypad[__] for __ in numbers)]

  • \$\begingroup\$ to declare it is probably more error-prone, but it's quite subjective \$\endgroup\$ Jul 24, 2018 at 19:30
  • \$\begingroup\$ >call each other sorry, it was a typo. fixed it \$\endgroup\$ Jul 24, 2018 at 19:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.