添加前面添加一个字符的字符

时间:2013-07-31 08:38:30

标签: python algorithm

我正在尝试实现的是一个将字符串递增一个字符的函数,例如:

'AAA' + 1 = 'AAB'
'AAZ' + 1 = 'ABA'
'ZZZ' + 1 = 'AAAA'

我已经为前两种情况实现了功能,但我想不出第三种情况的任何解决方案。

这是我的代码:

def new_sku(s):
    s = s[::-1]
    already_added = False
    new_sku = str()

    for i in s:
        if not already_added:
            if (i < 'Z'):
                already_added = True
            new_sku += chr((ord(i)+1)%65%26 + 65)
        else:
            new_sku += i

    return new_sku[::-1]

有什么建议吗?

10 个答案:

答案 0 :(得分:9)

如果您正在处理bijective numeration,那么您可能已经(或应该)具有转换为/从双射表示的功能;只需转换为整数,增加它,然后转换回来就会轻松得多:

def from_bijective(s, digits=string.ascii_uppercase):
    return sum(len(digits) ** i * (digits.index(c) + 1)
               for i, c in enumerate(reversed(s)))

def to_bijective(n, digits=string.ascii_uppercase):
    result = []
    while n > 0:
        n, mod = divmod(n - 1, len(digits))
        result += digits[mod]
    return ''.join(reversed(result))

def new_sku(s):
    return to_bijective(from_bijective(s) + 1)

答案 1 :(得分:3)

怎么样?

def new_sku(s):
    s = s[::-1]
    already_added = False
    new_sku = str()

    for i in s:
        if not already_added:
            if (i < 'Z'):
                already_added = True
            new_sku += chr((ord(i)+1)%65%26 + 65)
        else:
            new_sku += i

    if not already_added: # carry still left?
        new_sku += 'A'

    return new_sku[::-1]

示例运行: -

$ python sku.py Z
AA
$ python sku.py ZZZ
AAAA
$ python sku.py AAA
AAB
$ python sku.py AAZ
ABA

答案 2 :(得分:3)

你必须想到'AAA','ZZZ',......作为你操纵价值的代表。

首先,解析值:

val = sum(pow(26, i) * (ord(v) - ord('A') + 1) for i, v in enumerate(value[::-1]))

然后,为它增加价值:

val = val + 1

修改

最终值由:

给出
res = ""
while val > 0:
     val, n = divmod(val - 1, 26)
     res = chr(n+ord('A')) + res

缺少零表示要求传递给divmod的值在每个回合处递减,我没有找到一种方法来处理列表解析。

修改

而不是ord()chr(),可以使用string.ascii_uppercase.index()string.ascii_uppercase[]

答案 3 :(得分:2)

你可以在这里使用一些递归:

def new_sku(s):
    s = s[::-1]
    new_s = ''
    return expand(s.upper(), new_s)[::-1]

import string
chars = string.ascii_uppercase

def expand(s, new_s, carry_forward=True):

    if not s:
        new_s += 'A' if carry_forward else ''
        return new_s

    new_s += chars[(ord(s[0]) - ord('A') + carry_forward) % 26]

    # Slice the first character, and expand rest of the string
    if s[0] == 'Z': 
        return expand(s[1:], new_s, carry_forward)
    else:
        return expand(s[1:], new_s, False)


print new_sku('AAB')
print new_sku('AAZ')
print new_sku('ZZZ')
print new_sku('aab')
print new_sku('aaz')
print new_sku('zzz')

输出:

AAC
ABA
AAAA
AAC
ABA
AAAA

答案 4 :(得分:1)

我会像携带底座26一样加入它。

所以从字符串的右边开始,添加1.如果它到达Z,则换行到A并将下一个最左边的字符向上碰撞一个。如果最左边的字符到达Z,则在字符串的左侧添加A.

s = ["Z","Z","Z"]
done = 0

index = len(s) - 1
while done == 0:
    if s[index] < "Z":
        s[index] = chr(ord(s[index]) + 1)
        done = 1
    else:
        s[index] = "A"
        if index == 0:
            s = ["A"] + s
            done = 1
        else:
            index = index - 1

print s

答案 5 :(得分:1)

检查字符串是否全部为Z,如果是,请将其替换为长度为len(s) + 1的字符串,仅包含A s:

if s == "Z" * len(s):
    return "A" * (len(s) + 1)

答案 6 :(得分:1)

alp='ABCDEFGHIJKLMNOPQRSTUVWXYZA'
def rec(s):
    if len(s)==0:return 'A'
    last_letter=s[-1]
    if last_letter=='Z':return rec(s[:-1])+'A'
    return s[:-1]+alp[(alp.find(last_letter)+1)]

结果

>>> rec('AAA')
'AAB'
>>> rec('AAZ')
'ABA'
>>> rec('ZZZ')
'AAAA'
>>> rec('AZA')
'AZB'

答案 7 :(得分:1)

这个怎么样?作为处理字符串越来越长的一种简单方法,你可以在前面加上'@'并在它没有增加的情况下将其删除:

>>> def new_sku(s):
    def increment(s):
        if s.endswith('Z'):
            return increment(s[:-1])+'A'
        else:
            return s[:-1]+chr(ord(s[-1])+1)
    t = increment('@'+s)
    return t.lstrip('@')

>>> new_sku('AAA')
'AAB'
>>> new_sku('AAZ')
'ABA'
>>> new_sku('ZZZ')
'AAAA'

如果递归令你担心,那么你可以按照你已经做过的方式展平它,但仍然使用添加和剥离的'@'字符。

答案 8 :(得分:0)

您可以使用for-else循环:

from string import ascii_uppercase as au

def solve(strs):
    lis = []
    for i, c in enumerate(strs[::-1], 1):
        ind = au.index(c) + 2
        lis.append(au[(ind%26)-1])
        if ind <= 26:
            break
    else:
        # This will execute only if the for-loop didn't break.
        lis.append('A')

    return strs[:-1*i] + "".join(lis[::-1])

print solve('AAA')
print solve('AAZ')
print solve('ZZZ')
print solve('AZZZ')
print solve('ZYZZ')
print solve('ZYYZZ')

<强>输出:

AAB
ABA
AAAA
BAAA
ZZAA
ZYZAA

答案 9 :(得分:0)

我们可以看到完全有3个条件,你可以迭代字符串并处理其中一个条件。 您可以使用string.ascii_uppercase而不是chr和ord

import string
def add(s):
    s = list(s)[::-1]
    for index, char in enumerate(s):
        if char != "Z":
            s[index] = string.ascii_uppercase[string.ascii_uppercase.index(char) + 1]
            return s[::-1]
        elif char == "Z" and (index != len(s) - 1):
            s[index] = "A"
        elif char == "Z" and (index == len(s) - 1):
            s[index] = "A"
            return ["A"] + s[::-1]