如何根据数字输入生成所有可能的字母组合列表

时间:2013-04-24 05:21:05

标签: python algorithm alphabetical

我刚刚遇到一个有趣的采访风格类型的问题,我无法理解。

基本上,给定一个字母到数字的映射[1:A, 2:B, 3:C ...],打印出所有可能的组合。

例如,“123”将生成[ABC, LC, AW],因为它可以分为12,3和1,23。

我认为它必须是某种类型的递归函数,它检查大小为1和2的窗口,如果它是有效的字母映射,则附加到前一个结果。

如果有人能够制定一些非常受欢迎的伪/ python代码。

6 个答案:

答案 0 :(得分:1)

像树一样简单

假设你给了“1261”

用树构建一棵树。

通过定义节点(左,右),其中左侧始终是直接映射,右侧是组合

版本假设您将给定的数字视为1261

1261 - >

(1(261),12(61)) - > 1是左节点(直接映射 - > a)12是右节点(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)))

所以现在你已经拥有了所有叶子节点..

只打印从根节点到叶节点的所有路径,这为您提供了所有可能的组合。

就像在这种情况下

ABFA,AZA,LFA

因此,一旦完成了树的构造,只需打印从根到节点的所有路径

这是你的要求。

答案 1 :(得分:1)

所以我设法破解了一个答案,它不像我想的那样具有pythonic并且可能有一些冗余,但它适用于123示例输出ABC,AW和LC。

我明天可能会清理它(或者如果有人想要清理它),只需发布​​它以防有人也正在处理它并且想知道。

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

答案 2 :(得分:0)

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))

未经测试,但我相信这与您所寻找的一致。

答案 3 :(得分:0)

以下答案以递归方式尝试当前位置的所有可能性(有两个以上!)并继续使用字符串的其余部分。就是这样。

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())))

它期望一个数字作为字符串。它为101010['AAJ', 'AJJ', 'JAJ', 'JJJ'])提供了正确的输出。 (我认为其他一些解决方案无法正确处理零。)

答案 4 :(得分:0)

所以,我也想解决这个问题,因为它实际上是一个很酷的问题。所以这是我的解决方案:

如果我们暂时忽略对字符串的翻译,我们基本上是在寻找partitions of a set。因此,对于输入123,我们有一个集{1, 2, 3}并且正在寻找分区。但是在那些分区中,只有那些保持原始输入顺序的有趣。所以我们实际上并没有谈论最后的一个集合(顺序无关紧要)。

无论如何,我称之为“有序分区” - 我不知道是否确实存在一个术语。我们可以使用递归轻松生成这些有序分区:

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

对于字符串输入'123',这给了我们以下部分,这正是我们正在寻找的:

['1', '2', '3']
['1', '23']
['12', '3']
['123']

现在,为了回到原来要求翻译成字符串的问题,我们需要做的就是检查每个分区,如果它们只包含有效数字,即1到26.如果是这样的话,翻译这些数字并返回结果字符串。

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))

它有效:

>>> list(alphaCombinations(123))
['ABC', 'AW', 'LC']
>>> list(alphaCombinations(1234))
['ABCD', 'AWD', 'LCD']
>>> list(alphaCombinations(4567))
['DEFG']

答案 5 :(得分:0)

我仍然不确定描述,但是这个Python脚本首先将num分区为其'break',然后将每个break成员作为一个整体尝试作为其相应字符的索引;然后将成员的每个数字转换为单词的字母。在显示所有转换为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']
>>>