rajat maan
rajat maan

Reputation: 171

How to increment alphanumeric number in python?

I am creating a passkey of 16 alphanumeric characters where I am generating starting 4 digits with A001, A002, A003 till A999. Once it goes till A999, the alphabet will auto increase to B and digits will again start with 001. And the same process will go till Z999. Once the A-Z series will over, then it will start with AA01 and so on. How to do this thing in python? As I am new in python so I tried it on my own and also tried some examples but I am unable to make the increment of characters. Any ideas or thoughts would be greatly appreciated.

Many thanks

rec=0
new_list16 = []
def autoIncrement():
    global rec
    first = 'A'
    i = chr(ord(first))
    new_list16.append(i)

    while True:
        pStart = 1 #adjust start value, if req'd 
        pInterval = 1 #adjust interval value, if req'd
        if (rec == 0):
            rec += pStart
        else:
            rec = rec + pInterval
        return str(rec).zfill(3)
#print(autoIncrement())
new_list16.append(autoIncrement())

print(*new_list16, sep = '')

Upvotes: 4

Views: 2801

Answers (5)

rajat maan
rajat maan

Reputation: 171

Thank you for the solutions you had provided. But I tried something exactly which I want for my question. Please check it and give your comments on it.

def full_format(i):
    # limit of first range is 26 letters (A-Z) times 999 numbers (001-999)
    if i < 26 * 999:
        c,n = divmod(i,999)   # quotient c is index of letter 0-25, remainder n is 0-998
        c = chr(ord('A') + c) # compute letter
        n += 1
        return f'{c}{n:03}'
    # After first range, second range is 26 letters times 26 letters * 99 numbers (01-99)
    elif i < 26*999 + 26*26*99:
        i -= 26*999               # remove first range offset
        cc,n = divmod(i,99)       # remainder n is 0-98, use quotient cc to compute two letters
        c1,c2 = divmod(cc,26)     # c1 is index of first letter, c2 is index of second letter
        c1 = chr(ord('A') + c1)   # compute first letter
        c2 = chr(ord('A') + c2)   # compute second letter
        n += 1
        return f'{c1}{c2}{n:02}'
    else:
        raise OverflowError(f'limit is {26*999+26*26*99}')

for i in range(92880, 92898):
    print(full_format(i))

Upvotes: 0

tobias_k
tobias_k

Reputation: 82899

Going from A999 to B001 instead of B000 really messes things up a bit, but you can still use this for the A-Z part, and a simple modulo operation for the numbers.

def excel_format(num):
    # see https://stackoverflow.com/a/182924/1639625
    res = ""
    while num:
        mod = (num - 1) % 26
        res = chr(65 + mod) + res
        num = (num - mod) // 26
    return res

def full_format(num, d=3):
    chars = num // (10**d-1) + 1 # this becomes   A..ZZZ
    digit = num %  (10**d-1) + 1 # this becomes 001..999
    return excel_format(chars) + "{:0{}d}".format(digit, d)

for i in range(10000):
    print(i, full_format(i, d=2))

Number of digits in the numeric part is controlled with the optional d parameter. I'll use 2 for purpose of demonstration, but 3 works just as well.

0 A01
...
98 A99
99 B01
...
2573 Z99
2574 AA01
...
9998 CW99
9999 CX01

Upvotes: 2

Booboo
Booboo

Reputation: 44148

This is not quite what you are asking for, but if your requirement is for 4-character "sequential" strings, let me suggest a far more simpler approach. Why not simply used base 36 numbers? That is, have your numbers go from 0, 1, 2, ... A, B, C, ... Z, 10, 11, 12, ... 1Z, ... Then to convert one of the base 36 strings to an int it is simply:

n = int('12AV', 36)

And to convert an int to a base n string:

