Skip to content

Instantly share code, notes, and snippets.

@westc
Created May 18, 2026 23:36
Show Gist options
  • Select an option

  • Save westc/0b805674f2218ebe988ad0782af4bef3 to your computer and use it in GitHub Desktop.

Select an option

Save westc/0b805674f2218ebe988ad0782af4bef3 to your computer and use it in GitHub Desktop.
Convert numbers to custom bases using unique characters and convert back to numbers using custom bases.
/**
* @overload
* @param {string} uniqueBaseChars
* @returns {(str: string) => number}
*/
/**
* @overload
* @param {string} uniqueBaseChars
* @param {string} str
* @returns {number}
*/
/**
* Converts a custom-base string back into a number.
* @param {string} uniqueBaseChars
* @param {string=} str
*/
function fromUniqueBase(uniqueBaseChars, str) {
// Turn unique characters string into an array of characters.
uniqueBaseChars = [...uniqueBaseChars];
const len = uniqueBaseChars.length;
if (!len) {
throw new Error('You must specify at least one character for the unique characters.');
}
if (new Set(uniqueBaseChars).size !== len) {
throw new Error('Not all of the characters passed are unique.');
}
const charToIndex = new Map(uniqueBaseChars.map((c, i) => [c, i]));
/**
* @param {string} str
* @returns {number}
*/
function fromThisUniqueBase(str) {
let num = 0;
for (const char of str) {
const index = charToIndex.get(char);
if (index === undefined) {
throw new Error(`Invalid character: \u201C${char}\u201D`);
}
num = num * len + index;
}
return num;
}
return str === undefined ? fromThisUniqueBase : fromThisUniqueBase(str);
}
/**
* @overload
* @param {string} uniqueBaseChars
* @returns {(num: number) => string}
*/
/**
* @overload
* @param {string} uniqueBaseChars
* @param {number} num
* @returns {string}
*/
/**
* Converts a number to a custom base using the supplied unique characters.
* @param {string} uniqueBaseChars
* @param {number=} num
*/
function toUniqueBase(uniqueBaseChars, num) {
// Turn unique characters string into an array of characters.
uniqueBaseChars = [...uniqueBaseChars];
const len = uniqueBaseChars.length;
if (!len) {
throw new Error('You must specify at least one character for the unique characters.');
}
if (new Set(uniqueBaseChars).size !== len) {
throw new Error('Not all of the characters passed are unique.');
}
/**
* @param {number} num
* @returns {string}
*/
function toThisUniqueBase(num) {
if (num === 0) return uniqueBaseChars[0];
if (num !== Math.floor(num) || num < 0) {
throw new Error('Number must be non-negative integer.');
}
let result = '';
while (num > 0) {
const remainder = num % len;
result = uniqueBaseChars[remainder] + result;
num = Math.floor(num / len);
}
return result;
}
return num === undefined ? toThisUniqueBase : toThisUniqueBase(num);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment