Search code examples
c#uniquedecodeencodegenerated-code

Generate 5 length unique code from natural number


I need to generate a unique code with 5 lengths with the given number. In other words, I need to encode natural number to 5 length unique code

I wanna give fixed-length rememberable code to the customer, and keep the sequential number in the database and encode or decode when needed.

The given number can be in the range of 1 to 9999999. But the result always must be 5 lengths.

for example

1 => a56er or 2 => c7gh4

Uniqueness is important I googled a lot and I can't find a solution.


Solution

  • The given number can be in the range of 1 to 9999999

    Right. So you need to encode 24 bits of information, and you have 5 characters in which to do that - so you need 5 bits per character. That's pleasantly in the range of "only digits and lower case ASCII characters" and you can even remove points of confusion like "o/0" and "i/1".

    Note that this isn't in any way "secure" - it's entirely predictable and reversible. If you don't want customers being able to reverse engineer their sequence number from the encoded form, it won't work. But it's a simple way of encoding a number as a fixed-length string.

    Sample code showing encoding and decoding:

    using System;
    using System.Globalization;
    
    public class Test
    {
        static void Main()
        {
            EncodeDecode(10);
            EncodeDecode(100);
            EncodeDecode(1000);
            EncodeDecode(10000);
            EncodeDecode(100000);
            EncodeDecode(1000000);
            EncodeDecode(9999999);
            
            void EncodeDecode(int number)
            {
                string encoded = EncodeBase32(number);
                int decoded = DecodeBase32(encoded);
                Console.WriteLine($"{number} => {encoded} => {decoded}");
            }
       }
        
        private const string Base32Alphabet = 
            "23456789abcdefghjklmnpqrstuvwxyz";
        private static string EncodeBase32(int number)
        {
            // TODO: Range validation
            char[] chars = new char[5];
            for (int i = 0; i < 5; i++)
            {
                chars[i] = Base32Alphabet[number & 0x1f];
                number = number >> 5;
            }
            return new string(chars);
        }
        
        private static int DecodeBase32(string text)
        {
            if (text.Length != 5)
            {
                throw new ArgumentException("Invalid input: wrong length");
            }
            int number = 0;
            for (int i = 4; i >= 0; i--)
            {
                number = number << 5;
                int index = Base32Alphabet.IndexOf(text[i]);
                if (index == -1)
                {
                    throw new ArgumentException("Invalid input: invalid character");
                }
                number |= index;
            }
            return number;
        }
    }
    

    Output:

    10 => c2222 => 10
    100 => 65222 => 100
    1000 => az222 => 1000
    10000 => jsb22 => 10000
    100000 => 2p352 => 100000
    1000000 => 2ljy2 => 1000000
    9999999 => zm7kb => 9999999