Quick note before we start: This is not a substitute for converting between things like base-10 to binary or other predefined bases. As in if you give it the alphabet {“0”, “1”}, then 1
will encode to 0
and 2
will encode to 1
, 3
is 00
and so on. This is strictly for converting to your own custom alphabet. If you’re looking for something like converting strings to base64, I have a solution for that here which is a library I modified. And I’m sure there’s good modules for the other bases as well.
Now that that’s out of the way, here’s the asset: Roblox Asset. It’s very simple and only has 2 functions after you create the object.
Usage
Using CustomNumbers is simple, first you need to require the module:
local ServerStorage = game:GetService("ServerStorage")
local CustomNumbers = require(ServerStorage.CustomNumbers)
After you have the module, you need to make a new CustomNumbers object and give it the alphabet you want. For this example I will use an alphabet with a length of 64. This is not the same as converting a string to base64, this module ONLY works with numbers
local ServerStorage = game:GetService("ServerStorage")
local CustomNumbers = require(ServerStorage.CustomNumbers)
local cn = CustomNumbers.new({"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/" })
The alphabet is a table of characters. It can theoretically be any length you want as long as you don’t have repeating characters, it should work.
After you have this it’s super simple to turn numbers into this custom alphabet and back again using the Encode
and Decode
methods:
local ServerStorage = game:GetService("ServerStorage")
local CustomNumbers = require(ServerStorage.CustomNumbers)
local cn = CustomNumbers.new({"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "+", "/" })
local t = cn:Encode(1243671)
print(t) -- Prints the encoded value
print(cn:Decode(t)) -- prints the decoded value
This script produces this output:
That’s basically it. If you don’t care about why I made this or the source code then you can stop reading now.
Why?
I made this because I will be using it for my matchmaking service (which you can find here) in order to save as much space as possible when saving things to memory. The large majority of the time the encoded value is equal to or less than the length of the non encoded value if the base is higher than base 10. Because everything in memory is json encoded, all characters take the same space: 1 byte so every character saved is important.
I also made it because of topics like this. As you can see my solution to that is basically this module, but isn’t modular and has no way to decode the values again, but this module has that capability.
If you have no use for this module then simple solution: don’t use it I only decided to post it because someone else in the future might want it.
Source
Here’s the source if that’s all you want and don’t want the module itself:
local CustomNumbers = {}
CustomNumbers.__index = CustomNumbers
function CustomNumbers.new(alphabet)
local Numbers = {}
setmetatable(Numbers, CustomNumbers)
Numbers.Alphabet = alphabet
Numbers.AlphabetLength = #alphabet
return Numbers
end
function CustomNumbers:Encode(x)
local result = ""
if x < 1 then return result end
local quotient = x
local remainder = -1
while quotient ~= 0 do
local dec = quotient - 1
remainder = dec % self.AlphabetLength
quotient = math.floor(dec / self.AlphabetLength)
result = self.Alphabet[remainder + 1] .. result -- Compensated for lua's index 1 start
end
return result
end
function CustomNumbers:Decode(x)
local sum = 0
local index = 0
for i = #x, 1, -1 do
local c = x:sub(i,i)
sum += table.find(self.Alphabet, c)*(self.AlphabetLength^index)
index += 1
end
return sum
end
return CustomNumbers