Search code examples
c#alphabet

sequential alphanumeric string generation with 2 alpha and 7 numeric digits


I want to generate alphanumeric number in such way that its first two character represents the alpha and rest 7 digits represent numeric and it should be sequential. for example it should start like this

enter image description here

and once its reaches seven time 9 enter image description hereit should start like

enter image description here

and this process will continue in batches so I need to store the last generated numbers count as well so whenever the window service start again in can take last number count from DB and then generate new numbers.

In my current code I am able to generate it till AA9999999 but after that its change to A10000000 instead of AB0000001 .

Here is my code as follow which I have tried so far .

private static List<char> Values;

        private static readonly char[] AlphaNumericValues = {
        'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z','2','3', '4', '5', '6', '7', '8', '9'
        };
        private static readonly char[] NumericValues = {
         '0','1','2','3', '4', '5', '6', '7', '8', '9'
        };

        private static readonly char[] AlphaOnlyValues = {
          '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'
        };
        private static int ValueCount = 0;


    



switch (selectedItem.suffixType)
            {
                case "alphanumeric":
                    Values = AlphaNumericValues.ToList();
                    ValueCount = AlphaNumericValues.Count();
                    break;
                case "numeric":
                    Values = NumericValues.ToList();
                    ValueCount = NumericValues.Count();
                    break;
                case "alphaonly":
                    Values = AlphaOnlyValues.ToList();
                    ValueCount = AlphaOnlyValues.Count();
                    break;
            }

            if(selectedItem.suffixType== "alphaonly")
            {
                GeneratedNumbers = GenerateValues2(KnoLength, selectedItem).ToList();
            }

and here are two methods as follow

private IEnumerable<Tuple<string, long>> GenerateValues2(int count, PrefixItems selectedItem)
        {
            for (var c = 0; c < count; c++)
            {
                yield return FormatNumber2(KeyCountCurrent++, selectedItem.PrefixSize);

            }

        }
        private static Tuple<string, long> FormatNumber2(long value, int FormatSize)
        {

            var digits = Enumerable.Repeat(Values[0], FormatSize).ToList();

            digits[2] = NumericValues[Convert.ToInt32(0)];
            digits[3] = NumericValues[Convert.ToInt32(0)];
            digits[4] = NumericValues[Convert.ToInt32(0)];
            digits[5] = NumericValues[Convert.ToInt32(0)];
            digits[6] = NumericValues[Convert.ToInt32(0)];
            digits[7] = NumericValues[Convert.ToInt32(0)];
            digits[8] = NumericValues[Convert.ToInt32(0)];


            var slotCount = digits.Count;
            var current = value;
            var count = 0;
            while (current > 0)
            {
                long rem;
                current = Math.DivRem(current, NumericValues.Count(), out rem);
                digits[slotCount - ++count] = NumericValues[Convert.ToInt32(rem)];
            }

            return new Tuple<string, long>(item1: string.Join("", digits), item2: value);
        }

Solution

  • Here is one way:

    const long MaxAlphaNumericValue = 26 * 26 * 10000000L - 1;
    static string ToAlphaNumeric(long value) {
        // validate your input
        if (value < 0 || value > MaxAlphaNumericValue)
            throw new ArgumentException("value");
        // divide by 10000000. Remainder will be numeric part, quotient will be letters part
        var (lettersPart, numbersPart) = Math.DivRem(value, 10000000L);        
        // divide letters part by 26. Remainder will be second letter, quotient will be first letter
        // since we validated input - we can not check for overflow here
        var (first, second) = Math.DivRem(lettersPart, 26);
        var firstLetter = ((char) ('A' + first)).ToString();
        var secondLetter = ((char) ('A' + second)).ToString();
        // just concat what we got        
        return firstLetter + secondLetter + numbersPart.ToString("D7");
    }
    

    4.7.2 version compatible code

    using System;
                        
    public class Program
    {
        public static void Main()
        {
            Console.WriteLine("Hello World");
            Console.WriteLine(ToAlphaNumeric(100000001));
        }
        
        const long MaxAlphaNumericValue = 26 * 26 * 10000000L - 1;
        static string ToAlphaNumeric(long v) 
        {
            long numbersPart;
            var lettersPart = Math.DivRem(v, 10000000L, out numbersPart);        
            long second;
            var first = Math.DivRem(lettersPart, 26, out second);
            var firstLetter = ((char) ('A' + first)).ToString();
            var secondLetter = ((char) ('A' + second)).ToString();
            return firstLetter + secondLetter + numbersPart.ToString("D7");
        }
    }