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