9
\$\begingroup\$

Given a string of uppercase characters, return a string corresponding to the next item in the following series:

A, B, ..., Z, AA, AB, ..., AZ, BA, ..., BZ, ..., ZZ, AAA, ...

My code:

def increment_char(c):
    """
    Increment an uppercase character, returning 'A' if 'Z' is given
    """
    return chr(ord(c) + 1) if c != 'Z' else 'A'


def increment_str(s):
    lpart = s.rstrip('Z')
    if not lpart:  # s contains only 'Z'
        new_s = 'A' * (len(s) + 1)
    else:
        num_replacements = len(s) - len(lpart)
        new_s = lpart[:-1] + increment_char(lpart[-1])
        new_s += 'A' * num_replacements
    return new_s

Proof my code works according to the specification I gave above:

In [4]: increment_str('A')
Out[4]: 'B'

In [5]: increment_str('Z')
Out[5]: 'AA'

In [6]: increment_str('AA')
Out[6]: 'AB'

In [7]: increment_str('AZ')
Out[7]: 'BA'

In [8]: increment_str('ZZ')
Out[8]: 'AAA'

One thing I would ask you ignore is whether or not you think s and new_s (but only those two) are good names for identifiers, because they are not present in the real code (only the trimmed down version for here). All other suggestions, bug reports, etc., are welcome.

\$\endgroup\$
11
  • 1
    \$\begingroup\$ How much have you trimmed from the code to post it here? \$\endgroup\$
    – Malachi
    Aug 13, 2015 at 21:43
  • \$\begingroup\$ In the real code, increment_str isn't dealing with strings like 'AA', 'AB', etc. It's dealing with longer strings and parsing that bit out. I have removed all the code dealing with the rest of that string and presented a simpler function. The code is exact except for the two changes I mentioned in the post, just out of context. This is also why increment_str doesn't have a docstring here. \$\endgroup\$ Aug 13, 2015 at 21:48
  • \$\begingroup\$ This looks like base 26. How about going from "base 26 " to int, increment, and go back? \$\endgroup\$
    – Caridorc
    Aug 13, 2015 at 21:49
  • 1
    \$\begingroup\$ @Two-BitAlchemist The more the code, the more real and helpful the review can be. 100s of lines are welcome if properly explained. \$\endgroup\$
    – Caridorc
    Aug 13, 2015 at 21:51
  • \$\begingroup\$ @Caridorc I've never worked in base 26, though I do notice the similarity to the way positional numbering works. However, I don't think Python's built-in int function uses 'A-Z' as the base 26 "digits". int('Z', 26) raises a ValueError for me in Python 2.7. \$\endgroup\$ Aug 13, 2015 at 21:52

1 Answer 1

3
\$\begingroup\$

A slight simplification of the if else structure is possible:

def increment_str(s):
    lpart = s.rstrip('Z')
    num_replacements = len(s) - len(lpart)
    new_s = lpart[:-1] + increment_char(lpart[-1]) if lpart else 'A'
    new_s += 'A' * num_replacements
    return new_s
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.