utils.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Arr = exports.BigNumOps = exports.chainPromises = void 0;
  4. const chainPromises = (lazyPromises, reducer = (lp1, lp2) => (p) => lp1(p).then(lp2), initialValue) => lazyPromises.reduce(reducer, p => Promise.resolve(p))(initialValue);
  5. exports.chainPromises = chainPromises;
  6. const shuffleArray = (arr) => {
  7. const res = arr.slice(0);
  8. for (let i = arr.length - 1; i > 0; i--) {
  9. const j = Math.floor(Math.random() * (i + 1));
  10. [res[i], res[j]] = [res[j], res[i]];
  11. }
  12. return res;
  13. };
  14. const chunkArray = (arr, size) => {
  15. const noOfChunks = Math.ceil(size && arr.length / size);
  16. const res = Array(noOfChunks);
  17. for (let [i, j] = [0, 0]; i < noOfChunks; i++) {
  18. res[i] = arr.slice(j, j += size);
  19. }
  20. return res;
  21. };
  22. const splitBigNumAt = (num, at) => num.replace(RegExp(String.raw `^([+-]?)(\d+)(\d{${at}})$`), '$1$2,$1$3')
  23. .replace(/^([^,]*)$/, '0,$1').split(',')
  24. .map(Number);
  25. const bigNumPlus = (num1, num2) => {
  26. let [high, low] = [splitBigNumAt(num1, 15), splitBigNumAt(num2, 15)]
  27. .reduce((a, b) => [a[0] + b[0], a[1] + b[1]]);
  28. const [highSign, lowSign] = [high, low].map(Math.sign);
  29. if (highSign === 0)
  30. return low.toString();
  31. if (highSign !== lowSign) {
  32. [high, low] = [high - highSign, low - lowSign * Math.pow(10, 15)];
  33. }
  34. else {
  35. [high, low] = [high + Math.trunc(low / Math.pow(10, 15)), low % Math.pow(10, 15)];
  36. }
  37. if (high === 0)
  38. return low.toString();
  39. return `${high}${Math.abs(low).toString().padStart(15, '0')}`;
  40. };
  41. const bigNumCompare = (num1, num2) => Math.sign(Number(bigNumPlus(num1, num2.replace(/^([+-]?)(\d+)/, (_, $1, $2) => `${$1 === '-' ? '' : '-'}${$2}`))));
  42. const bigNumMin = (...nums) => {
  43. if (!nums || !nums.length)
  44. return undefined;
  45. let min = nums[0];
  46. for (let i = 1; i < nums.length; i++) {
  47. if (bigNumCompare(nums[i], min) < 0)
  48. min = nums[i];
  49. }
  50. return min;
  51. };
  52. const bigNumLShift = (num, by) => {
  53. if (by < 0)
  54. throw Error('cannot perform right shift');
  55. const at = Math.trunc((52 - by) / 10) * 3;
  56. const [high, low] = splitBigNumAt(num, at).map(n => n * Math.pow(2, by));
  57. return bigNumPlus(`${high} ${'0'.repeat(at)}`, low.toString());
  58. };
  59. const parseBigNum = (str) => (/^-?\d+$/.exec(str) || [''])[0].replace(/^(-)?0*/, '$1');
  60. exports.BigNumOps = {
  61. splitAt: splitBigNumAt,
  62. plus: bigNumPlus,
  63. compare: bigNumCompare,
  64. min: bigNumMin,
  65. lShift: bigNumLShift,
  66. parse: parseBigNum,
  67. };
  68. exports.Arr = { chunk: chunkArray, shuffle: shuffleArray };