Reputation: 1270
I have just come across an interesting interview style type of question which I couldn't get my head around.
Basically, given a number to alphabet mapping such that [1:A, 2:B, 3:C ...]
, print out all possible combinations.
For instance "123" will generate [ABC, LC, AW]
since it can be separated into 12,3 and 1,23.
I'm thinking it has to be some type of recursive function where it checks with windows of size 1 and 2 and appending to a previous result if it's a valid letter mapping.
If anyone can formulate some pseudo/python code that'd be much appreciated.
Upvotes: 1
Views: 1828
Reputation: 4772
I still am not sure of the description, but this Python script first partitions the num into its 'breaks' then tries each break member as a whole as an index into its corresponding character; then converts each digit of the member into letters of a word. Both contributions are shown before showing the sum total of all conversions to letters/words for the num "123"
>>> import string
>>> mapping ={str(n):ch for n,ch in zip(range(1,27), string.ascii_uppercase)}
>>> num = '123'
>>> [[num[:i], num[i:]] for i in range(len(num)+1)]
[['', '123'], ['1', '23'], ['12', '3'], ['123', '']]
>>> breaks = set(part for part in sum(([num[:i], num[i:]] for i in range(len(num)+1)), []) if part)
>>> breaks
{'123', '12', '3', '1', '23'}
>>> as_a_whole = [mapping[p] for p in breaks if p in mapping]
>>> as_a_whole
['L', 'C', 'A', 'W']
>>> by_char = [''.join(mapping[n] for n in p) for p in breaks]
>>> by_char
['ABC', 'AB', 'C', 'A', 'BC']
>>> everything = sorted(set(as_a_whole + by_char))
>>> everything
['A', 'AB', 'ABC', 'BC', 'C', 'L', 'W']
>>>
Upvotes: 0
Reputation: 388253
So, I wanted to tackle this as well, since it’s actually a cool problem. So here goes my solution:
If we ignore the translations to strings for now, we are essentially looking for partitions of a set. So for the input 123
we have a set {1, 2, 3}
and are looking for partitions. But of those partitions, only those are interesting which maintain the original order of the input. So we are actually not talking about a set in the end (where order doesn’t matter).
Anyway, I called this “ordered partition”—I don’t know if there actually exists a term for it. And we can generate those ordered partitions easily using recursion:
def orderedPartitions(s):
if len(s) == 0:
yield []
return
for i in range(1, len(s)+1):
for p in orderedPartitions(s[i:]):
yield [s[:i]] + p
For a string input '123'
, this gives us the following partions, which is exactly what we are looking for:
['1', '2', '3']
['1', '23']
['12', '3']
['123']
Now, to get back to the original problem which is asking for translations to strings, all we need to do is check each of those partitions, if they contain only valid numbers, i.e. 1 to 26. And if that is the case, translate those numbers and return the resulting string.
import string
def alphaCombinations(s):
for partition in orderedPartitions(str(s)):
# get the numbers
p = list(map(int, partition))
# skip invalid numbers
if list(filter(lambda x: x < 1 or x > 26, p)):
continue
# yield translated string
yield ''.join(map(lambda i: string.ascii_uppercase[i - 1], p))
And it works:
>>> list(alphaCombinations(123))
['ABC', 'AW', 'LC']
>>> list(alphaCombinations(1234))
['ABCD', 'AWD', 'LCD']
>>> list(alphaCombinations(4567))
['DEFG']
Upvotes: 0
Reputation: 1182
As simple as a tree
Let suppose you have give "1261"
Construct a tree with it a Root .
By defining the node(left , right ) , where left is always direct map and right is combo
version suppose for the if you take given Number as 1261
1261 ->
(1(261) ,12(61)) -> 1 is left-node(direct map -> a) 12 is right node(combo-map1,2->L)
(A(261) , L(61)) ->
(A(2(61),26(1))) ,L(6(1)) ->
(A(B(6(1)),Z(1)) ,L(F(1))) ->
(A(B(F(1)),Z(A)) ,L(F(A))) ->
(A(B(F(A)),Z(A)) ,L(F(A)))
so now you have got all the leaf node..
just print all paths from root to leaf node , this gives you all possible combinations .
like in this case
ABFA , AZA , LFA
So once you are done with the construction of tree just print all paths from root to node
which is your requirement .
Upvotes: 1
Reputation: 4723
The following answer recursively tries all possibilities at the current position (there are more than two!) and goes on with the remainder of the string. That's it.
from string import ascii_uppercase
def alpha_combinations(s):
if len(s) == 0:
yield ""
return
for size in range(1, len(s) + 1):
v = int(s[:size])
if v > 26:
break
if v > 0:
c = ascii_uppercase[v - 1]
for ac in alpha_combinations(s[size:]):
yield c + ac
print(list(alpha_combinations(input())))
It expects a number as a string. It gives correct output for 101010
(['AAJ', 'AJJ', 'JAJ', 'JJJ']
). (I think some of the other solutions don't handle zeroes correctly.)
Upvotes: 0
Reputation: 1270
So I managed to hack together an answer, it's not as pythonic as I'd like and there may be some redundancies, but it works with the 123 example to output ABC,AW, and LC.
I'll probably clean it up tomorrow (or if someone wants to clean it up), just posting it in case someone is also working on it and is wondering.
def num_to_alphabet(numbers, ans = ""):
if not numbers:
print ans
numbers = str(numbers)
window = numbers[:2]
alph = string.uppercase
ans = ans[:]
ans2 = ans[:]
window_val = ""
try:
if window[0]:
val = int(numbers[0])-1
if alph[val]:
ans += alph[val]
num_to_alphabet(numbers[1:], ans)
if window[1]:
val = int(window) -1
if alph[val]:
ans2 += alph[val]
if len(window) > 1:
num_to_alphabet(numbers[2:],ans2)
else:
num_to_alphabet(numbers[1:],ans2)
except IndexError:
pass
Upvotes: 1
Reputation: 735
charMap = {'1':'A', '2':'B' ... }
def getNodes(str):
results = []
if len(str) == 0: return results
c = str[0]
results.append(c)
results = results.join(c.join(getNodes(str[1:])))
if str[:2] in charMap.keys(): results = results.join(c.join(getNodes(str[2:])))
return results
def mapout(nodes):
cArray = []
for x in nodes:
cx = ''
for y in x:
cx = cx + charMap.get(y)
cArray.append(cx)
return cArray
res = getNodes('12345')
print(mapout(res))
Untested, but I believe this is along the lines of what you're looking for.
Upvotes: 0