【问题标题】:Increment a char given a sequence给定序列增加一个字符
【发布时间】:2016-08-25 06:52:11
【问题描述】:

给定一个字符序列,按字母顺序返回下一个。

Example: given 'A' it should return 'B', 'Z' -> 'AA', 'ZYZ' -> 'ZZA'

我找到了一个使用模数和数学的相关参考is in c#。 我没有将其转换为 python,而是提出了自己的解决方案。

什么是比下面的更有效的算法方法?

import string
def increment_excel(s=''):
    """
    A->B, Z->AA, AZ->BA, KZZ->LAA
    """
    def wrapped(s):
        if not s: 
            return string.uppercase[0]
        ind = string.uppercase.index(s[-1])
        if ind < len(string.uppercase) - 1: 
            return s[:-1] + string.uppercase[ind + 1]
        return wrapped(s[:-1]) + string.uppercase[0]
    return wrapped(s.upper().replace(' ',''))


increment_excel('TRYME') # -> 'TRYMF'
increment_excel('TRY ZZ') # -> 'TRZAA'
increment_excel('ABCC') # -> 'ABCD'
increment_excel('ZZ Z') # -> 'AAAA'

【问题讨论】:

  • 简单的通用解决方案是那些在base-26中的...转换为base-10,然后添加1...再次转换为base-26...
  • @lok​​esh1729 这种方法有一个小问题。哪个字母对应零?
  • 是的,当数字可以被零整除时,我们必须小心...然后我们必须将余数作为 26 并且商 = 商-1...比如说 52.. 52/26=2 ,所以 q=1,rem=26 给出 AZ
  • 为什么Z 后跟AAZZ 也跟AA
  • ZZ -&gt; AAA 我这边的解释器

标签: python string algorithm


【解决方案1】:

试试:

def increment_excel(s=''):
    arr = list(s.upper().replace(' ', ''))
    if arr:
        arr.reverse()
        n = 1
        for i in range(len(arr)):
            if ord(arr[i])+n <= ord('Z'):
                arr[i] = chr(ord(arr[i]) + n)
                n = 0
            else:
                arr[i] = 'A'
                n = 1
        if n == 1:
            arr.append('A')
        arr.reverse()
    return ''.join(arr)

【讨论】:

    【解决方案2】:

    这是一个只使用字符串操作的解决方案。

    撇开字符串的规范化(大写,去掉空格),该函数本质上是找到由一个可选字母组成的后缀,而不是 Z 后跟任意数量的 Z kbd>s(包括无)。尾随的 Z 全部更改为 A,而 Z 之前的最后一个字符(如果有)递增。最后,如果字符串仅由 Zs 组成,则在前面添加 A

    import re
    import string
    succ_tb = string.maketrans(string.uppercase,
                               string.uppercase[1:]+string.uppercase[0])
    up_tb = string.maketrans(string.lowercase, string.uppercase)
    suff_re = re.compile('(([A-Y]?)Z*)$')
    
    def increment_excel(s):
      return suff_re.sub(
        lambda m: (('' if m.group(2) else 'A') + 
                   m.group(1).translate(succ_tb)),
        s.translate(up_tb, ' '))
    

    【讨论】:

      【解决方案3】:

      请检查我的解决方案,我从我这边测试过,它有效。

      def seqconverter(a):
          def converter(number):
              retval = str()
              while number:
                  x = (number - 1) % 26
                  number = (number - 1) / 26
                  retval = '%s%s' % (chr(x + 65), retval)
              return retval
      
          def numconverter(a):
              res = 0
              for c in a:
                  res *= 26
                  res += ord(c) - 64
              return res
          return converter(numconverter(a) + 1)
      
      if __name__=='__main__':
          print(seqconverter('ZYZ'))
          print(seqconverter('ZZA'))
          print(seqconverter('XY'))
      

      输出:

      ZZA
      ZZB
      XZ
      
      
      ------------------
      (program exited with code: 0)
      Press return to continue
      

      【讨论】:

      • 太糟糕了你的程序永远不会返回'Z'。
      • [convert(i, '') for i in range(50)] ['@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'A', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW']
      • [convert(i, '') for i in range(1,50)] ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH', 'AI', 'AJ', 'AK', 'AL', 'AM', 'AN', 'AO', 'AP', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AV', 'AW']
      • 是的,同意...必须付出更多的努力...现在做不到...但肯定会改善我的答案。
      • @VladNikiporoff 我不明白你的解决方案,这对我来说有点复杂......效率是什么意思?时间,空间?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-19
      相关资源
      最近更新 更多