import { Defined, Compare, freeze, nat } from "../index.js" import { RedBlackTree, deleteElement, empty, findEqualElement, findMaximumElement, findMinimumElement, insertElement, isElementOf, iterateElements } from "./RedBlackTree.js" export interface RedBlackSet extends Iterable { order : Compare tree : RedBlackTree size : nat has(elem : E) : boolean findEqual(elem : E) : E | undefined insert(...elems : E[]) : RedBlackSet insertMultiple(elems : Iterable) : RedBlackSet delete(...elems : E[]) : RedBlackSet deleteMultiple(elems : Iterable) : RedBlackSet minimum() : E | undefined maximum() : E | undefined union(other : RedBlackSet) : RedBlackSet difference(other : RedBlackSet) : RedBlackSet intersection(other : RedBlackSet) : RedBlackSet filter(predicate : (elem : E) => boolean) : RedBlackSet } class RedBlackSetImpl implements RedBlackSet { order : Compare tree : RedBlackTree size : number constructor(order : Compare, tree : RedBlackTree, size : number) { this.order = order; this.tree = tree; this.size = size; freeze(this); } [Symbol.iterator]() { return iterateElements(this.tree); } has(elem : E) : boolean { return isElementOf(this.order, elem, this.tree); } findEqual(elem : E) : E | undefined { return findEqualElement(this.order, elem, this.tree); } insert(...elems : E[]) : RedBlackSetImpl { return this.insertMultiple(elems); } insertMultiple(elems : Iterable) : RedBlackSetImpl { let tree = this.tree; const order = this.order; let size = this.size; for (const elem of elems) { const t = insertElement(order, elem, tree); tree = t.result; if (t.previous === undefined) size += 1; } return new RedBlackSetImpl(order, tree, size); } delete(...elems : E[]) : RedBlackSetImpl { return this.deleteMultiple(elems); } deleteMultiple(elems : Iterable) : RedBlackSetImpl { let tree = this.tree; const order = this.order; let size = this.size; for (const elem of elems) { const t = deleteElement(order, elem, tree); tree = t.result; if (t.deleted !== undefined) size -= 1; } return new RedBlackSetImpl(order, tree, size); } minimum() : E | undefined { return findMinimumElement(this.tree); } maximum() : E | undefined { return findMaximumElement(this.tree); } union(other : RedBlackSet) : RedBlackSet { if (this.size >= other.size) return this.insertMultiple(other); else return other.insertMultiple(this); } difference(other : RedBlackSet) : RedBlackSet { return this.deleteMultiple(other); } filter(predicate : (elem : E) => boolean) : RedBlackSet { const elements : E[] = []; for (const elem of this) { if (predicate(elem)) elements.push(elem); } return RedBlackSet(this.order, elements); } intersection(other : RedBlackSet) : RedBlackSet { if (this.size <= other.size) return this.filter(e => other.has(e)); else return other.filter(e => this.has(e)); } } freeze(RedBlackSetImpl); export function RedBlackSet(order : Compare, elems? : Iterable) : RedBlackSet { const rb = new RedBlackSetImpl(order, empty(), 0); if (elems === undefined) return rb; else return rb.insertMultiple(elems); } freeze(RedBlackSet);