2
\$\begingroup\$

Given a dictionary where 1:a , 2:b ... 26:z. I need to find all the possible letter combinations that can be formed from the three digits.

Either each digit should translate to a letter individually or you can combine adjacent digits to check for a letter. You can't change the order of the digits. For example -

121 translates to aba, au, la;

151 translates to aea, oa;

101 translates to ja;

I was able to get this working but I feel my code is not very "pythonic". I am trying to figure out a more efficient & python-like solution for this problem.

# creating the dict that has keys as digits and values as letters
root_dict = {}
for num in range(0,26):
    root_dict[str(num+1)] = string.ascii_lowercase[num]

# asking user for a three digit number
sequence_to_convert = raw_input('Enter three digit number \n')

# storing all possible permutations from the three digit number
first_permutation = sequence_to_convert[0]
second_permutation = sequence_to_convert[1]
third_permutation = sequence_to_convert[2]
fourth_permutation = sequence_to_convert[0]+sequence_to_convert[1]
fifth_permutation = sequence_to_convert[1]+sequence_to_convert[2]

# checking if the permutations exist in the dict, if so print corresponding letters
if first_permutation in root_dict and second_permutation in root_dict and third_permutation in root_dict:
    print root_dict[first_permutation]+root_dict[second_permutation]+root_dict[third_permutation]
if first_permutation in root_dict and fifth_permutation in root_dict:
    print root_dict[first_permutation]+root_dict[fifth_permutation]
if fourth_permutation in root_dict and third_permutation in root_dict:
    print root_dict[fourth_permutation]+root_dict[third_permutation]
\$\endgroup\$
1
\$\begingroup\$

First, Python 2 is going to be no longer supported in less than a year. If you are starting to learn Python now, learn Python 3. In your code the only differences are that print is a function now and no longer an expression (so you need ()) and that raw_input was renamed input (and the Python 2 input basically no longer exists).

Your building of the root dictionary can be simplified a bit using a dictionary comprehension:

from string import ascii_lowercase

num_to_letter = {str(i): c for i, c in enumerate(ascii_lowercase, 1)}

For the first three different permutations you can use tuple unpacking:

first, second, third = sequence_to_convert

Note that you are currently not validating if the user entered a valid string. The minimum you probably want is this:

from string import digits
digits = set(digits)

sequence_to_convert = input('Enter three digit number \n')
if len(sequence_to_convert) != 3:
    raise ValueError("Entered sequence not the right length (3)")
if not all(x in digits for x in sequence_to_convert):
    raise ValueError("Invalid characters in input (only digits allowed)")

(A previous version of this answer used str.isdigit, but that unfortunately returns true for digitlike strings such as "¹"...)

Your testing and printing can also be made a bit easier by putting the possible permutations into a list and iterating over it:

permutations = [(first, second, third), (first, fifth), (fourth, third)]
for permutation in permutations:
    if all(x in num_to_letter for x in permutation):
        print("".join(map(num_to_letter.get, permutation)))

However, in the end you would probably want to make this more extendable (especially to strings longer than three). For that you would need a way to get all possible one or two letter combinations, and that is hard. It is probably doable with an algorithm similar to this one, but it might be worth it to ask a question on Stack Overflow about this.

\$\endgroup\$
8
  • \$\begingroup\$ There is a pairwise generator in the Itertools recipes. \$\endgroup\$
    – aghast
    Apr 2 '19 at 15:53
  • \$\begingroup\$ @AustinHastings: I'm aware. But here you would need all partitions of a string into groups of one or two characters, not just the current and the following character. \$\endgroup\$
    – Graipher
    Apr 2 '19 at 15:54
  • \$\begingroup\$ itertools.chain(a_string, pairwise(a_string)) \$\endgroup\$
    – aghast
    Apr 2 '19 at 15:56
  • 1
    \$\begingroup\$ @AustinHastings: While this does work for the example with three characters (and so might be worth it to put it into an answer), it fails for more characters. For 1234, it is missing e.g. 12,3,4. \$\endgroup\$
    – Graipher
    Apr 2 '19 at 15:58
  • \$\begingroup\$ Ah, you're right. I was focused on pairing, and neglecting the "whole word" thing. \$\endgroup\$
    – aghast
    Apr 2 '19 at 16:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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