UNPKG

@rniv/base-n

Version:
232 lines (231 loc) 8.22 kB
"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;