简体   繁体   English

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

[英]How to generate a list of all possible alphabetical combinations based on an input of numbers

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. 基本上,给数字一个字母映射,使[1:A, 2:B, 3:C ...]打印出所有可能的组合。

For instance "123" will generate [ABC, LC, AW] since it can be separated into 12,3 and 1,23. 例如,“ 123”将生成[ABC, LC, AW]因为它可以分为12,3和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. 我认为它必须是某种类型的递归函数,其中它会检查大小为1和2的窗口,如果它是有效的字母映射,则会追加到先前的结果中。

If anyone can formulate some pseudo/python code that'd be much appreciated. 如果有人可以制定一些伪/ python代码,将不胜感激。

As simple as a tree 像树一样简单

Let suppose you have give "1261" 假设您给了“ 1261”

Construct a tree with it a Root . 用根构造一棵树。

By defining the node(left , right ) , where left is always direct map and right is combo 通过定义node(left,right),其中left始终是直接映射,right始终是组合

version suppose for the if you take given Number as 1261 版本假设如果您将给定数字设为1261

1261 -> 1261->

(1(261) ,12(61)) -> 1 is left-node(direct map -> a) 12 is right node(combo-map1,2->L) (1(261),12(61))-> 1是左节点(直接映射-> a)12是右节点(combo-map1,2-> L)

(A(261) , L(61)) -> (A(261),L(61))->

(A(2(61),26(1))) ,L(6(1)) -> (A(2(61),26(1))),L(6(1))->

(A(B(6(1)),Z(1)) ,L(F(1))) -> (A(B(6(1)),Z(1)),L(F(1)))->

(A(B(F(1)),Z(A)) ,L(F(A))) -> (A(B(F(1)),Z(A)),L(F(A)))->

(A(B(F(A)),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 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 . 这是您的要求。

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. 因此,我设法找到了一个答案,它不是我想要的Pythonic,并且可能会有一些冗余,但是它可以与123示例一起使用,以输出ABC,AW和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
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. 未经测试,但我相信这与您要寻找的是一致的。

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'] ). 它给出了101010正确输出( ['AAJ', 'AJJ', 'JAJ', 'JJJ'] )。 (I think some of the other solutions don't handle zeroes correctly.) (我认为其他一些解决方案不能正确处理零。)

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 . 如果现在暂时忽略对字符串的转换,则实际上是在寻找set的分区 So for the input 123 we have a set {1, 2, 3} and are looking for partitions. 因此,对于输入123我们有一个集合{1, 2, 3} ,正在寻找分区。 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: 对于字符串输入'123' ,这为我们提供了以下部分,这正是我们要查找的部分:

['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, ie 1 to 26. And if that is the case, translate those numbers and return the resulting string. 现在,回到要求转换为字符串的原始问题,我们需要做的就是检查每个分区,如果它们仅包含有效数字(即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))

And it works: 它的工作原理是:

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

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; 我仍然不确定该描述,但是这个Python脚本首先将num划分为它的“ breaks”,然后尝试将每个break成员作为一个整体作为其对应字符的索引; 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" 在显示数字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']
>>> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM