Incremental Count Using Alphanumeric Values

by Michael Khalili on October 14, 2009

I’m currently working on a website that needs a URL shortener. In order to have a good shortened URL I must make the most of the path after the domain. The common way to do this, as Bit.ly and others already do, is to have a mix of alphanumeric characters that increment each time a new URL has been created. I’m using Asp.Net and since there’s no built in function or an already published one, I created my own.

This function works by accepting a list of characters to use in the counting process. Each time a new value is needed the function increments the count by going to the next character in the array. I hope to have a lot of traffic so it’s important to be efficient and fast. The resulting code can run thousands of times in just a fraction of a second.

To use the function you need to pass in the current value (or empty string “” if it’s the first time) and a character array of values to use (include lowercase and uppercase values if you want to have case sensitivity). Including lowercase letters adds an enormous amount of extra values in a shorter character span. That’s very important when you’re working with short URLs.

Function CountWithCharacters(ByVal strValueCurrent As String, ByVal aryCharacter() As Char) As String
    Dim chrCharacterCurrent As Char
    Dim chrCharacterNew As Char
    Dim blnIncrementParent As Boolean
    Dim intCharacterCurrent As Integer = strValueCurrent.Length
    Dim strReturnValue As String

    strReturnValue = strValueCurrent

    Do
        'reset the IncrementParent switch
        blnIncrementParent = False

        'decrement the current character place so it moves up to the parent
        intCharacterCurrent -= 1

        'Are we still looking at characters that exist?
        If intCharacterCurrent >= 0 Then
            chrCharacterCurrent = strReturnValue.Substring(intCharacterCurrent, 1)

            'If the current character is the same as the last value in the array we must increment the parent
            'and set its value to the first value in the array
            If chrCharacterCurrent = aryCharacter(aryCharacter.Length - 1) Then
                If intCharacterCurrent >= 0 Then
                    blnIncrementParent = True
                    chrCharacterNew = aryCharacter(0)
                Else
                    chrCharacterNew = Nothing
                End If

            Else
                'take the next value
                chrCharacterNew = aryCharacter(Array.IndexOf(aryCharacter, chrCharacterCurrent) + 1)
            End If

            'Remove the current character and replace it with the new one
            strReturnValue = strReturnValue.Remove(intCharacterCurrent, 1).Insert(intCharacterCurrent, chrCharacterNew)
        Else
            'Trying to increment a value that doesn't exist. Instead append the first value in the character array
            strReturnValue = aryCharacter(0) & strReturnValue
        End If

    Loop While blnIncrementParent

    Return strReturnValue

End Function

Using the function
After calling the following example the result will be a value of 0 since it’s passing in an empty string and 0 is the first value in the character array. I’m creating the character array by using a string and converting it as I pass it into the function. This character array can include any set of characters in any order. I’m using numbers, lowercase letters, uppercase letters and finally _, – and ~. I’m using those three extra characters to give me more values in a smaller character span. It’s important that all these characters don’t have to be URL encoded which would actually make the URL longer.

strValue = CountWithCharacters("", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-~".ToCharArray)

As I continue to use the function, feeding it the previous result so it can increment it, I’ll get values like 1, 2, 3, … a, b, c, …A, B, C, … _, -, ~. After the ~ value the function will return 00, 01, 02 and so on. The following call will return 0Az to strValue.

strValue = CountWithCharacters("0Ay", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-~".ToCharArray)

Profanity
As I worked on this function it crossed my mind that I would eventually run into some curse words. As the values increment, the letter combinations will spell words like ass, shit, fuck, etc. Users will probably not appreciate me giving them a URL that contains curse words. To prevent this I created another function that skips past any words I specify. This skipping process can take a tiny fraction of a second or much longer, depending on how many characters need to be skipped. Once I hit 5+ characters it can take over 1 second to execute. That’s a lot of time for a single function but given how infrequently it needs to skip past a word and now long it’ll take me to reach 5 character URL (”00000″ is the equivalent of 17,850,626), I was willing to forgive it and move on.

Function CountWithCharacters(ByVal strValueCurrent As String, ByVal aryCharacter() As Char, ByVal arySkipWords() As String) As String
    Dim strReturnValue As String
    Dim blnSkip As Boolean
    Dim strSkipWord As String
    strReturnValue = strValueCurrent

    Do
        blnSkip = False
        strReturnValue = CountWithCharacters(strReturnValue, aryCharacter)
        For Each strSkipWord In arySkipWords
            If strReturnValue.ToLower.Contains(strSkipWord) Then
                blnSkip = True
                Exit For
            End If
        Next
    Loop While blnSkip

    Return strReturnValue

End Function

This new function will execute the previous one and then check it for a skip word. If it finds a skip word then it’ll keep looping until the counter incremented past it. This design probably isn’t the most efficient one but I didn’t want to spend any more time on something so simple. It’s better to move on and revisit it if the site gets popular enough for me to be concerned.

Here’s an example call to the function. It passes in the value “asr” which would normally return “ass” but instead, since “ass” is included in the skip word array, “ast” will be the return value.

strValue = CountWithCharacters("asr", "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-~".ToCharArray, "shit,piss,fuck,cunt,cock,dick,tit,ass".Split(","))
You should share this page:
  • email
  • HackerNews
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • Mixx
  • Sphinn
  • Yahoo! Buzz
  • Print
blog comments powered by Disqus

Previous post: Use Bit.ly to Expose Click Traffic of Tweets

Next post: Apple Changes App Store Links to be SEO Friendly