Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Find all strings formed from characters mapped to digits of a number in Python
When working with digit-to-character mappings, we often need to generate all possible string combinations from a given number. This is similar to how old mobile phone keypads worked, where each digit mapped to multiple letters.
Problem Understanding
Given a mapping where each digit (1-9) corresponds to a list of characters, we need to find all possible strings that can be formed from a number. The key constraint is that we must use the same character for every occurrence of a digit in the number.
1 ? ['A', 'B', 'C'] 2 ? ['D', 'E', 'F'] 3 ? ['G', 'H', 'I'] 4 ? ['J', 'K', 'L'] 5 ? ['M', 'N', 'O'] 6 ? ['P', 'Q', 'R'] 7 ? ['S', 'T', 'U'] 8 ? ['V', 'W', 'X'] 9 ? ['Y', 'Z']
For example, if the input is [4,3,5], and we choose 'J' for digit 4, then every occurrence of 4 must use 'J'.
Using itertools.product() Method
The most straightforward approach uses Python's itertools.product() to generate all combinations ?
import itertools
def find_combinations_simple(digits, mapping):
# Get character options for each digit
char_options = [mapping[digit - 1] for digit in digits]
# Generate all combinations
combinations = []
for combo in itertools.product(*char_options):
combinations.append(''.join(combo))
return combinations
# Define the mapping
mapping = [['A', 'B', 'C'], # 1
['D', 'E', 'F'], # 2
['G', 'H', 'I'], # 3
['J', 'K', 'L'], # 4
['M', 'N', 'O'], # 5
['P', 'Q', 'R'], # 6
['S', 'T', 'U'], # 7
['V', 'W', 'X'], # 8
['Y', 'Z']] # 9
digits = [4, 3, 5]
result = find_combinations_simple(digits, mapping)
print(' '.join(result))
JGM JGN JGO JHM JHN JHO JIM JIN JIO KGM KGN KGO KHM KHN KHO KIM KIN KIO LGM LGN LGO LHM LHN LHO LIM LIN LIO
Handling Repeated Digits
When digits repeat in the input, we need to ensure the same character is used for all occurrences ?
def find_combinations_with_repeats(digits, mapping):
# Find unique digits and their positions
unique_digits = []
digit_positions = {}
for i, digit in enumerate(digits):
if digit not in digit_positions:
unique_digits.append(digit)
digit_positions[digit] = []
digit_positions[digit].append(i)
# Get character options for unique digits only
char_options = [mapping[digit - 1] for digit in unique_digits]
combinations = []
for combo in itertools.product(*char_options):
# Build the result string
result = [''] * len(digits)
for i, digit in enumerate(unique_digits):
char = combo[i]
for pos in digit_positions[digit]:
result[pos] = char
combinations.append(''.join(result))
return combinations
# Test with repeated digits
digits = [4, 3, 4, 5] # 4 appears twice
result = find_combinations_with_repeats(digits, mapping)
print(f"Input: {digits}")
print(f"First few combinations: {' '.join(result[:6])}")
print(f"Total combinations: {len(result)}")
Input: [4, 3, 4, 5] First few combinations: JGJM JGJN JGJO JHJM JHJN JHJO Total combinations: 18
Recursive Approach
Here's a recursive solution that builds combinations step by step ?
def find_combinations_recursive(digits, mapping):
def backtrack(index, current_string, char_map):
if index == len(digits):
return [current_string]
digit = digits[index]
combinations = []
if digit in char_map:
# Use the already chosen character for this digit
char = char_map[digit]
combinations.extend(backtrack(index + 1, current_string + char, char_map))
else:
# Try all possible characters for this digit
for char in mapping[digit - 1]:
new_char_map = char_map.copy()
new_char_map[digit] = char
combinations.extend(backtrack(index + 1, current_string + char, new_char_map))
return combinations
return backtrack(0, "", {})
# Test the recursive approach
digits = [2, 3, 2] # 2 appears twice
result = find_combinations_recursive(digits, mapping)
print(f"Input: {digits}")
print(f"Combinations: {' '.join(result)}")
Input: [2, 3, 2] Combinations: DGD DHD DID EGE EHE EIE FGF FHF FIF
Comparison
| Method | Best For | Time Complexity | Space Complexity |
|---|---|---|---|
| itertools.product() | Simple cases, no repeated digits | O(k^n) | O(k^n) |
| Manual handling | Repeated digits, custom logic | O(k^u) | O(k^u) |
| Recursive | Educational, custom constraints | O(k^u) | O(k^u × n) |
Where k = average characters per digit, n = number of digits, u = unique digits
Conclusion
Use itertools.product() for simple cases without repeated digits. For repeated digits, manually handle unique digit mapping to ensure consistency. The recursive approach provides more control but uses more memory due to call stack overhead.
