Increment an index that uses numbers and characters (aka Base36 numbers)

2k Views Asked by At

I have a string based code that can be either two or three characters in length and I am looking for some help in creating a function that will increment it.

Each 'digit' of the code has a value of 0 to 9 and A to Z.

some examples:

the first code in the sequence is 000

009 - next code is - 00A
00D - next code is - 00E
AAZ - next code is - AB0

the last code is ZZZ.

Hope this makes some sense.

4

There are 4 best solutions below

2
Martin On BEST ANSWER

Thanks for the advice guys.

This is what I independently came up with.

    private static String Increment(String s)
    {
        String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        char lastChar = s[s.Length - 1];
        string fragment = s.Substring(0, s.Length - 1);

        if (chars.IndexOf(lastChar) < 35)
        {
            lastChar = chars[chars.IndexOf(lastChar) + 1];

            return fragment + lastChar;
        }

        return Increment(fragment) + '0';
    }

I don't know if it is better/worse but seems to work. If anyone can suggest improvements then that is great.

3
Tim Lloyd On

Maintain the counter as an int and increment this. Convert the int to your character representation by modding and dividing by 36 iterativly. Map the modded range (0-35) to 0-Z.

Example

Updated with functions to go in either direction:

internal class Program
{
    const int Base = 36;

    public static void Main()
    {
        Console.WriteLine(ToInt("0AA"));
        Console.WriteLine(ToString(370));
    }

    private static string ToString(int counter)
    {
        List<char> chars = new List<char>();

        do
        {
            int c = (counter % Base);

            char ascii = (char)(c + (c < 10 ? 48 : 55));

            chars.Add(ascii);
        }
        while ((counter /= Base) != 0);

        chars.Reverse();

        string charCounter = new string(chars.ToArray()).PadLeft(3, '0');

        return charCounter;
    }

    private static int ToInt(string charCounter)
    {
        var chars = charCounter.ToCharArray();

        int counter = 0;

        for (int i = (chars.Length - 1), j = 0; i >= 0; i--, j++)
        {
            int chr = chars[i];

            int value = (chr - (chr > 57 ? 55 : 48)) * (int)Math.Pow(Base, j);

            counter += value;
        }

        return counter;
    }

For more variants of conversion code see Quickest way to convert a base 10 number to any base in .NET?.

0
AudioBubble On

Does this do what you need?

public class LetterCounter
{
    private static readonly string[] _charactersByIndex = new string[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "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" };

    public string GetStr(int i)
    {
        if (i < _charactersByIndex.Length)
            return _charactersByIndex[i];

        int x = i / (_charactersByIndex.Length - 1) - 1;
        string a = _charactersByIndex[x];
        string b = GetStr(i - (_charactersByIndex.Length - 1));
        return a + b;
    }
}

}

0
Faraz Ahmed On

Based on @Martin answer, I found some error when two ZZ comes, this makes exception in code

private static String Increment(String s,bool IsFromRecursion=false)
{
    String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    //Added this condition
    if (IsFromRecursion && string.IsNullOrEmpty(number))
    {
         return "1";
    }
    //Added this condition

    char lastChar = s[s.Length - 1];
    string fragment = s.Substring(0, s.Length - 1);

    if (chars.IndexOf(lastChar) < 35)
    {
        lastChar = chars[chars.IndexOf(lastChar) + 1];

        return fragment + lastChar;
    }

    return Increment(fragment,true) + '0';
}

When we call this method we pass first parameter only.