/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
export class Stack {
    constructor() {
        this.items = [];
    }
    push(val) {
        this.items.push(val);
    }
    empty() {
        return this.items.length === 0;
    }
    top() {
        return this.items[this.items.length - 1];
    }
    pop() {
        return this.items.pop();
    }
}
export function ListRemoveEntry(entry) {
    if (entry === undefined) {
        return undefined;
    }
    else if (entry.isHead) {
        return undefined;
    }
    else {
        entry.next.prev = entry.prev;
        entry.prev.next = entry.next;
    }
    return (entry);
}
function ListMakeEntry(data) {
    return new List(false, data);
}
export function ListMakeHead() {
    return new List(true, undefined);
}
export class List {
    constructor(isHead, data) {
        this.isHead = isHead;
        this.data = data;
        this.prev = this;
        this.next = this;
    }
    clear() {
        if (this.isHead) {
            this.prev = this;
            this.next = this;
        }
    }
    add(data) {
        const entry = ListMakeEntry(data);
        this.prev.next = entry;
        entry.next = this;
        entry.prev = this.prev;
        this.prev = entry;
        return (entry);
    }
    dequeue() {
        if (!this.empty()) {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            const removedEntry = ListRemoveEntry(this.next);
            return removedEntry.data;
        }
    }
    enqueue(data) {
        return this.add(data);
    }
    walk(fn) {
        for (let entry = this.next; !(entry.isHead); entry = entry.next) {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            fn(entry.data, entry);
        }
    }
    some(fn, rev) {
        const rtn = [];
        const start = rev ? this.prev : this.next;
        for (let entry = start; !(entry.isHead); entry = rev ? entry.prev : entry.next) {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            const data = entry.data;
            if (fn(data, entry)) {
                if (rev) {
                    // preserve list order when in reverse
                    rtn.unshift(data);
                }
                else {
                    rtn.push(data);
                }
            }
        }
        return rtn;
    }
    count() {
        let entry;
        let i;
        entry = this.next;
        for (i = 0; !(entry.isHead); i++) {
            entry = entry.next;
        }
        return (i);
    }
    first() {
        if (!this.empty()) {
            return (this.next.data);
        }
    }
    last() {
        if (!this.empty()) {
            return (this.prev.data);
        }
    }
    empty() {
        return (this.next === this);
    }
    /**
     * @deprecated - use unshift
     */
    push(data) {
        this.unshift(data);
    }
    unshift(data) {
        const entry = ListMakeEntry(data);
        entry.data = data;
        entry.isHead = false;
        entry.next = this.next;
        entry.prev = this;
        this.next = entry;
        entry.next.prev = entry;
    }
    [Symbol.iterator]() {
        // eslint-disable-next-line @typescript-eslint/no-this-alias
        let node = this;
        const iterator = {
            next() {
                while (node && node.next.isHead === false) {
                    node = node.next;
                    if (node.data !== undefined) {
                        return { value: node.data, done: false };
                    }
                }
                return { value: undefined, done: true };
            },
            [Symbol.iterator]() {
                return this;
            },
        };
        return iterator;
    }
}
export class Heap {
    constructor(a, comp) {
        this.comp = comp;
        this.L = [comp.min];
        for (let i = 0, len = a.length; i < len; i++) {
            this.add(a[i]);
        }
    }
    count() {
        return this.L.length - 1;
    }
    peek() {
        return this.L[1];
    }
    get() {
        const x = this.L[1];
        this.L[1] = this.L[this.count()];
        this.L.pop();
        this.fixDown(1);
        return x;
    }
    add(x) {
        this.L.push(x);
        this.fixup(this.count());
    }
    /* eslint-disable no-bitwise */
    fixup(k) {
        let _k = k;
        while (_k > 1 && (this.comp.compare(this.L[_k >> 1], this.L[_k]) > 0)) {
            const tmp = this.L[_k >> 1];
            this.L[_k >> 1] = this.L[_k];
            this.L[_k] = tmp;
            _k = _k >> 1;
        }
    }
    fixDown(k) {
        let _k = k;
        while ((_k << 1) <= (this.count())) {
            let j = _k << 1;
            if ((j < this.count()) && (this.comp.compare(this.L[j], this.L[j + 1]) > 0)) {
                j++;
            }
            if (this.comp.compare(this.L[_k], this.L[j]) <= 0) {
                break;
            }
            const tmp = this.L[_k];
            this.L[_k] = this.L[j];
            this.L[j] = tmp;
            _k = j;
        }
    }
}
export const RBColor = {
    RED: 0,
    BLACK: 1,
};
export class RedBlackTree {
    constructor(compareKeys, aug) {
        this.compareKeys = compareKeys;
        this.aug = aug;
    }
    makeNode(key, data, color, size) {
        return { key, data, color, size };
    }
    isRed(node) {
        return !!node && (node.color === RBColor.RED);
    }
    nodeSize(node) {
        return node ? node.size : 0;
    }
    size() {
        return this.nodeSize(this.root);
    }
    isEmpty() {
        return !this.root;
    }
    get(key) {
        if (key !== undefined) {
            return this.nodeGet(this.root, key);
        }
    }
    nodeGet(node, key) {
        let _node = node;
        while (_node) {
            const cmp = this.compareKeys(key, _node.key);
            if (cmp < 0) {
                _node = _node.left;
            }
            else if (cmp > 0) {
                _node = _node.right;
            }
            else {
                return _node;
            }
        }
    }
    contains(key) {
        return this.get(key);
    }
    gather(key, matcher) {
        const results = [];
        if (key !== undefined) {
            this.nodeGather(this.root, results, key, matcher);
        }
        return results;
    }
    nodeGather(node, results, key, matcher) {
        if (node) {
            if (matcher.continueSubtree(node.left, key)) {
                this.nodeGather(node.left, results, key, matcher);
            }
            if (matcher.matchNode(node, key)) {
                results.push(node);
            }
            if (matcher.continueSubtree(node.right, key)) {
                this.nodeGather(node.right, results, key, matcher);
            }
        }
    }
    walkExactMatchesForward(compareFn, actionFn, continueLeftFn, continueRightFn) {
        this.nodeWalkExactMatchesForward(this.root, compareFn, actionFn, continueLeftFn, continueRightFn);
    }
    nodeWalkExactMatchesForward(node, compareFn, actionFn, continueLeftFn, continueRightFn) {
        if (!node) {
            return;
        }
        const result = compareFn(node);
        if (continueLeftFn(result)) {
            this.nodeWalkExactMatchesForward(node.left, compareFn, actionFn, continueLeftFn, continueRightFn);
        }
        if (result === 0) {
            actionFn(node);
        }
        if (continueRightFn(result)) {
            this.nodeWalkExactMatchesForward(node.right, compareFn, actionFn, continueLeftFn, continueRightFn);
        }
    }
    walkExactMatchesBackward(compareFn, actionFn, continueLeftFn, continueRightFn) {
        this.nodeWalkExactMatchesBackward(this.root, compareFn, actionFn, continueLeftFn, continueRightFn);
    }
    nodeWalkExactMatchesBackward(node, compareFn, actionFn, continueLeftFn, continueRightFn) {
        if (!node) {
            return;
        }
        const result = compareFn(node);
        if (continueRightFn(result)) {
            this.nodeWalkExactMatchesBackward(node.right, compareFn, actionFn, continueLeftFn, continueRightFn);
        }
        if (result === 0) {
            actionFn(node);
        }
        if (continueLeftFn(result)) {
            this.nodeWalkExactMatchesBackward(node.left, compareFn, actionFn, continueLeftFn, continueRightFn);
        }
    }
    put(key, data, conflict) {
        if (key !== undefined) {
            if (data === undefined) {
                this.remove(key);
            }
            else {
                this.root = this.nodePut(this.root, key, data, conflict);
                this.root.color = RBColor.BLACK;
            }
        }
    }
    nodePut(node, key, data, conflict) {
        let _node = node;
        if (!_node) {
            return this.makeNode(key, data, RBColor.RED, 1);
        }
        else {
            const cmp = this.compareKeys(key, _node.key);
            if (cmp < 0) {
                _node.left = this.nodePut(_node.left, key, data, conflict);
            }
            else if (cmp > 0) {
                _node.right = this.nodePut(_node.right, key, data, conflict);
            }
            else {
                if (conflict) {
                    const kd = conflict(key, _node.key, data, _node.data);
                    if (kd.key) {
                        _node.key = kd.key;
                    }
                    if (kd.data) {
                        _node.data = kd.data;
                    }
                    else {
                        _node.data = data;
                    }
                }
                else {
                    _node.data = data;
                }
            }
            if (this.isRed(_node.right) && (!this.isRed(_node.left))) {
                _node = this.rotateLeft(_node);
            }
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            if (this.isRed(_node.left) && this.isRed(_node.left.left)) {
                _node = this.rotateRight(_node);
            }
            if (this.isRed(_node.left) && this.isRed(_node.right)) {
                this.flipColors(_node);
            }
            _node.size = this.nodeSize(_node.left) + this.nodeSize(_node.right) + 1;
            if (this.aug) {
                this.updateLocal(_node);
            }
            return _node;
        }
    }
    updateLocal(node) {
        if (this.aug) {
            if (this.isRed(node.left)) {
                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                this.aug.update(node.left);
            }
            if (this.isRed(node.right)) {
                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                this.aug.update(node.right);
            }
            this.aug.update(node);
        }
    }
    nodeRemoveMin(node) {
        let _node = node;
        if (_node.left) {
            if ((!this.isRed(_node.left)) && (!this.isRed(_node.left.left))) {
                _node = this.moveRedLeft(_node);
            }
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            _node.left = this.nodeRemoveMin(_node.left);
            return this.balance(_node);
        }
    }
    remove(key) {
        if (key !== undefined) {
            if (!this.contains(key)) {
                return;
            }
            this.removeExisting(key);
        }
        // TODO: error on undefined key
    }
    removeExisting(key) {
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        if ((!this.isRed(this.root.left)) && (!this.isRed(this.root.right))) {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            this.root.color = RBColor.RED;
        }
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        this.root = this.nodeRemove(this.root, key);
    }
    nodeRemove(node, key) {
        let _node = node;
        if (this.compareKeys(key, _node.key) < 0) {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            if ((!this.isRed(_node.left)) && (!this.isRed(_node.left.left))) {
                _node = this.moveRedLeft(_node);
            }
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            _node.left = this.nodeRemove(_node.left, key);
        }
        else {
            if (this.isRed(_node.left)) {
                _node = this.rotateRight(_node);
            }
            if ((this.compareKeys(key, _node.key) === 0) && (!_node.right)) {
                return undefined;
            }
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            if ((!this.isRed(_node.right)) && (!this.isRed(_node.right.left))) {
                _node = this.moveRedRight(_node);
            }
            if (this.compareKeys(key, _node.key) === 0) {
                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                const subtreeMin = this.nodeMin(_node.right);
                _node.key = subtreeMin.key;
                _node.data = subtreeMin.data;
                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                _node.right = this.nodeRemoveMin(_node.right);
            }
            else {
                // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
                _node.right = this.nodeRemove(_node.right, key);
            }
        }
        return this.balance(_node);
    }
    floor(key) {
        if (!this.isEmpty()) {
            return this.nodeFloor(this.root, key);
        }
    }
    nodeFloor(node, key) {
        if (node) {
            const cmp = this.compareKeys(key, node.key);
            if (cmp === 0) {
                return node;
            }
            else if (cmp < 0) {
                return this.nodeFloor(node.left, key);
            }
            else {
                const rightFloor = this.nodeFloor(node.right, key);
                if (rightFloor) {
                    return rightFloor;
                }
                else {
                    return node;
                }
            }
        }
    }
    ceil(key) {
        if (!this.isEmpty()) {
            return this.nodeCeil(this.root, key);
        }
    }
    nodeCeil(node, key) {
        if (node) {
            const cmp = this.compareKeys(key, node.key);
            if (cmp === 0) {
                return node;
            }
            else if (cmp > 0) {
                return this.nodeCeil(node.right, key);
            }
            else {
                const leftCeil = this.nodeCeil(node.left, key);
                if (leftCeil) {
                    return leftCeil;
                }
                else {
                    return node;
                }
            }
        }
    }
    min() {
        if (this.root) {
            return this.nodeMin(this.root);
        }
    }
    nodeMin(node) {
        if (!node.left) {
            return node;
        }
        else {
            return this.nodeMin(node.left);
        }
    }
    max() {
        if (this.root) {
            return this.nodeMax(this.root);
        }
    }
    nodeMax(node) {
        if (!node.right) {
            return node;
        }
        else {
            return this.nodeMax(node.right);
        }
    }
    rotateRight(node) {
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        const leftChild = node.left;
        node.left = leftChild.right;
        leftChild.right = node;
        leftChild.color = leftChild.right.color;
        leftChild.right.color = RBColor.RED;
        leftChild.size = node.size;
        node.size = this.nodeSize(node.left) + this.nodeSize(node.right) + 1;
        if (this.aug) {
            this.updateLocal(node);
            this.updateLocal(leftChild);
        }
        return leftChild;
    }
    rotateLeft(node) {
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        const rightChild = node.right;
        node.right = rightChild.left;
        rightChild.left = node;
        rightChild.color = rightChild.left.color;
        rightChild.left.color = RBColor.RED;
        rightChild.size = node.size;
        node.size = this.nodeSize(node.left) + this.nodeSize(node.right) + 1;
        if (this.aug) {
            this.updateLocal(node);
            this.updateLocal(rightChild);
        }
        return rightChild;
    }
    oppositeColor(c) {
        return (c === RBColor.BLACK) ? RBColor.RED : RBColor.BLACK;
    }
    flipColors(node) {
        node.color = this.oppositeColor(node.color);
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        node.left.color = this.oppositeColor(node.left.color);
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        node.right.color = this.oppositeColor(node.right.color);
    }
    moveRedLeft(node) {
        let _node = node;
        this.flipColors(_node);
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        if (this.isRed(_node.right.left)) {
            // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
            _node.right = this.rotateRight(_node.right);
            _node = this.rotateLeft(_node);
            this.flipColors(_node);
        }
        return _node;
    }
    moveRedRight(node) {
        let _node = node;
        this.flipColors(_node);
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        if (this.isRed(_node.left.left)) {
            _node = this.rotateRight(_node);
            this.flipColors(_node);
        }
        return _node;
    }
    balance(input) {
        let node = input;
        if (this.isRed(node.right)) {
            node = this.rotateLeft(node);
        }
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        if (this.isRed(node.left) && this.isRed(node.left.left)) {
            node = this.rotateRight(node);
        }
        if (this.isRed(node.left) && (this.isRed(node.right))) {
            this.flipColors(node);
        }
        node.size = this.nodeSize(node.left) + this.nodeSize(node.right) + 1;
        if (this.aug) {
            this.aug.update(node);
        }
        return node;
    }
    mapRange(action, accum, start, end) {
        this.nodeMap(this.root, action, start, end);
    }
    map(action, accum) {
        // TODO: optimize to avoid comparisons
        this.nodeMap(this.root, action, accum);
    }
    keys() {
        const keyList = [];
        const actions = {
            showStructure: true,
            infix: (node) => {
                keyList.push(node.key);
                return true;
            },
        };
        this.walk(actions);
        return keyList;
    }
    /**
     * Depth-first traversal with custom action; if action returns
     * false, traversal is halted.
     * @param action - action to apply to each node
     */
    walk(actions) {
        this.nodeWalk(this.root, actions);
    }
    walkBackward(actions) {
        this.nodeWalkBackward(this.root, actions);
    }
    nodeWalk(node, actions) {
        let go = true;
        if (node) {
            if (actions.pre) {
                if (actions.showStructure || (node.color === RBColor.BLACK)) {
                    go = actions.pre(node);
                }
            }
            if (node.left) {
                go = this.nodeWalk(node.left, actions);
            }
            if (go && actions.infix) {
                if (actions.showStructure || (node.color === RBColor.BLACK)) {
                    go = actions.infix(node);
                }
            }
            if (go) {
                go = this.nodeWalk(node.right, actions);
            }
            if (go && actions.post) {
                if (actions.showStructure || (node.color === RBColor.BLACK)) {
                    go = actions.post(node);
                }
            }
        }
        return go;
    }
    nodeWalkBackward(node, actions) {
        let go = true;
        if (node) {
            if (actions.pre) {
                if (actions.showStructure || (node.color === RBColor.BLACK)) {
                    go = actions.pre(node);
                }
            }
            if (node.right) {
                go = this.nodeWalkBackward(node.right, actions);
            }
            if (go && actions.infix) {
                if (actions.showStructure || (node.color === RBColor.BLACK)) {
                    go = actions.infix(node);
                }
            }
            if (go) {
                go = this.nodeWalkBackward(node.left, actions);
            }
            if (go && actions.post) {
                if (actions.showStructure || (node.color === RBColor.BLACK)) {
                    go = actions.post(node);
                }
            }
        }
        return go;
    }
    nodeMap(node, action, accum, start, end) {
        let _start = start;
        let _end = end;
        if (!node) {
            return true;
        }
        if (_start === undefined) {
            _start = this.nodeMin(node).key;
        }
        if (_end === undefined) {
            _end = this.nodeMax(node).key;
        }
        const cmpStart = this.compareKeys(_start, node.key);
        const cmpEnd = this.compareKeys(_end, node.key);
        let go = true;
        if (cmpStart < 0) {
            go = this.nodeMap(node.left, action, accum, _start, _end);
        }
        if (go && (cmpStart <= 0) && (cmpEnd >= 0)) {
            // REVIEW: test for black node here
            go = action(node, accum);
        }
        if (go && (cmpEnd > 0)) {
            go = this.nodeMap(node.right, action, accum, _start, _end);
        }
        return go;
    }
}
export const integerRangeToString = (range) => `[${range.start},${range.end})`;
const intervalComparer = (a, b) => a.compare(b);
export class IntervalTree {
    constructor() {
        this.intervals = new RedBlackTree(intervalComparer, this);
    }
    remove(x) {
        this.intervals.remove(x);
    }
    removeExisting(x) {
        this.intervals.removeExisting(x);
    }
    put(x, conflict) {
        let rbConflict;
        if (conflict) {
            rbConflict = (key, currentKey) => {
                const ival = conflict(key, currentKey);
                return {
                    key: ival,
                };
            };
        }
        this.intervals.put(x, { minmax: x.clone() }, rbConflict);
    }
    map(fn) {
        const actions = {
            infix: (node) => {
                fn(node.key);
                return true;
            },
            showStructure: true,
        };
        this.intervals.walk(actions);
    }
    mapUntil(fn) {
        const actions = {
            infix: (node) => {
                return fn(node.key);
            },
            showStructure: true,
        };
        this.intervals.walk(actions);
    }
    mapBackward(fn) {
        const actions = {
            infix: (node) => {
                fn(node.key);
                return true;
            },
            showStructure: true,
        };
        this.intervals.walkBackward(actions);
    }
    // TODO: toString()
    match(x) {
        return this.intervals.gather(x, this);
    }
    matchNode(node, key) {
        return !!node && node.key.overlaps(key);
    }
    continueSubtree(node, key) {
        return !!node && node.data.minmax.overlaps(key);
    }
    update(node) {
        if (node.left && node.right) {
            node.data.minmax = node.key.union(node.left.data.minmax.union(node.right.data.minmax));
        }
        else {
            if (node.left) {
                node.data.minmax = node.key.union(node.left.data.minmax);
            }
            else if (node.right) {
                node.data.minmax = node.key.union(node.right.data.minmax);
            }
            else {
                node.data.minmax = node.key.clone();
            }
        }
    }
}
export class TST {
    constructor() {
        this.n = 0;
    }
    size() {
        return this.n;
    }
    contains(key) {
        return this.get(key);
    }
    get(key) {
        const x = this.nodeGet(this.root, key, 0);
        if (x === undefined) {
            return undefined;
        }
        return x.val;
    }
    nodeGet(x, key, d) {
        if (x === undefined) {
            return undefined;
        }
        const c = key.charAt(d);
        if (c < x.c) {
            return this.nodeGet(x.left, key, d);
        }
        else if (c > x.c) {
            return this.nodeGet(x.right, key, d);
        }
        else if (d < (key.length - 1)) {
            return this.nodeGet(x.mid, key, d + 1);
        }
        else {
            return x;
        }
    }
    put(key, val) {
        if (!this.contains(key)) {
            this.n++;
        }
        this.root = this.nodePut(this.root, key, val, 0);
    }
    nodePut(x, key, val, d) {
        let _x = x;
        const c = key.charAt(d);
        if (_x === undefined) {
            _x = { c };
        }
        if (c < _x.c) {
            _x.left = this.nodePut(_x.left, key, val, d);
        }
        else if (c > _x.c) {
            _x.right = this.nodePut(_x.right, key, val, d);
        }
        else if (d < (key.length - 1)) {
            _x.mid = this.nodePut(_x.mid, key, val, d + 1);
        }
        else {
            _x.val = val;
        }
        return _x;
    }
    neighbors(text, distance = 2) {
        let q = [];
        this.nodeProximity(this.root, { text: "" }, 0, text, distance, q);
        q = q.filter((value) => (value.text.length > 0));
        return q;
    }
    keysWithPrefix(text) {
        const q = [];
        const x = this.nodeGet(this.root, text, 0);
        if (x === undefined) {
            return q;
        }
        if (x.val !== undefined) {
            q.push(text);
        }
        this.collect(x.mid, { text }, q);
        return q;
    }
    collect(x, prefix, q) {
        if (x === undefined) {
            return;
        }
        this.collect(x.left, prefix, q);
        if (x.val !== undefined) {
            q.push(prefix.text + x.c);
        }
        this.collect(x.mid, { text: prefix.text + x.c }, q);
        this.collect(x.right, prefix, q);
    }
    mapNode(x, prefix, fn) {
        if (x === undefined) {
            return;
        }
        const key = prefix.text + x.c;
        this.mapNode(x.left, prefix, fn);
        if (x.val) {
            fn(key, x.val);
        }
        this.mapNode(x.mid, { text: key }, fn);
        this.mapNode(x.right, prefix, fn);
    }
    map(fn) {
        this.mapNode(this.root, { text: "" }, fn);
    }
    pairsWithPrefix(text) {
        const q = [];
        const x = this.nodeGet(this.root, text, 0);
        if (x === undefined) {
            return q;
        }
        if (x.val !== undefined) {
            q.push({ key: text, val: x.val });
        }
        this.collectPairs(x.mid, { text }, q);
        return q;
    }
    collectPairs(x, prefix, q) {
        if (x === undefined) {
            return;
        }
        this.collectPairs(x.left, prefix, q);
        if (x.val !== undefined) {
            q.push({ key: prefix.text + x.c, val: x.val });
        }
        this.collectPairs(x.mid, { text: prefix.text + x.c }, q);
        this.collectPairs(x.right, prefix, q);
    }
    nodeProximity(x, prefix, d, pattern, distance, q) {
        if ((x === undefined) || (distance < 0)) {
            return;
        }
        const c = pattern.charAt(d);
        if ((distance > 0) || (c < x.c)) {
            this.nodeProximity(x.left, prefix, d, pattern, distance, q);
        }
        if (x.val !== undefined) {
            const remD = distance - (pattern.length - d);
            if (remD >= 0) {
                let invD = distance;
                if (c !== x.c) {
                    invD--;
                }
                q.push({ text: prefix.text + x.c, val: x.val, invDistance: invD });
            }
        }
        const recurD = (d < (pattern.length - 1)) ? d + 1 : d;
        if (c === x.c) {
            this.nodeProximity(x.mid, { text: prefix.text + x.c }, recurD, pattern, distance, q);
        }
        else {
            this.nodeProximity(x.mid, { text: prefix.text + x.c }, recurD, pattern, distance - 1, q);
        }
        if ((distance > 0) || (c > x.c)) {
            this.nodeProximity(x.right, prefix, d, pattern, distance, q);
        }
    }
}
//# sourceMappingURL=collections.js.map