def baseN(num, base, numerals="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
      return ((num == 0) and numerals[0]) or (baseN(num // base, base, numerals).lstrip(numerals[0]) + numerals[num % base])

Putting it all together:

n = int('12AV', 36)
s = baseN(n + 1, 36)
print(s)

Prints:

12AW

You can, of course, start with 'A001' if you need to. You will then go to A00Z after 35 iterations. You will end up generating the same numbers as in your original method, just in a different order.

Upvotes: 1

wogsland
wogsland

Reputation: 9508

This probably needs to be tested and refactored more, but here's a start for you:

def leadingZeros(number, digits):
    numberString = str(number)
    for digit in range(1, digits):
        if number < 10**digit:
            numberString = '0' + numberString
    return numberString


def autoIncrement(oldNumber):
    order = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ!'
    lastDigitOrder = order.find(oldNumber[3])
    newNumber = ''
    if order.find(oldNumber[1]) <= 9:
        # 3 digit number
        number = int(oldNumber[1:]) + 1
        letter = oldNumber[0]
        if 1000 == number:
            letterOrder = order.find(oldNumber[0])
            letter = order[letterOrder + 1]
        newNumber = letter + leadingZeros(number % 1000, 3)
    elif order.find(oldNumber[2]) <= 9:
        # 2 digit number
        number = int(oldNumber[2:]) + 1
        letters = oldNumber[0:2]
        if 100 == number:
            letterOrder = order.find(oldNumber[1])
            letter = order[letterOrder + 1]
            letters = oldNumber[0] + letter
        newNumber = letters + leadingZeros(number % 100, 2)
    elif order.find(oldNumber[3]) <= 9:
        # 1 digit number
        number = int(oldNumber[3]) + 1
        letters = oldNumber[0:3]
        if 10 == number:
            letterOrder = order.find(oldNumber[2])
            letter = order[letterOrder + 1]
            letters = oldNumber[0:2] + letter
        newNumber = letters + leadingZeros(number % 10, 1)
    else:
        # just letters
        print(oldNumber)
        letterOrder = order.find(oldNumber[3])
        letter = order[letterOrder + 1]
        newNumber = oldNumber[0:3] + letter

    # if one of the digits has gone past Z then we need to update the letters
    if '!' == newNumber[3]:
        # past Z in 4th digit
        letterOrder = order.find(oldNumber[2])
        newNumber = newNumber[0:2] + order[letterOrder + 1] + 'A'
    if '!' == newNumber[2]:
        # past Z in 3rd digit
        letterOrder = order.find(oldNumber[1])
        newNumber = newNumber[0:1] + order[letterOrder + 1] + 'A' + newNumber[3]
    if '!' == newNumber[1]:
        # past Z in 2nd digit
        letterOrder = order.find(oldNumber[0])
        newNumber = order[letterOrder + 1] + 'A' + newNumber[2:]

    return newNumber


print(autoIncrement('A999'))
print(autoIncrement('AA99'))
print(autoIncrement('AAA9'))
print(autoIncrement('AAAA'))
print(autoIncrement('AZZ9'))

Upvotes: 1

Awaish Kumar
Awaish Kumar

Reputation: 557

def auto_increment(number):
    if number == 'ZZZZ':
        return 'ZZZZ'

    digits = "".join([i for i in number if i.isdigit()])
    chars = "".join([i for i in number if not i.isdigit()])
    if int(digits) == int('9' * len(digits)):
        digits = "000"
        new_char = [ord(i) for i in chars]
        if new_char[-1] % ord('Z') == 0:
            new_char = "".join([chr(i) for i in new_char]) + 'A'
        else:
            new_char[-1] = new_char[-1] + 1
            new_char = "".join([chr(i) for i in new_char])
    else:
        new_char = chars

    new_digit = int(digits) + 1
    l = len(new_char) 
    ll = len(str(new_digit))
    new_digit = (("0" * (3-ll)) + str(new_digit))[(l-1):]
    return f"{new_char}{new_digit}"

This function return you the next number, given any number. for example: A999 will return AB01.

you can now just use this function in a loop.

Upvotes: 1

Related Questions