Base 52
123456.base_52
This week I needed to encode a number in a minimum of URL safe characters.
I started with Ruby’s built in to_s(36)
which was pretty reasonable,
until you run into user accounts translating directly into bad words. I’m looking at you 13996.
I decided to write my own with numbers and both cases of letters but no vowels. That leaves 52 characters.
Monkey patching isn’t in vogue anymore, but I like it for this kind of stuff.
class Integer
# No vowels means no naughty words. Radix: 52
# You can't do negative, that's not what this is for.
# See also String.base_52
def base_52
alphabet = "0123456789bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ".freeze
"#{(self.abs / 52).nonzero?&.base_52}" + alphabet[self.abs % 52]
end
end
class String
# No vowels means no naughty words. Radix: 52
# See also Integer.base_52
def base_52
alphabet = "0123456789bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ".freeze
self.chars.reverse.each_with_index.map{ |char, index| alphabet.index(char) * 52 ** index }.sum
rescue
nil
end
end
It works pretty well. If you try to use a String with an invalid character it just returns nil.
123456.base_52
=> "SF8"
"SF8".base_52
=> 123456