Skip to content

Instantly share code, notes, and snippets.

@rfprod
Last active April 5, 2019 19:11
Show Gist options
  • Save rfprod/e2f9af2290fc679595d1bf145225b6f9 to your computer and use it in GitHub Desktop.
Save rfprod/e2f9af2290fc679595d1bf145225b6f9 to your computer and use it in GitHub Desktop.
Arbitrary Base Converter
const Alphabet = {
BINARY: '01',
OCTAL: '01234567',
DECIMAL: '0123456789',
HEXA_DECIMAL: '0123456789abcdef',
ALPHA_LOWER: 'abcdefghijklmnopqrstuvwxyz',
ALPHA_UPPER: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
ALPHA: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
ALPHA_NUMERIC: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
};
function baseConverter(input, source, target) {
if (source === target) { return input; }
//console.log(input);
//console.log(source, target);
let remainders = [];
let div = 0;
if ((source.length === 2 && target.length !== 10) || (source.length === 2 && !Number.isSafeInteger(parseInt(input)))) {
/*
* convert bin to dec first
* if bin should be converted to not dec
* or if bin is not a safe integer
*/
let binToDec = 0;
let power = 0;
for (let i = input.length - 1; i >= 0; i--) {
binToDec += parseInt(input[i]) * Math.pow(2, power);
power++;
}
input = binToDec;
if (!Number.isSafeInteger(parseInt(input)) && target.length === 10) {
/*
* if input is not a safe integer
* and should actually be converted from bin to dec
*/
return input;
}
} else if (source.length !== 2 && source.length !== 10) {
/*
* use dictionary to convert from arbitrary base
* to base10 before moving further
*/
//console.log('convert:', input, 'from:', source, 'to decimal');
const sourceBase = source.length;
let sourceToBase10 = 0;
//console.log('sourceBase:', sourceBase);
let power = 0;
for (let i = input.length - 1; i >= 0; i--) {
sourceToBase10 += source.indexOf(input[i]) * Math.pow(sourceBase, power);
power++;
}
input = sourceToBase10;
//input = input.split('').map(item => source.indexOf(item)).join('');
}
//console.log('input:', input);
input = parseInt(input);
while (input > target.length) {
/*
* convert using remainder approach
*/
const remainder = input % target.length;
remainders.unshift(remainder);
input = Math.trunc(input / target.length);
//console.log('input:', input, '| remainder:', remainder);
}
//console.log('remainders:', remainders, '| input:', input);
if (source.length === 10 && target.length === 2) {
/*
* fixt for dec to bin convertion
* convert rest if input is still >= 2
*/
while (input >= target.length) {
/*
* convert using remainder approach
*/
const remainder = input % target.length;
remainders.unshift(remainder);
input = Math.trunc(input / target.length);
//console.log('input:', input, '| remainder:', remainder);
}
}
remainders.unshift(input);
//console.log('remainders:', remainders);
remainders = remainders.map(item => target[item]);
return remainders.join('');
}
// convert between numeral systems
baseConverter('15', Alphabet.DECIMAL, Alphabet.BINARY); // '1111'
baseConverter('15', Alphabet.DECIMAL, Alphabet.OCTAL); // '17'
baseConverter('1010', Alphabet.BINARY, Alphabet.DECIMAL); // '10'
baseConverter('1010', Alphabet.BINARY, Alphabet.HEXA_DECIMAL); // 'a'
// other bases
baseConverter('0', Alphabet.DECIMAL, Alphabet.ALPHA); // 'a'
baseConverter('27', Alphabet.DECIMAL, Alphabet.ALPHA_LOWER); // 'bb'
baseConverter('hello', Alphabet.ALPHA_LOWER, Alphabet.HEXA_DECIMAL); // '320048'
baseConverter('SAME', Alphabet.ALPHA_UPPER, Alphabet.ALPHA_UPPER); // 'SAME'
// advanced
baseConverter('1001001100101100000001011010010', Alphabet.BINARY, Alphabet.DECIMAL); // '1234567890'
baseConverter('1001001100101100000001011010010', Alphabet.BINARY, Alphabet.OCTAL); // '11145401322'
baseConverter('1001001100101100000001011010010', Alphabet.BINARY, Alphabet.HEXA_DECIMAL); // '499602d2'
baseConverter('1001001100101100000001011010010', Alphabet.BINARY, Alphabet.ALPHA_LOWER); // 'dzxprwk'
baseConverter('1001001100101100000001011010010', Alphabet.BINARY, Alphabet.ALPHA); // 'dmSkYk'
baseConverter('1001001100101100000001011010010', Alphabet.BINARY, Alphabet.ALPHA_NUMERIC); // '1ly7vk'
baseConverter('1337', Alphabet.DECIMAL, Alphabet.BINARY); // '10100111001'
baseConverter('1337', Alphabet.DECIMAL, Alphabet.OCTAL); // '2471'
baseConverter('1337', Alphabet.DECIMAL, Alphabet.HEXA_DECIMAL); // '539'
baseConverter('1337', Alphabet.DECIMAL, Alphabet.ALPHA_LOWER); // 'bzl'
baseConverter('1337', Alphabet.DECIMAL, Alphabet.ALPHA); // 'zL'
baseConverter('1337', Alphabet.DECIMAL, Alphabet.ALPHA_NUMERIC); // 'lz'
baseConverter('CodeWars', Alphabet.ALPHA, Alphabet.BINARY); // '110100110111011111011110001100111111110000110'
baseConverter('CodeWars', Alphabet.ALPHA, Alphabet.OCTAL); // '646737361477606'
baseConverter('CodeWars', Alphabet.ALPHA, Alphabet.DECIMAL); // '29063972814726'
baseConverter('CodeWars', Alphabet.ALPHA, Alphabet.HEXA_DECIMAL); // '1a6efbc67f86'
baseConverter('CodeWars', Alphabet.ALPHA, Alphabet.ALPHA_LOWER); // 'fjepvaubis'
baseConverter('CodeWars', Alphabet.ALPHA, Alphabet.ALPHA_NUMERIC); // '8fGCU1me'
// ROT13 with custom alphabet
const customAlpha = 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM';
baseConverter('PbqrJnef', Alphabet.ALPHA, customAlpha); // 'CodeWars'
baseConverter('chAllEnge', Alphabet.ALPHA, customAlpha); // 'puNyyRatr'

Arbitrary Base Converter

Converts between arbitrary bases defined as alphabets (should work for any arbitrary alphabet not only for predefined ones):

const Alphabet = {
  BINARY:        '01',
  OCTAL:         '01234567',
  DECIMAL:       '0123456789',
  HEXA_DECIMAL:  '0123456789abcdef',
  ALPHA_LOWER:   'abcdefghijklmnopqrstuvwxyz',
  ALPHA_UPPER:   'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
  ALPHA:         'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  ALPHA_NUMERIC: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
};

Does not consider negative values.

A script by V.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment