Solved

Auto increment an alphanumeric id

Posted on 2009-05-06
11
2,179 Views
Last Modified: 2013-12-17
I need to Increment an ID based on the following "array" of characters...

"0123456789BCDFGHJKLMNPQRSTVWXYZ"

The ID starts with a "P" followed by four characters i.e., P0000

increment would like like P0009, P000B, P000C, P000D, P000F...P0019, P001B, and so on...
0
Comment
Question by:revstudio
  • 6
  • 4
11 Comments
 
LVL 31

Expert Comment

by:Frosty555
Comment Utility
Try this out
        private void Form1_Load(object sender, EventArgs e)

        {

            string x = "ZZZZ9";

            MessageBox.Show(incrementString(x));

        }
 

        public string incrementString(string input)

        {
 

            char[] c = input.ToCharArray();

            int i = c.Length -1;
 

            bool overflow = false;

            bool nextdigit = false;

            do

            {

                if( i < 0 ) {

                    nextdigit = true;

                    overflow = false;

                }else{

                    c[i]++;
 

                    if (c[i] == ':') {

                        c[i] = 'A';     // jump from ":" to "A" in ascii table

                    }
 

                    if( c[i] > 'Z' ) {

                        // roll over to next digit

                        c[i] = '0';

                        overflow = true;

                        i--;

                    } else {

                        overflow = false;

                    }

                }

            } while (overflow);
 

            string output;

            if (nextdigit)

            {

                output = String.Concat("1", new string(c));

            }

            else

            {

                output = new string(c);

            }
 

            return output;

        }

Open in new window

0
 
LVL 31

Expert Comment

by:Frosty555
Comment Utility
I don't know if you intended to intentionally skip those letters in your array above.  (e.g. skipping over A, and going straight to B)

If you did, you can put those jumps in the code. See attached.
        public string incrementString(string input)

        {
 

            char[] c = input.ToCharArray();

            int i = c.Length -1;
 

            bool overflow = false;

            bool nextdigit = false;

            do

            {

                if( i < 0 ) {

                    nextdigit = true;

                    overflow = false;

                }else{

                    c[i]++;
 
 

                    // Skipping characters and jumps

                    if (c[i] == ':')

                    {

                        c[i] = 'B';  

                    }

                    if (c[i] == 'E')

                    {

                        c[i] = 'F';

                    }

                    if (c[i] == 'I')

                    {

                        c[i] = 'J';

                    }

                    if (c[i] == 'O')

                    {

                        c[i] = 'P'; 

                    }

                    if (c[i] == 'U')

                    {

                        c[i] = 'V'; 

                    }
 
 

                    if( c[i] > 'Z' ) {

                        // roll over to next digit

                        c[i] = '0';

                        overflow = true;

                        i--;

                    } else {

                        overflow = false;

                    }

                }

            } while (overflow);
 

            string output;

            if (nextdigit)

            {

                output = String.Concat("1", new string(c));

            }

            else

            {

                output = new string(c);

            }
 

            return output;

        }

Open in new window

0
 

Author Comment

by:revstudio
Comment Utility
Had to convert to VB but it doesn't seem to work

If I leave i as integer = c.length -1 (which makes sense to me) then I get and out of bounds error

If i change it to c.length -2 (which doesnt make sense to me) then:

If I pass in a string "P0051" it should increment to "P0052" (this is any easy one) it returns the same value


    Public Function incrementString(ByVal input As String) As String
 

        Dim c As Char() = input.ToCharArray()

        Dim i As Integer = c.Length - 2
 

        Dim overflow As Boolean = False

        Dim nextdigit As Boolean = False

        Do

            If i < 0 Then

                nextdigit = True

                overflow = False

            Else

                System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
 

                ' Skipping characters and jumps

                If c(i) = "A"c Then

                    c(i) = "B"c

                End If

                If c(i) = "E"c Then

                    c(i) = "F"c

                End If

                If c(i) = "I"c Then

                    c(i) = "J"c

                End If

                If c(i) = "O"c Then

                    c(i) = "P"c

                End If

                If c(i) = "U"c Then

                    c(i) = "V"c

                End If
 

                If c(i) > "Z"c Then

                    ' roll over to next digit

                    c(i) = "0"c

                    overflow = True

                    System.Math.Max(System.Threading.Interlocked.Decrement(i), i + 1)

                Else

                    overflow = False

                End If

            End If

        Loop While overflow
 

        Dim output As String

        If nextdigit Then

            output = [String].Concat("1", New String(c))

        Else

            output = New String(c)

        End If
 

        Return output

    End Function

Open in new window

0
 

Author Comment

by:revstudio
Comment Utility
I created a C# test applicaiton and it works fine. Can anyone help me figure out what is wrong in my conversion?
0
 

Author Comment

by:revstudio
Comment Utility
I think it can be resolved with an equivalent to c(i)++

That was the reason for the System.Math.Max(System.Threading.Interlocked.Increment(i), i + 1) and System.Math.Max(System.Threading.Interlocked.Decrement(i), i + 1)
 
 
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:revstudio
Comment Utility
Modified code from http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_23100704.html

Create a Base31 Converter :)

   Function NextID(ByVal InputNumber As String) As String

        Dim J, K, DecimalValue, X, MaxBase, InputNumberLength As Integer

        Dim NumericBaseData, OutputValue As String

        NumericBaseData = "0123456789BCDFGHJKLMNPQRSTVWXYZ"

        MaxBase = (NumericBaseData.Length)
 

        InputNumberLength = InputNumber.Length

        DecimalValue = 0

        For J = 1 To InputNumberLength

            For K = 1 To MaxBase

                If Mid(InputNumber, J, 1) = Mid(NumericBaseData, K, 1) Then

                    DecimalValue = DecimalValue + Int((K - 1) * (MaxBase ^ (InputNumberLength - J)) + 0.5)

                End If

            Next K

        Next J
 

        '*/ Add 1 to Decimal Equivalent of the Current Base31 number /*

        DecimalValue = DecimalValue + 1
 

        ' Convert the Decimal Value + 1 back to Base31 Value /*

        OutputValue = ""

        While DecimalValue > 0

            X = Int(((DecimalValue / 31) - Int(DecimalValue / 31)) * 31 + 1.5)

            OutputValue = Mid(NumericBaseData, X, 1) + OutputValue

            DecimalValue = Int(DecimalValue / 31)

        End While

        Return OutputValue
 

    End Function

Open in new window

0
 
LVL 31

Accepted Solution

by:
Frosty555 earned 250 total points
Comment Utility
revstudio,

See the attached code, worked fine for me. No out of bounds error.

Also note that the NextID() code you just posted fails on any number greater than 7 digits. E.g. incrementing "ZZZZZZZ" fails with an arithmetic overflow.

My function works on strings of unbounded length.
    Public Function incrementString(ByVal input As String) As String
 

        Dim c As Char() = input.ToCharArray()

        Dim i As Integer = c.Length - 1
 

        Dim overflow As Boolean = False

        Dim nextdigit As Boolean = False

        Do

            If i < 0 Then

                nextdigit = True

                overflow = False

            Else

                c(i) = Chr(Asc(c(i)) + 1)
 

                ' Skipping characters and jumps

                If c(i) = "A"c Then

                    c(i) = "B"c

                End If

                If c(i) = "E"c Then

                    c(i) = "F"c

                End If

                If c(i) = "I"c Then

                    c(i) = "J"c

                End If

                If c(i) = "O"c Then

                    c(i) = "P"c

                End If

                If c(i) = "U"c Then

                    c(i) = "V"c

                End If
 

                If c(i) > "Z"c Then

                    ' roll over to next digit

                    c(i) = "0"c

                    overflow = True

                    System.Math.Max(System.Threading.Interlocked.Decrement(i), i + 1)

                Else

                    overflow = False

                End If

            End If

        Loop While overflow
 

        Dim output As String

        If nextdigit Then

            output = [String].Concat("1", New String(c))

        Else

            output = New String(c)

        End If
 

        Return output

    End Function

Open in new window

0
 

Author Closing Comment

by:revstudio
Comment Utility
Thanks for the help.
0
 

Author Comment

by:revstudio
Comment Utility
Solution was missing ...

                ' Skipping characters and jumps
                If c(i) = ":"c Then
                    c(i) = "B"c
                End If
 
0
 
LVL 2

Expert Comment

by:indmillert
Comment Utility
I've been playing with this for a little while now and I guess I don't really understand how it's working because I would like it to run like:

A,B,C,D.....Z,0,1,2,3,4,5,6,7,8,9

I can't seem to tweak the code to work correctly. Can anyone clarify?
0
 
LVL 31

Expert Comment

by:Frosty555
Comment Utility
The code takes advantage of the fact that alphanumeric digits can be represented in ascii using integer values.

http://www.asciitable.com/

So to increment a particular digit, you convert it to its ascii code (e.g. "A"->65), then increment the number (e.g. 65->66), then convert from the ascii code back to an actual letter/number (e.g. 66->"B"). This is done with the ASC() and CHR() functions.

In ASCII, numbers 0-9 come before the uppercase letters A-Z, so that's the pattern it is going to follow.

There is no easy way to modify the above code that I can see to have the numbers come after the letters, since now you can't take advantage of the ASCII table.  So you will need to "reinvent" the wheel and create your own table of digits instead of using ASCII.

You will need to rewrite this line:

c(i) = Chr(Asc(c(i)) + 1)

And have it instead look up the index of the characters from an array that you have defined, increment the index, then re-evaluate the new character using your array. Effectively this is like making your own "table" of letters instead of using the built in ASCII table and rewriting the CHR() and ASC() functions.

c(i) = GetIndexFromLetter(GetLetterFromIndex(c(i)) + 1)

You'll also need to rewrite the "rollover" and "concatenate" parts of the code since those don't line up anymore with what you're trying to do:



Below, you need to instead roll over to the next digit when you hit the number "9", since "9" is the last digit in your sequence. Better yet, you should use the last item in your array of characters.

-------------

                If c(i) > "Z"c Then
                    ' roll over to next digit
                    c(i) = "0"c
                    overflow = True
                    System.Math.Max(System.Threading.Interlocked.Decrement(i), i + 1)
                Else
                    overflow = False
                End If

-------------

And below, you would want to concatenate "A" to the end, since "A" is the first digit in the sequence now instead of "1". Or better yet you should use the 0th index in your array of characters.

-------------

        Dim output As String
        If nextdigit Then
            output = [String].Concat("1", New String(c))
        Else
            output = New String(c)
        End If

-------------
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Total in textboxes 9 35
Help with error message for ReportViewer in VS2015 4 23
Create XML 5 30
Calling stored proc in EDMX 11 17
This article describes relatively difficult and non-obvious issues that are likely to arise when creating COM class in Visual Studio and deploying it by professional MSI-authoring tools. It is assumed that the reader is already familiar with the cla…
Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
This tutorial demonstrates a quick way of adding group price to multiple Magento products.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now