Vlad M
Vlad M

Reputation: 477

Increment a char given a sequence

Given a sequence of characters, return next following in alphabetical order.

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

One relevant reference using modulo and math i have found is in c#. Instead of converting it into python, i came up with my own solution.

What would be a more effective algorithmic approach than the one below?

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'

Upvotes: 1

Views: 266

Answers (3)

Lokesh Sanapalli
Lokesh Sanapalli

Reputation: 1034

Please check my solution, I tested from my side and it worked.

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

Output:

ZZA
ZZB
XZ


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

Upvotes: 1

rici
rici

Reputation: 241691

Here's a solution which just uses string manipulation.

Leaving aside the normalization of the string (uppercase it, strip blanks), the function essentially finds the suffix consisting of an optional letter other than Z followed by any number of Zs (including none). The trailing Zs are all changed to A, while the last character before the Zs (if any) is incremented. Finally, an A is prepended if the string consists only of Zs.

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

Upvotes: 1

acw1668
acw1668

Reputation: 46669

Try:

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)

Upvotes: 1

Related Questions