@effect-ts/system
Version:
Effect-TS is a zero dependency set of libraries to write highly productive, purely functional TypeScript at scale.
1,715 lines (1,372 loc) • 35.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.RedBlackTreeIterator = exports.RedBlackTree = void 0;
exports.at = at;
exports.at_ = at_;
exports.backwards = backwards;
exports.find = find;
exports.findFirst = findFirst;
exports.findFirst_ = findFirst_;
exports.find_ = find_;
exports.forEach = forEach;
exports.forEachBetween = forEachBetween;
exports.forEachBetween_ = forEachBetween_;
exports.forEachGe = forEachGe;
exports.forEachGe_ = forEachGe_;
exports.forEachLt = forEachLt;
exports.forEachLt_ = forEachLt_;
exports.forEach_ = forEach_;
exports.from = from;
exports.ge = ge;
exports.ge_ = ge_;
exports.getAt = getAt;
exports.getAt_ = getAt_;
exports.getFirst = getFirst;
exports.getLast = getLast;
exports.gt = gt;
exports.gt_ = gt_;
exports.has = has;
exports.has_ = has_;
exports.insert = insert;
exports.insert_ = insert_;
exports.keys = keys;
exports.keys_ = keys_;
exports.le = le;
exports.le_ = le_;
exports.lt = lt;
exports.lt_ = lt_;
exports.make = make;
exports.reduce = reduce;
exports.reduceWithIndex = reduceWithIndex;
exports.reduceWithIndex_ = reduceWithIndex_;
exports.reduce_ = reduce_;
exports.removeFirst = removeFirst;
exports.removeFirst_ = removeFirst_;
exports.size = size;
exports.values = values;
exports.values_ = values_;
exports.visitBetween = visitBetween;
exports.visitFull = visitFull;
exports.visitGe = visitGe;
exports.visitLt = visitLt;
require("../../../Operator/index.js");
var _index2 = /*#__PURE__*/require("../../../Function/index.js");
var I = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../../../Iterable/index.js"));
var O = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../../../Option/index.js"));
var _index5 = /*#__PURE__*/require("../../../Stack/index.js");
var St = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../../../Structural/index.js"));
var A = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Array/index.js"));
var Tp = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Tuple/index.js"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
// ets_tracing: off
class Node {
constructor(color, key, value, left, right, count) {
this.color = color;
this.key = key;
this.value = value;
this.left = left;
this.right = right;
this.count = count;
}
}
function cloneNode(node) {
return new Node(node.color, node.key, node.value, node.left, node.right, node.count);
}
function swapNode(n, v) {
n.key = v.key;
n.value = v.value;
n.left = v.left;
n.right = v.right;
n.color = v.color;
n.count = v.count;
}
function repaintNode(node, color) {
return new Node(color, node.key, node.value, node.left, node.right, node.count);
}
function recountNode(node) {
var _a, _b, _c, _d;
node.count = 1 + ((_b = (_a = node.left) === null || _a === void 0 ? void 0 : _a.count) !== null && _b !== void 0 ? _b : 0) + ((_d = (_c = node.right) === null || _c === void 0 ? void 0 : _c.count) !== null && _d !== void 0 ? _d : 0);
}
/**
* A Red-Black Tree
*/
class RedBlackTree {
constructor(ord, root) {
this.ord = ord;
this.root = root;
}
[Symbol.iterator]() {
const stack = [];
let n = this.root;
while (n) {
stack.push(n);
n = n.left;
}
return new RedBlackTreeIterator(this, stack, "Forward");
}
get [St.hashSym]() {
return St.hashIterator(this[Symbol.iterator]());
}
[St.equalsSym](that) {
return that instanceof RedBlackTree && size(this) === size(that) && I.corresponds(this, that, St.equals);
}
}
/**
* Creates a new Red-Black Tree
*/
exports.RedBlackTree = RedBlackTree;
function make(ord) {
return new RedBlackTree(ord, undefined);
}
/**
* Returns the length of the tree
*/
function size(self) {
var _a, _b;
return (_b = (_a = self.root) === null || _a === void 0 ? void 0 : _a.count) !== null && _b !== void 0 ? _b : 0;
}
/**
* Insert a new item into the tree
*/
function insert_(self, key, value) {
const cmp = self.ord.compare; //Find point to insert new node at
let n = self.root;
const n_stack = [];
const d_stack = [];
while (n) {
const d = cmp(key, n.key);
n_stack.push(n);
d_stack.push(d);
if (d <= 0) {
n = n.left;
} else {
n = n.right;
}
} //Rebuild path to leaf node
n_stack.push(new Node("Red", key, value, undefined, undefined, 1));
for (let s = n_stack.length - 2; s >= 0; --s) {
const n2 = n_stack[s];
if (d_stack[s] <= 0) {
n_stack[s] = new Node(n2.color, n2.key, n2.value, n_stack[s + 1], n2.right, n2.count + 1);
} else {
n_stack[s] = new Node(n2.color, n2.key, n2.value, n2.left, n_stack[s + 1], n2.count + 1);
}
} //Rebalance tree using rotations
for (let s = n_stack.length - 1; s > 1; --s) {
const p = n_stack[s - 1];
const n3 = n_stack[s];
if (p.color === "Black" || n3.color === "Black") {
break;
}
const pp = n_stack[s - 2];
if (pp.left === p) {
if (p.left === n3) {
const y = pp.right;
if (y && y.color === "Red") {
p.color = "Black";
pp.right = repaintNode(y, "Black");
pp.color = "Red";
s -= 1;
} else {
pp.color = "Red";
pp.left = p.right;
p.color = "Black";
p.right = pp;
n_stack[s - 2] = p;
n_stack[s - 1] = n3;
recountNode(pp);
recountNode(p);
if (s >= 3) {
const ppp = n_stack[s - 3];
if (ppp.left === pp) {
ppp.left = p;
} else {
ppp.right = p;
}
}
break;
}
} else {
const y = pp.right;
if (y && y.color === "Red") {
p.color = "Black";
pp.right = repaintNode(y, "Black");
pp.color = "Red";
s -= 1;
} else {
p.right = n3.left;
pp.color = "Red";
pp.left = n3.right;
n3.color = "Black";
n3.left = p;
n3.right = pp;
n_stack[s - 2] = n3;
n_stack[s - 1] = p;
recountNode(pp);
recountNode(p);
recountNode(n3);
if (s >= 3) {
const ppp = n_stack[s - 3];
if (ppp.left === pp) {
ppp.left = n3;
} else {
ppp.right = n3;
}
}
break;
}
}
} else {
if (p.right === n3) {
const y = pp.left;
if (y && y.color === "Red") {
p.color = "Black";
pp.left = repaintNode(y, "Black");
pp.color = "Red";
s -= 1;
} else {
pp.color = "Red";
pp.right = p.left;
p.color = "Black";
p.left = pp;
n_stack[s - 2] = p;
n_stack[s - 1] = n3;
recountNode(pp);
recountNode(p);
if (s >= 3) {
const ppp = n_stack[s - 3];
if (ppp.right === pp) {
ppp.right = p;
} else {
ppp.left = p;
}
}
break;
}
} else {
const y = pp.left;
if (y && y.color === "Red") {
p.color = "Black";
pp.left = repaintNode(y, "Black");
pp.color = "Red";
s -= 1;
} else {
p.left = n3.right;
pp.color = "Red";
pp.right = n3.left;
n3.color = "Black";
n3.right = p;
n3.left = pp;
n_stack[s - 2] = n3;
n_stack[s - 1] = p;
recountNode(pp);
recountNode(p);
recountNode(n3);
if (s >= 3) {
const ppp = n_stack[s - 3];
if (ppp.right === pp) {
ppp.right = n3;
} else {
ppp.left = n3;
}
}
break;
}
}
}
} //Return new tree
n_stack[0].color = "Black";
return new RedBlackTree(self.ord, n_stack[0]);
}
/**
* Insert a new item into the tree
*/
function insert(key, value) {
return self => insert_(self, key, value);
}
/**
* Visit all nodes inorder until a Some is returned
*/
function visitFull(node, visit) {
let current = node;
let stack = undefined;
let done = false;
while (!done) {
if (current) {
stack = new _index5.Stack(current, stack);
current = current.left;
} else if (stack) {
const v = visit(stack.value.key, stack.value.value);
if (O.isSome(v)) {
return v;
}
current = stack.value.right;
stack = stack.previous;
} else {
done = true;
}
}
return O.none;
}
/**
* Visit each node of the tree in order
*/
function forEach_(self, visit) {
if (self.root) {
visitFull(self.root, (key, value) => {
visit(key, value);
return O.none;
});
}
}
/**
* Visit each node of the tree in order
*/
function forEach(visit) {
return self => forEach_(self, visit);
}
/**
* Visit nodes greater than or equal to key
*/
function visitGe(node, min, ord, visit) {
let current = node;
let stack = undefined;
let done = false;
while (!done) {
if (current) {
stack = new _index5.Stack(current, stack);
if (ord.compare(min, current.key) <= 0) {
current = current.left;
} else {
current = undefined;
}
} else if (stack) {
if (ord.compare(min, stack.value.key) <= 0) {
const v = visit(stack.value.key, stack.value.value);
if (O.isSome(v)) {
return v;
}
}
current = stack.value.right;
stack = stack.previous;
} else {
done = true;
}
}
return O.none;
}
/**
* Visit each node of the tree in order with key greater then or equal to max
*/
function forEachGe_(self, min, visit) {
if (self.root) {
visitGe(self.root, min, self.ord, (key, value) => {
visit(key, value);
return O.none;
});
}
}
/**
* Visit each node of the tree in order with key greater then or equal to max
*/
function forEachGe(min, visit) {
return self => forEachGe_(self, min, visit);
}
/**
* Visit nodes lower than key
*/
function visitLt(node, max, ord, visit) {
let current = node;
let stack = undefined;
let done = false;
while (!done) {
if (current) {
stack = new _index5.Stack(current, stack);
current = current.left;
} else if (stack && ord.compare(max, stack.value.key) > 0) {
const v = visit(stack.value.key, stack.value.value);
if (O.isSome(v)) {
return v;
}
current = stack.value.right;
stack = stack.previous;
} else {
done = true;
}
}
return O.none;
}
/**
* Visit each node of the tree in order with key lower then max
*/
function forEachLt_(self, max, visit) {
if (self.root) {
visitLt(self.root, max, self.ord, (key, value) => {
visit(key, value);
return O.none;
});
}
}
/**
* Visit each node of the tree in order with key lower then max
*/
function forEachLt(max, visit) {
return self => forEachLt_(self, max, visit);
}
/**
* Visit nodes with key lower than max and greater then or equal to min
*/
function visitBetween(node, min, max, ord, visit) {
let current = node;
let stack = undefined;
let done = false;
while (!done) {
if (current) {
stack = new _index5.Stack(current, stack);
if (ord.compare(min, current.key) <= 0) {
current = current.left;
} else {
current = undefined;
}
} else if (stack && ord.compare(max, stack.value.key) > 0) {
if (ord.compare(min, stack.value.key) <= 0) {
const v = visit(stack.value.key, stack.value.value);
if (O.isSome(v)) {
return v;
}
}
current = stack.value.right;
stack = stack.previous;
} else {
done = true;
}
}
return O.none;
}
/**
* Visit each node of the tree in order with key lower than max and greater then or equal to min
*/
function forEachBetween_(self, min, max, visit) {
if (self.root) {
visitBetween(self.root, min, max, self.ord, (key, value) => {
visit(key, value);
return O.none;
});
}
}
/**
* Visit each node of the tree in order with key lower than max and greater then or equal to min
*/
function forEachBetween(min, max, visit) {
return self => forEachBetween_(self, min, max, visit);
}
/**
* Fix up a double black node in a tree
*/
function fixDoubleBlack(stack) {
let n, p, s, z;
for (let i = stack.length - 1; i >= 0; --i) {
n = stack[i];
if (i === 0) {
n.color = "Black";
return;
} //console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key)
p = stack[i - 1];
if (p.left === n) {
//console.log("left child")
s = p.right;
if (s && s.right && s.right.color === "Red") {
//console.log("case 1: right sibling child red")
s = p.right = cloneNode(s);
z = s.right = cloneNode(s.right);
p.right = s.left;
s.left = p;
s.right = z;
s.color = p.color;
n.color = "Black";
p.color = "Black";
z.color = "Black";
recountNode(p);
recountNode(s);
if (i > 1) {
const pp = stack[i - 2];
if (pp.left === p) {
pp.left = s;
} else {
pp.right = s;
}
}
stack[i - 1] = s;
return;
} else if (s && s.left && s.left.color === "Red") {
//console.log("case 1: left sibling child red")
s = p.right = cloneNode(s);
z = s.left = cloneNode(s.left);
p.right = z.left;
s.left = z.right;
z.left = p;
z.right = s;
z.color = p.color;
p.color = "Black";
s.color = "Black";
n.color = "Black";
recountNode(p);
recountNode(s);
recountNode(z);
if (i > 1) {
const pp = stack[i - 2];
if (pp.left === p) {
pp.left = z;
} else {
pp.right = z;
}
}
stack[i - 1] = z;
return;
}
if (s && s.color === "Black") {
if (p.color === "Red") {
//console.log("case 2: black sibling, red parent", p.right.value)
p.color = "Black";
p.right = repaintNode(s, "Red");
return;
} else {
//console.log("case 2: black sibling, black parent", p.right.value)
p.right = repaintNode(s, "Red");
continue;
}
} else if (s) {
//console.log("case 3: red sibling")
s = cloneNode(s);
p.right = s.left;
s.left = p;
s.color = p.color;
p.color = "Red";
recountNode(p);
recountNode(s);
if (i > 1) {
const pp = stack[i - 2];
if (pp.left === p) {
pp.left = s;
} else {
pp.right = s;
}
}
stack[i - 1] = s;
stack[i] = p;
if (i + 1 < stack.length) {
stack[i + 1] = n;
} else {
stack.push(n);
}
i = i + 2;
}
} else {
//console.log("right child")
s = p.left;
if (s && s.left && s.left.color === "Red") {
//console.log("case 1: left sibling child red", p.value, p._color)
s = p.left = cloneNode(s);
z = s.left = cloneNode(s.left);
p.left = s.right;
s.right = p;
s.left = z;
s.color = p.color;
n.color = "Black";
p.color = "Black";
z.color = "Black";
recountNode(p);
recountNode(s);
if (i > 1) {
const pp = stack[i - 2];
if (pp.right === p) {
pp.right = s;
} else {
pp.left = s;
}
}
stack[i - 1] = s;
return;
} else if (s && s.right && s.right.color === "Red") {
//console.log("case 1: right sibling child red")
s = p.left = cloneNode(s);
z = s.right = cloneNode(s.right);
p.left = z.right;
s.right = z.left;
z.right = p;
z.left = s;
z.color = p.color;
p.color = "Black";
s.color = "Black";
n.color = "Black";
recountNode(p);
recountNode(s);
recountNode(z);
if (i > 1) {
const pp = stack[i - 2];
if (pp.right === p) {
pp.right = z;
} else {
pp.left = z;
}
}
stack[i - 1] = z;
return;
}
if (s && s.color === "Black") {
if (p.color === "Red") {
//console.log("case 2: black sibling, red parent")
p.color = "Black";
p.left = repaintNode(s, "Red");
return;
} else {
//console.log("case 2: black sibling, black parent")
p.left = repaintNode(s, "Red");
continue;
}
} else if (s) {
//console.log("case 3: red sibling")
s = cloneNode(s);
p.left = s.right;
s.right = p;
s.color = p.color;
p.color = "Red";
recountNode(p);
recountNode(s);
if (i > 1) {
const pp = stack[i - 2];
if (pp.right === p) {
pp.right = s;
} else {
pp.left = s;
}
}
stack[i - 1] = s;
stack[i] = p;
if (i + 1 < stack.length) {
stack[i + 1] = n;
} else {
stack.push(n);
}
i = i + 2;
}
}
}
}
/**
* Stateful iterator
*/
class RedBlackTreeIterator {
constructor(self, stack, direction) {
this.self = self;
this.stack = stack;
this.direction = direction;
this.count = 0;
}
/**
* Clones the iterator
*/
clone() {
return new RedBlackTreeIterator(this.self, this.stack.slice(), this.direction);
}
/**
* Reverse the traversal direction
*/
reversed() {
return new RedBlackTreeIterator(this.self, this.stack.slice(), this.direction === "Forward" ? "Backward" : "Forward");
}
/**
* Iterator next
*/
next() {
const entry = this.entry;
this.count++;
if (this.direction === "Forward") {
this.moveNext();
} else {
this.movePrev();
}
return O.fold_(entry, () => ({
done: true,
value: this.count
}), kv => ({
done: false,
value: kv
}));
}
/**
* Returns the key
*/
get key() {
if (this.stack.length > 0) {
return O.some(this.stack[this.stack.length - 1].key);
}
return O.none;
}
/**
* Returns the value
*/
get value() {
if (this.stack.length > 0) {
return O.some(this.stack[this.stack.length - 1].value);
}
return O.none;
}
/**
* Returns the key
*/
get entry() {
if (this.stack.length > 0) {
return O.some((0, _index2.tuple)(this.stack[this.stack.length - 1].key, this.stack[this.stack.length - 1].value));
}
return O.none;
}
/**
* Returns the position of this iterator in the sorted list
*/
get index() {
let idx = 0;
const stack = this.stack;
if (stack.length === 0) {
const r = this.self.root;
if (r) {
return r.count;
}
return 0;
} else if (stack[stack.length - 1].left) {
idx = stack[stack.length - 1].left.count;
}
for (let s = stack.length - 2; s >= 0; --s) {
if (stack[s + 1] === stack[s].right) {
++idx;
if (stack[s].left) {
idx += stack[s].left.count;
}
}
}
return idx;
}
/**
* Advances iterator to next element in list
*/
moveNext() {
const stack = this.stack;
if (stack.length === 0) {
return;
}
let n = stack[stack.length - 1];
if (n.right) {
n = n.right;
while (n) {
stack.push(n);
n = n.left;
}
} else {
stack.pop();
while (stack.length > 0 && stack[stack.length - 1].right === n) {
n = stack[stack.length - 1];
stack.pop();
}
}
}
/**
* Checks if there is a next element
*/
get hasNext() {
const stack = this.stack;
if (stack.length === 0) {
return false;
}
if (stack[stack.length - 1].right) {
return true;
}
for (let s = stack.length - 1; s > 0; --s) {
if (stack[s - 1].left === stack[s]) {
return true;
}
}
return false;
}
/**
* Advances iterator to previous element in list
*/
movePrev() {
const stack = this.stack;
if (stack.length === 0) {
return;
}
let n = stack[stack.length - 1];
if (n && n.left) {
n = n.left;
while (n) {
stack.push(n);
n = n.right;
}
} else {
stack.pop();
while (stack.length > 0 && stack[stack.length - 1].left === n) {
n = stack[stack.length - 1];
stack.pop();
}
}
}
/**
* Checks if there is a previous element
*/
get hasPrev() {
const stack = this.stack;
if (stack.length === 0) {
return false;
}
if (stack[stack.length - 1].left) {
return true;
}
for (let s = stack.length - 1; s > 0; --s) {
if (stack[s - 1].right === stack[s]) {
return true;
}
}
return false;
}
}
/**
* Returns the first entry in the tree
*/
exports.RedBlackTreeIterator = RedBlackTreeIterator;
function getFirst(tree) {
let n = tree.root;
let c = tree.root;
while (n) {
c = n;
n = n.left;
}
return c ? O.some(Tp.tuple(c.key, c.value)) : O.none;
}
/**
* Returns the last entry in the tree
*/
function getLast(tree) {
let n = tree.root;
let c = tree.root;
while (n) {
c = n;
n = n.right;
}
return c ? O.some(Tp.tuple(c.key, c.value)) : O.none;
}
/**
* Returns an iterator that points to the element i of the tree
*/
function at_(tree, idx, direction = "Forward") {
return {
ord: tree.ord,
[Symbol.iterator]: () => {
if (idx < 0) {
return new RedBlackTreeIterator(tree, [], direction);
}
let n = tree.root;
const stack = [];
while (n) {
stack.push(n);
if (n.left) {
if (idx < n.left.count) {
n = n.left;
continue;
}
idx -= n.left.count;
}
if (!idx) {
return new RedBlackTreeIterator(tree, stack, direction);
}
idx -= 1;
if (n.right) {
if (idx >= n.right.count) {
break;
}
n = n.right;
} else {
break;
}
}
return new RedBlackTreeIterator(tree, [], direction);
}
};
}
/**
* Returns an iterator that points to the element i of the tree
*/
function at(idx) {
return tree => at_(tree, idx);
}
/**
* Returns the element i of the tree
*/
function getAt_(tree, idx) {
if (idx < 0) {
return O.none;
}
let n = tree.root;
let node = undefined;
while (n) {
node = n;
if (n.left) {
if (idx < n.left.count) {
n = n.left;
continue;
}
idx -= n.left.count;
}
if (!idx) {
return O.some(Tp.tuple(node.key, node.value));
}
idx -= 1;
if (n.right) {
if (idx >= n.right.count) {
break;
}
n = n.right;
} else {
break;
}
}
return O.none;
}
/**
* Returns the element i of the tree
*/
function getAt(idx) {
return tree => getAt_(tree, idx);
}
/**
* Returns an iterator that traverse entries with keys less then or equal to key
*/
function le_(tree, key, direction = "Forward") {
return {
ord: tree.ord,
[Symbol.iterator]: () => {
const cmp = tree.ord.compare;
let n = tree.root;
const stack = [];
let last_ptr = 0;
while (n) {
const d = cmp(key, n.key);
stack.push(n);
if (d <= 0) {
last_ptr = stack.length;
}
if (d <= 0) {
n = n.left;
} else {
n = n.right;
}
}
stack.length = last_ptr;
return new RedBlackTreeIterator(tree, stack, direction);
}
};
}
/**
* Returns an iterator that traverse entries with keys less then or equal to key
*/
function le(key, direction = "Forward") {
return tree => le_(tree, key, direction);
}
/**
* Returns an iterator that traverse entries with keys less then key
*/
function lt_(tree, key, direction = "Forward") {
return {
ord: tree.ord,
[Symbol.iterator]: () => {
const cmp = tree.ord.compare;
let n = tree.root;
const stack = [];
let last_ptr = 0;
while (n) {
const d = cmp(key, n.key);
stack.push(n);
if (d > 0) {
last_ptr = stack.length;
}
if (d <= 0) {
n = n.left;
} else {
n = n.right;
}
}
stack.length = last_ptr;
return new RedBlackTreeIterator(tree, stack, direction);
}
};
}
/**
* Returns an iterator that traverse entries with keys less then key
*/
function lt(key, direction = "Forward") {
return tree => lt_(tree, key, direction);
}
/**
* Returns an iterator that traverse entries with keys greater then or equal to key
*/
function ge_(tree, key, direction = "Forward") {
return {
ord: tree.ord,
[Symbol.iterator]: () => {
const cmp = tree.ord.compare;
let n = tree.root;
const stack = [];
let last_ptr = 0;
while (n) {
const d = cmp(key, n.key);
stack.push(n);
if (d <= 0) {
last_ptr = stack.length;
}
if (d <= 0) {
n = n.left;
} else {
n = n.right;
}
}
stack.length = last_ptr;
return new RedBlackTreeIterator(tree, stack, direction);
}
};
}
/**
* Returns an iterator that traverse entries with keys greater then or equal to key
*/
function ge(key, direction = "Forward") {
return tree => ge_(tree, key, direction);
}
/**
* Returns an iterator that traverse entries with keys greater then or equal to key
*/
function gt_(tree, key, direction = "Forward") {
return {
ord: tree.ord,
[Symbol.iterator]: () => {
const cmp = tree.ord.compare;
let n = tree.root;
const stack = [];
let last_ptr = 0;
while (n) {
const d = cmp(key, n.key);
stack.push(n);
if (d < 0) {
last_ptr = stack.length;
}
if (d < 0) {
n = n.left;
} else {
n = n.right;
}
}
stack.length = last_ptr;
return new RedBlackTreeIterator(tree, stack, direction);
}
};
}
/**
* Returns an iterator that traverse entries with keys greater then or equal to key
*/
function gt(key, direction = "Forward") {
return tree => gt_(tree, key, direction);
}
/**
* Traverse the tree backwards
*/
function backwards(self) {
return {
ord: self.ord,
[Symbol.iterator]: () => {
const stack = [];
let n = self.root;
while (n) {
stack.push(n);
n = n.right;
}
return new RedBlackTreeIterator(self, stack, "Backward");
}
};
}
/**
* Get the values of the tree
*/
function values_(self, direction = "Forward") {
const begin = self[Symbol.iterator]();
let count = 0;
return {
[Symbol.iterator]: () => values_(self, direction),
next: () => {
count++;
const entry = begin.value;
if (direction === "Forward") {
begin.moveNext();
} else {
begin.movePrev();
}
return O.fold_(entry, () => ({
value: count,
done: true
}), entry => ({
value: entry,
done: false
}));
}
};
}
/**
* Get the values of the tree
*/
function values(direction = "Forward") {
return self => values_(self, direction);
}
/**
* Get the keys of the tree
*/
function keys_(self, direction = "Forward") {
const begin = self[Symbol.iterator]();
let count = 0;
return {
[Symbol.iterator]: () => keys_(self, direction),
next: () => {
count++;
const entry = begin.key;
if (direction === "Forward") {
begin.moveNext();
} else {
begin.movePrev();
}
return O.fold_(entry, () => ({
value: count,
done: true
}), entry => ({
value: entry,
done: false
}));
}
};
}
/**
* Get the keys of the tree
*/
function keys(direction = "Forward") {
return self => keys_(self, direction);
}
function from(...args) {
let tree = args.length === 2 ? make(args[1]) : make(args[0].ord);
for (const [k, v] of args[0]) {
tree = insert_(tree, k, v);
}
return tree;
}
/**
* Finds the item with key if it exists
*/
function find_(tree, key) {
const cmp = tree.ord.compare;
let n = tree.root;
const res = [];
while (n) {
const d = cmp(key, n.key);
if (d === 0 && St.equals(key, n.key)) {
res.push(n.value);
}
if (d <= 0) {
n = n.left;
} else {
n = n.right;
}
}
return A.reverse(res);
}
/**
* Finds the item with key if it exists
*/
function find(key) {
return tree => find_(tree, key);
}
/**
* Finds the item with key if it exists
*/
function findFirst_(tree, key) {
const cmp = tree.ord.compare;
let n = tree.root;
while (n) {
const d = cmp(key, n.key);
if (St.equals(key, n.key)) {
return O.some(n.value);
}
if (d <= 0) {
n = n.left;
} else {
n = n.right;
}
}
return O.none;
}
/**
* Finds the item with key if it exists
*/
function findFirst(key) {
return tree => findFirst_(tree, key);
}
/**
* Finds the item with key if it exists
*/
function has_(tree, key) {
return findFirst_(tree, key)._tag === "Some";
}
/**
* Finds the item with key if it exists
*/
function has(key) {
return tree => has_(tree, key);
}
/**
* Removes entry with key
*/
function removeFirst_(self, key) {
const cmp = self.ord.compare;
let node = self.root;
const stack = [];
while (node) {
const d = cmp(key, node.key);
stack.push(node);
if (St.equals(key, node.key)) {
node = undefined;
} else if (d <= 0) {
node = node.left;
} else {
node = node.right;
}
}
if (stack.length === 0) {
return self;
}
const cstack = new Array(stack.length);
let n = stack[stack.length - 1];
cstack[cstack.length - 1] = new Node(n.color, n.key, n.value, n.left, n.right, n.count);
for (let i = stack.length - 2; i >= 0; --i) {
n = stack[i];
if (n.left === stack[i + 1]) {
cstack[i] = new Node(n.color, n.key, n.value, cstack[i + 1], n.right, n.count);
} else {
cstack[i] = new Node(n.color, n.key, n.value, n.left, cstack[i + 1], n.count);
}
} //Get node
n = cstack[cstack.length - 1]; //console.log("start remove: ", n.value)
//If not leaf, then swap with previous node
if (n.left && n.right) {
//console.log("moving to leaf")
//First walk to previous leaf
const split = cstack.length;
n = n.left;
while (n.right) {
cstack.push(n);
n = n.right;
} //Copy path to leaf
const v = cstack[split - 1];
cstack.push(new Node(n.color, v.key, v.value, n.left, n.right, n.count));
cstack[split - 1].key = n.key;
cstack[split - 1].value = n.value; //Fix up stack
for (let i = cstack.length - 2; i >= split; --i) {
n = cstack[i];
cstack[i] = new Node(n.color, n.key, n.value, n.left, cstack[i + 1], n.count);
}
cstack[split - 1].left = cstack[split];
} //console.log("stack=", cstack.map(function(v) { return v.value }))
//Remove leaf node
n = cstack[cstack.length - 1];
if (n.color === "Red") {
//Easy case: removing red leaf
//console.log("RED leaf")
const p = cstack[cstack.length - 2];
if (p.left === n) {
p.left = null;
} else if (p.right === n) {
p.right = null;
}
cstack.pop();
for (let i = 0; i < cstack.length; ++i) {
cstack[i]._count--;
}
return new RedBlackTree(self.ord, cstack[0]);
} else {
if (n.left || n.right) {
//Second easy case: Single child black parent
//console.log("BLACK single child")
if (n.left) {
swapNode(n, n.left);
} else if (n.right) {
swapNode(n, n.right);
} //Child must be red, so repaint it black to balance color
n.color = "Black";
for (let i = 0; i < cstack.length - 1; ++i) {
cstack[i]._count--;
}
return new RedBlackTree(self.ord, cstack[0]);
} else if (cstack.length === 1) {
//Third easy case: root
//console.log("ROOT")
return new RedBlackTree(self.ord, undefined);
} else {
//Hard case: Repaint n, and then do some nasty stuff
//console.log("BLACK leaf no children")
for (let i = 0; i < cstack.length; ++i) {
cstack[i]._count--;
}
const parent = cstack[cstack.length - 2];
fixDoubleBlack(cstack); //Fix up links
if (parent.left === n) {
parent.left = null;
} else {
parent.right = null;
}
}
}
return new RedBlackTree(self.ord, cstack[0]);
}
/**
* Removes entry with key
*/
function removeFirst(key) {
return tree => removeFirst_(tree, key);
}
/**
* Reduce a state over the map entries
*/
function reduceWithIndex_(map, z, f) {
let x = z;
for (const [k, v] of map) {
x = f(x, k, v);
}
return x;
}
/**
* Reduce a state over the map entries
*
* @ets_data_first reduceWithIndex_
*/
function reduceWithIndex(z, f) {
return map => reduceWithIndex_(map, z, f);
}
/**
* Reduce a state over the map entries
*/
function reduce_(map, z, f) {
return reduceWithIndex_(map, z, (z1, _, v) => f(z1, v));
}
/**
* Reduce a state over the map entries
*
* @ets_data_first reduceWithIndex_
*/
function reduce(z, f) {
return map => reduce_(map, z, f);
}
//# sourceMappingURL=index.js.map