Skip to content

Instantly share code, notes, and snippets.

@firepacket
Last active June 18, 2021 14:02
Show Gist options
  • Save firepacket/8e9077792ea63a069ca6b0acf3dd4d21 to your computer and use it in GitHub Desktop.
Save firepacket/8e9077792ea63a069ca6b0acf3dd4d21 to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
using System.Linq;
using System.Text;
/**
* ShortURL: Bijective conversion between natural numbers (IDs) and short strings
*
* ShortURL.Encode() takes an ID and turns it into a short string
* ShortURL.Decode() takes a short string and turns it into an ID
*
* Features:
* + VERY large alphabet all composite numbers from 33-64 are included to find the shortest and nicest looking URL.
* + Offensive words have been made very unlikely due to design.
* + This allows for much more room (support for ULONG data type) at the expense of sometimes adding 1 letter for shorter numbers.
* + This method guarantees the shortest URL at the expense of one digit, but this is often reversed and some long numbers can become extra short!
* + Ultimate PRIVACY. Search space is enormous. Nobody will ever find anyone else's URL.
* + Added extra char "." that is acceptable in URLs
* + No extra DB lookups
*
* Example output:
* 434433 <=> zfMn-
* 1234 <=> w-x
* 8989800 <=> gVXG.
* 132 <=> pc_
* 2 <=> _c
* (ulong) 18446744073709551615 <=> dD5E.dbtn3-s
* (long) 9223372036854775807 <=> iD-kBTykgmf8
* (uint) 4294967295 <=> efGCg_s
* (int) 2147483647 <=> nfhj.gy
* (ushort) 65535 <=> t_zs
* (byte) 255 <=> ie-
*/
public class ShortURL
{
private static string Keys = "abcdeghijkmnpqrstuvwxyz23456789_"; // Do not change this string length. If you want to remove something, replace it with something else.
private static string AllChars = "abcdefghjkmnpqrstvwxyzABCDE-_.FGHJKLMNPQRSTVWXYZ1234567890oOiIuU"; // Do not change this string length. If you want to remove something, replace it with something else.
private static Dictionary<char, string> DAlphabet = new Dictionary<char, string>();
static ShortURL() // Contains all composite numbers from 33-64
{
for (int i = 0; i < Keys.Length; i++)
DAlphabet[ Keys[ i ] ] = new string(AllChars.Take(AllChars.Length - i).ToArray());
}
public static string Encode(ulong num)
{
ulong n = num;
List<string> s = new List<string>();
foreach (char t in Keys)
{
string A = DAlphabet[ t ];
ulong B = (ulong)A.Length;
var S = new StringBuilder();
while (n > 0) // Because we use all composite numbers, we will find the shortest url possible here!
{
S.Insert(0, A.ElementAt((int)(n % B)));
n = n / B;
}
n = num;
S.Insert(0, t);
s.Add(S.ToString());
}
// Prioritizes certain characters. Changing this will make your version unique.
var sort = s.OrderBy(x => x.Length).ThenByDescending(x => x.Contains("_") || x.Contains("-") || x.Contains(".")).ThenByDescending(x => x.ToCharArray().Count(z => char.IsLower(z)));
return sort.ToArray()[ 0 ];
}
public static ulong Decode(string str)
{
char c = str[ 0 ];
string Alphabet = DAlphabet[ c ];
ulong Base = (ulong)Alphabet.Length;
str = str.Substring(1, str.Length - 1);
ulong num = 0;
for (var i = 0; i < str.Length; i++)
{
num = num * Base + (ulong)Alphabet.IndexOf(str.ElementAt(i));
}
return num;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment