@rniv/base-n
Version:
## Installation
232 lines (231 loc) • 8.22 kB
JavaScript
"use strict";
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
var __values = (this && this.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
exports.__esModule = true;
var range = function (n) {
return __spread(Array(n).keys());
};
var BaseN = /** @class */ (function () {
function BaseN(symbols) {
this._regex = /^[a-z0-9]+$/i;
this._symbol_number = {};
this._number_symbol = {};
if (typeof symbols === 'string') {
symbols = symbols.split('');
}
this._symbols_string = symbols.join('');
if (!this.is_valid_symbols())
throw new Error('Invalid symbols');
this._base = symbols.length;
this._symbols = symbols;
this._base_regex = new RegExp("^[" + this._symbols_string + "]+$");
this._numbers = range(this._base);
this._init();
}
BaseN.prototype._init = function () {
for (var idx = 0; idx < this._base; idx++) {
var num = this._numbers[idx];
var symbol = this._symbols[idx];
this._symbol_number[symbol] = num;
this._number_symbol[num] = symbol;
}
};
BaseN.prototype.is_valid_symbols = function () {
var regex_test = this._regex.test(this._symbols_string);
if (!regex_test)
return regex_test;
var duplicate_test = !this.has_duplicate();
return duplicate_test;
};
BaseN.prototype.has_duplicate = function () {
var e_1, _a;
var charset = {};
try {
for (var _b = __values(this._symbols_string), _c = _b.next(); !_c.done; _c = _b.next()) {
var char = _c.value;
if (charset[char] === 1)
return true;
charset[char] = 1;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return false;
};
BaseN.prototype.encode = function (n) {
n = parseInt(n + '');
var result = '';
while (n > 0) {
var rem = n % this._base;
result = this._number_symbol[rem] + result;
n = parseInt((n / this._base) + '');
}
if (result.length < 1) {
result = this._number_symbol[0];
}
return result;
};
BaseN.prototype.decode = function (s) {
var e_2, _a;
if (!this._base_regex.test(s))
throw new Error('Invalid symbols exist');
s = s.trim();
var result = 0;
var pow = s.length - 1;
try {
for (var s_1 = __values(s), s_1_1 = s_1.next(); !s_1_1.done; s_1_1 = s_1.next()) {
var symbol = s_1_1.value;
result += Math.pow(this._base, pow) * this._symbol_number[symbol];
pow -= 1;
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (s_1_1 && !s_1_1.done && (_a = s_1["return"])) _a.call(s_1);
}
finally { if (e_2) throw e_2.error; }
}
return result;
};
BaseN.prototype.add = function (n1, n2) {
var _a;
if (!this._base_regex.test(n1) || !this._base_regex.test(n2))
throw new Error('Invalid symbols exist');
var n1_array = Array.from(n1);
var n2_array = Array.from(n2);
var result = '';
var sum = '';
var carry = '';
while (n1_array.length > 0 || n2_array.length > 0) {
_a = __read(this._add(n1_array.pop(), n2_array.pop(), carry), 2), sum = _a[0], carry = _a[1];
result = sum + result;
}
if (this._symbol_number[carry] !== 0)
result = carry + result;
result = this.remove_left_zeros(result);
return result;
};
BaseN.prototype._add = function (n1, n2, carry) {
var n1_value = this._symbol_number[n1] || 0;
var n2_value = this._symbol_number[n2] || 0;
var carry_value = this._symbol_number[carry] || 0;
var sum = n1_value + n2_value + carry_value;
carry_value = parseInt((sum / this._base) + '');
var result = sum % this._base;
return [this._number_symbol[result], this._number_symbol[carry_value]];
};
BaseN.prototype.subtract = function (s1, s2, abs) {
var _a, _b;
if (abs === void 0) { abs = true; }
if (!this._base_regex.test(s1) || !this._base_regex.test(s2))
throw new Error('Invalid symbols exist');
var compare_value = this.compare(s1, s2);
if (compare_value === -1) {
_a = __read([s2, s1], 2), s1 = _a[0], s2 = _a[1];
}
var result = '';
var borrow = '';
var s1_array = Array.from(s1);
var s2_array = Array.from(s2);
var value = '';
while (s1_array.length > 0 || s2_array.length > 0) {
_b = __read(this._subtract(s1_array.pop(), s2_array.pop(), borrow), 2), value = _b[0], borrow = _b[1];
if (s1.length > 1 && s1_array.length === 0 && this._symbol_number[value] === 0)
continue;
result = value + result;
}
if (!abs) {
var prefix = compare_value === -1 ? '-' : '';
return prefix + result;
}
result = this.remove_left_zeros(result);
return result;
};
BaseN.prototype._subtract = function (s1, s2, borrow) {
var s1_value = this._symbol_number[s1] || 0;
var s2_value = this._symbol_number[s2] || 0;
var borrow_value = this._symbol_number[borrow] || 0;
var value = s1_value - s2_value - borrow_value;
if (value < 0) {
borrow_value = 1;
value += this._base;
}
var result = this._number_symbol[value];
borrow = this._number_symbol[borrow_value];
return [result, borrow];
};
BaseN.prototype.compare = function (s1, s2) {
if (!this._base_regex.test(s1) || !this._base_regex.test(s2))
throw new Error('Invalid symbols exist');
s1 = this.remove_left_zeros(s1);
s2 = this.remove_left_zeros(s2);
if (s1.length > s2.length)
return 1;
else if (s1.length < s2.length)
return -1;
var max_len = s1.length;
for (var idx = 0; idx < max_len; idx++) {
var s1_char = s1[idx];
var s2_char = s2[idx];
var s1_char_value = this._symbol_number[s1_char] || 0;
var s2_char_value = this._symbol_number[s2_char] || 0;
if (s1_char_value === s2_char_value) {
continue;
}
else if (s1_char_value < s2_char_value) {
return -1;
}
else {
return 1;
}
}
return 0;
};
BaseN.prototype.remove_left_zeros = function (s) {
var zero_char = this._number_symbol[0];
var idx = 0;
for (; idx < s.length && s[idx] === zero_char; idx++)
;
var result = s.slice(idx);
if (result.length < 1) {
result = this._number_symbol[0];
}
return result;
};
return BaseN;
}());
exports.BaseN = BaseN;