-2

I am looking for a method to recode a String that only consists of digits [0,1,2,...8,9] into another String of a different character set like digits and letters [0,1,...9,a,b,...z] (as an example). The resulting string should typically be shorter than the digit-only String. The method should be reversible and it should be fast. Source code in C# answers would be appreciated but gerneal ideas are also welcome ;-) Example:

Input:  "1234567890123"
Output: "ar4cju7d"

The output of the reversing method applied to "ar4cju7d" should be "1234567890123.

ares_games
  • 1,019
  • 2
  • 15
  • 32
  • 1
    The sample input you have shown overflows an `Int64` which has a maximum value of `9223372036854775807`. So you'd better change the title of your question or make your requirements a bit more specific. Also don't hesitate to show what you have tried so far to achieve your goal explaining what particular difficulties you have encountered with your code. Because at its current state your question would be more suited to a *rent-a-coder* like website, rather than StackOverflow. – Darin Dimitrov Jan 30 '16 at 13:21
  • 1
    "Somewhat cryptographic" goes very much against the concept of an encoding which can be reversed without a key. Maybe use base64 or base32? – Maximilian Gerhardt Jan 30 '16 at 13:27
  • The "cryptograpic" part was not well explained. I removed it. What I wanted to say was that the original number should not be easily derived from the output string but this can be easily achived by adding a secret number to the input string before encoding. It is very light cryptography but enough in this case. – ares_games Jan 30 '16 at 13:34
  • @DarinDimitrov My bad. I corrected the mistake. – ares_games Jan 30 '16 at 13:37

1 Answers1

3

If your input is always an Int64, then you may check Base36 encoding. And here's a sample implementation:

// Edit: Slightly updated on 2011-03-29

/// <summary>
/// A Base36 De- and Encoder
/// </summary>
public static class Base36
{
    private const string CharList = "0123456789abcdefghijklmnopqrstuvwxyz";

    /// <summary>
    /// Encode the given number into a Base36 string
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static String Encode(long input)
    {
        if (input < 0) throw new ArgumentOutOfRangeException("input", input, "input cannot be negative");

        char[] clistarr = CharList.ToCharArray();
        var result = new Stack<char>();

        while (input != 0)
        {
            result.Push(clistarr[input % 36]);
            input /= 36;
        }

        return new string(result.ToArray());
    }

    /// <summary>
    /// Decode the Base36 Encoded string into a number
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static Int64 Decode(string input)
    {
        var reversed = input.ToLower().Reverse();
        long result = 0;
        int pos = 0;

        foreach (char c in reversed)
        {
            result += CharList.IndexOf(c) * (long)Math.Pow(36, pos);
            pos++;
        }

        return result;
    }
}

which can be applied to your example:

long input = 1234567890123;
string encoded = Base36.Encode(input); // yields "fr5hugnf"
long originalInput = Base36.Decode(encoded); // yields 1234567890123
Markus Safar
  • 6,324
  • 5
  • 28
  • 44
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    Nice encoding, this would fit well if the input is indeed alsways `int64`. If OP wants more obfuscation, you could do a character substituation (i.e. substitute every 'f' for a 'L' etc., simple substitution cipher), this is also reverseble and hinders people trying out common encodings (like base64, but base36 is already really uncommon). Ergo, good answer. – Maximilian Gerhardt Jan 30 '16 at 14:04
  • I certainly agree ;-) – ares_games Jan 30 '16 at 14:25