2021-04-20 06:31:57 +03:00
|
|
|
import _ from 'lodash';
|
|
|
|
import bigInt, { BigInteger } from "big-integer";
|
|
|
|
|
|
|
|
function sortBigInt(a: BigInteger, b: BigInteger) {
|
|
|
|
if (a.lt(b)) {
|
|
|
|
return 1;
|
|
|
|
} else if (a.eq(b)) {
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
2021-01-27 08:45:18 +03:00
|
|
|
}
|
|
|
|
export default class BigIntOrderedMap<V> implements Iterable<[BigInteger, V]> {
|
2021-04-20 06:31:57 +03:00
|
|
|
private root: Record<string, V> = {}
|
|
|
|
private cachedIter: [BigInteger, V][] | null = null;
|
2021-01-27 08:45:18 +03:00
|
|
|
|
2021-04-20 06:31:57 +03:00
|
|
|
constructor(items: [BigInteger, V][] = []) {
|
|
|
|
_.forEach(items, ([key, val]) => {
|
2021-01-27 08:45:18 +03:00
|
|
|
this.set(key, val);
|
|
|
|
});
|
2021-04-20 06:31:57 +03:00
|
|
|
this.generateCachedIter();
|
2021-01-27 08:45:18 +03:00
|
|
|
}
|
|
|
|
|
2021-04-20 06:31:57 +03:00
|
|
|
get size() {
|
|
|
|
return this.cachedIter?.length ?? Object.keys(this.root).length;
|
2021-01-27 08:45:18 +03:00
|
|
|
}
|
|
|
|
|
2021-02-17 05:35:28 +03:00
|
|
|
|
2021-04-20 06:31:57 +03:00
|
|
|
get(key: BigInteger) {
|
|
|
|
return this.root[key.toString()] ?? null;
|
|
|
|
}
|
2021-01-27 08:45:18 +03:00
|
|
|
|
2021-04-20 06:31:57 +03:00
|
|
|
set(key: BigInteger, value: V) {
|
|
|
|
this.root[key.toString()] = value;
|
|
|
|
this.cachedIter = null;
|
2021-01-27 08:45:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
clear() {
|
2021-04-20 06:31:57 +03:00
|
|
|
this.cachedIter = null;
|
|
|
|
this.root = {}
|
2021-01-27 08:45:18 +03:00
|
|
|
}
|
|
|
|
|
2021-04-20 06:31:57 +03:00
|
|
|
has(key: BigInteger) {
|
|
|
|
return key.toString() in this.root;
|
2021-01-27 08:45:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
delete(key: BigInteger) {
|
2021-04-20 06:31:57 +03:00
|
|
|
const had = this.has(key);
|
|
|
|
if(had) {
|
|
|
|
delete this.root[key.toString()];
|
|
|
|
this.cachedIter = null;
|
2021-01-27 08:45:18 +03:00
|
|
|
}
|
2021-04-20 06:31:57 +03:00
|
|
|
return had;
|
2021-01-27 08:45:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
[Symbol.iterator](): IterableIterator<[BigInteger, V]> {
|
|
|
|
let idx = 0;
|
2021-04-20 06:31:57 +03:00
|
|
|
const result = this.generateCachedIter();
|
2021-01-27 08:45:18 +03:00
|
|
|
return {
|
|
|
|
[Symbol.iterator]: this[Symbol.iterator],
|
|
|
|
next: (): IteratorResult<[BigInteger, V]> => {
|
|
|
|
if (idx < result.length) {
|
|
|
|
return { value: result[idx++], done: false };
|
|
|
|
}
|
|
|
|
return { done: true, value: null };
|
|
|
|
},
|
|
|
|
};
|
|
|
|
}
|
2021-04-20 06:31:57 +03:00
|
|
|
|
|
|
|
peekLargest() {
|
|
|
|
const sorted = Array.from(this);
|
|
|
|
return sorted[0] as [BigInteger, V] | null;
|
|
|
|
}
|
|
|
|
|
|
|
|
peekSmallest() {
|
|
|
|
const sorted = Array.from(this);
|
|
|
|
return sorted[sorted.length - 1] as [BigInteger, V] | null;
|
|
|
|
}
|
|
|
|
|
|
|
|
keys() {
|
|
|
|
return Object.keys(this.root).map(k => bigInt(k)).sort(sortBigInt)
|
|
|
|
}
|
|
|
|
|
|
|
|
private generateCachedIter() {
|
|
|
|
if(this.cachedIter) {
|
|
|
|
return this.cachedIter;
|
|
|
|
}
|
|
|
|
const result = Object.keys(this.root).map(key => {
|
|
|
|
const num = bigInt(key);
|
|
|
|
return [num, this.root[key]] as [BigInteger, V];
|
|
|
|
}).sort(([a], [b]) => sortBigInt(a,b));
|
|
|
|
this.cachedIter = result;
|
|
|
|
return result;
|
|
|
|
}
|
2021-01-27 08:45:18 +03:00
|
|
|
}
|
2021-04-20 06:31:57 +03:00
|
|
|
|