import { MapFunction as MapFunction$1 } from 'extra-iterable';

/**
 * Handle reading of a single value.
 * [📘](https://github.com/nodef/extra-set/wiki/ReadFunction)
 * @returns value
 */
type ReadFunction<T> = () => T;
/**
 * Handle combining of two values.
 * [📘](https://github.com/nodef/extra-set/wiki/CombineFunction)
 * @param a a value
 * @param b another value
 * @returns combined value
 */
type CombineFunction<T> = (a: T, b: T) => T;
/**
 * Handle comparison of two values.
 * [📘](https://github.com/nodef/extra-set/wiki/CompareFunction)
 * @param a a value
 * @param b another value
 * @returns a<b: -ve, a=b: 0, a>b: +ve
 */
type CompareFunction<T> = (a: T, b: T) => number;
/**
 * Handle processing of values in a set.
 * [📘](https://github.com/nodef/extra-set/wiki/ProcessFunction)
 * @param v value in set
 * @param k key of value in set (= value)
 * @param x set containing the value
 */
type ProcessFunction<T> = (v: T, k: T, x: Set<T>) => void;
/**
 * Handle selection of values in a set.
 * [📘](https://github.com/nodef/extra-set/wiki/TestFunction)
 * @param v value in set
 * @param k key of value in set (= value)
 * @param x set containing the value
 * @returns selected?
 */
type TestFunction<T> = (v: T, k: T, x: Set<T>) => boolean;
/**
 * Handle transformation of a value to another.
 * [📘](https://github.com/nodef/extra-set/wiki/MapFunction)
 * @param v value in set
 * @param k key of value in set (= value)
 * @param x set containing the value
 * @returns transformed value
 */
type MapFunction<T, U> = (v: T, k: T, x: Set<T>) => U;
/**
 * Handle reduction of multiple values into a single value.
 * [📘](https://github.com/nodef/extra-set/wiki/ReduceFunction)
 * @param acc accumulator (temporary result)
 * @param v value in set
 * @param k key of value in set (= value)
 * @param x set containing the value
 * @returns reduced value
 */
type ReduceFunction<T, U> = (acc: U, v: T, k: T, x: Set<T>) => U;
/**
 * Handle ending of a combined set.
 * [📘](https://github.com/nodef/extra-set/wiki/EndFunction)
 * @param dones iᵗʰ set done?
 * @returns combined set done?
 */
type EndFunction = (dones: boolean[]) => boolean;
/**
 * Check if value is a set.
 * [📘](https://github.com/nodef/extra-set/wiki/is)
 * @param v a value
 * @returns v is a set?
 */
declare function is(v: any): v is Set<any>;
/**
 * List all values.
 * [📘](https://github.com/nodef/extra-set/wiki/values)
 * @param x a set
 * @returns v₀, v₁, ... | vᵢ ∈ x
 */
declare function values<T>(x: Set<T>): IterableIterator<T>;

/**
 * List all value-value pairs.
 * [📘](https://github.com/nodef/extra-set/wiki/entries)
 * @param x a set
 * @returns [v₀, v₀], [v₁, v₁], ... | vᵢ ∈ x
 */
declare function entries<T>(x: Set<T>): IterableIterator<[T, T]>;
/**
 * Convert an iterable to set.
 * [📘](https://github.com/nodef/extra-set/wiki/from)
 * @param x an iterable
 * @param fm map function (v, i, x)
 * @returns x as set
 */
declare function from<T, U = T>(x: Iterable<T>, fm?: MapFunction$1<T, U> | null): Set<T | U>;
/**
 * Convert an iterable to set.
 * [📘](https://github.com/nodef/extra-set/wiki/from$)
 * @param x an iterable (updatable if set!)
 * @returns x as set
 */
declare function from$<T>(x: Iterable<T>): Set<T>;
/**
 * Compare two sets.
 * [📘](https://github.com/nodef/extra-set/wiki/compare)
 * @param x a set
 * @param y another set
 * @returns x=y: 0, otherwise: -ve/+ve
 */
declare function compare<T>(x: Set<T>, y: Set<T>): number;
/**
 * Check if two sets are equal.
 * [📘](https://github.com/nodef/extra-set/wiki/isEqual)
 * @param x a set
 * @param y another set
 * @returns x = y?
 */
declare function isEqual<T>(x: Set<T>, y: Set<T>): boolean;
/**
 * Find the size of a set.
 * [📘](https://github.com/nodef/extra-set/wiki/size)
 * @param x a set
 * @returns |x|
 */
declare function size<T>(x: Set<T>): number;

/**
 * Check if a set is empty.
 * [📘](https://github.com/nodef/extra-set/wiki/isEmpty)
 * @param x a set
 * @returns |x| = 0?
 */
declare function isEmpty<T>(x: Set<T>): boolean;
/**
 * Add a value to set.
 * [📘](https://github.com/nodef/extra-set/wiki/add)
 * @param x a set
 * @param v value
 * @returns x ∪ \{v\}
 */
declare function add<T>(x: Set<T>, v: T): Set<T>;
/**
 * Add a value to set.
 * [📘](https://github.com/nodef/extra-set/wiki/add$)
 * @param x a set (updated)
 * @param v value
 * @returns x = x ∪ \{v\}
 */
declare function add$<T>(x: Set<T>, v: T): Set<T>;
/**
 * Delete a value from set.
 * [📘](https://github.com/nodef/extra-set/wiki/remove)
 * @param x a set
 * @param v value
 * @returns x \\ \{v\}
 */
declare function remove<T>(x: Set<T>, v: T): Set<T>;
/**
 * Delete a value from set.
 * [📘](https://github.com/nodef/extra-set/wiki/remove$)
 * @param x a set (updated)
 * @param v value
 * @returns x = x \\ \{v\}
 */
declare function remove$<T>(x: Set<T>, v: T): Set<T>;
/**
 * Count values which satisfy a test.
 * [📘](https://github.com/nodef/extra-set/wiki/count)
 * @param x a set
 * @param ft test function (v, v, x)
 * @returns Σtᵢ | tᵢ = 1 if ft(vᵢ) else 0; vᵢ ∈ x
 */
declare function count<T>(x: Set<T>, ft: TestFunction<T>): number;
/**
 * Count occurrences of values.
 * [📘](https://github.com/nodef/extra-set/wiki/countAs)
 * @param x a set
 * @param fm map function (v, v, x)
 * @returns Map \{value ⇒ count\}
 */
declare function countAs<T, U = T>(x: Set<T>, fm: MapFunction<T, T | U>): Map<T | U, number>;
/**
 * Find smallest value.
 * [📘](https://github.com/nodef/extra-set/wiki/min)
 * @param x a set
 * @param fc compare function (a, b)
 * @param fm map function (v, v, x)
 * @returns v | v ≤ vᵢ; vᵢ ∈ x
 */
declare function min<T, U = T>(x: Set<T>, fc?: CompareFunction<T | U> | null, fm?: MapFunction<T, T | U> | null): T;
/**
 * Find largest value.
 * [📘](https://github.com/nodef/extra-set/wiki/max)
 * @param x a set
 * @param fc compare function (a, b)
 * @param fm map function (v, v, x)
 * @returns v | v ≥ vᵢ; vᵢ ∈ x
 */
declare function max<T, U = T>(x: Set<T>, fc?: CompareFunction<T | U> | null, fm?: MapFunction<T, T | U> | null): T;
/**
 * Find smallest and largest entries.
 * [📘](https://github.com/nodef/extra-set/wiki/range)
 * @param x a set
 * @param fc compare function (a, b)
 * @param fm map function (v, v, x)
 * @returns [min_value, max_value]
 */
declare function range<T, U = T>(x: Set<T>, fc?: CompareFunction<T | U> | null, fm?: MapFunction<T, T | U> | null): [T, T];
/**
 * Get first value from set (default order).
 * [📘](https://github.com/nodef/extra-set/wiki/head)
 * @param x a set
 * @param vd default value
 * @returns v₀ if x ≠ Φ else vd | v₀ ∈ x
 */
declare function head<T>(x: Set<T>, vd?: T): T | undefined;
/**
 * Get a set without its first value (default order).
 * [📘](https://github.com/nodef/extra-set/wiki/tail)
 * @param x a set
 * @returns x \\ \{v₀\} if x ≠ Φ else x | v₀ ∈ x
 */
declare function tail<T>(x: Set<T>): Set<T>;
/**
 * Keep first n values only (default order).
 * [📘](https://github.com/nodef/extra-set/wiki/take)
 * @param x a set
 * @param n number of values [1]
 * @returns \{v₀, v₁, ...\} | vᵢ ∈ x and |\{v₀, v₁, ...\}| ≤ n
 */
declare function take<T>(x: Iterable<T>, n?: number): Set<T>;
/**
 * Keep first n values only (default order).
 * [📘](https://github.com/nodef/extra-set/wiki/take$)
 * @param x a set (updated)
 * @param n number of values [1]
 * @returns x = \{v₀, v₁, ...\} | vᵢ ∈ x and |\{v₀, v₁, ...\}| ≤ n
 */
declare function take$<T>(x: Set<T>, n?: number): Set<T>;
/**
 * Remove first n values (default order).
 * [📘](https://github.com/nodef/extra-set/wiki/drop)
 * @param x a set
 * @param n number of values [1]
 * @returns \{vₙ, vₙ₊₁, ...\} | vᵢ ∈ x and |\{vₙ, vₙ₊₁, ...\}| ≤ max(|x| - n, 0)
 */
declare function drop<T>(x: Set<T>, n?: number): Set<T>;
/**
 * Remove first n values (default order).
 * [📘](https://github.com/nodef/extra-set/wiki/drop$)
 * @param x a set (updated)
 * @param n number of values [1]
 * @returns x = \{vₙ, vₙ₊₁, ...\} | vᵢ ∈ x and |\{vₙ, vₙ₊₁, ...\}| ≤ max(|x| - n, 0)
 */
declare function drop$<T>(x: Set<T>, n?: number): Set<T>;
/**
 * List all possible subsets.
 * [📘](https://github.com/nodef/extra-set/wiki/subsets)
 * @param x a set
 * @param n number of values [-1 ⇒ any]
 * @returns elements selected by bit from 0..2^|x| if n<0; only of length n otherwise
 */
declare function subsets<T>(x: Set<T>, n?: number): IterableIterator<Set<T>>;
/**
 * Pick an arbitrary value.
 * [📘](https://github.com/nodef/extra-set/wiki/randomValue)
 * @param x a set
 * @param fr random number generator ([0, 1))
 * @returns vᵢ | vᵢ ∈ x
 */
declare function randomValue<T>(x: Set<T>, fr?: ReadFunction<number>): T;

/**
 * Pick an arbitrary entry.
 * [📘](https://github.com/nodef/extra-set/wiki/randomEntry)
 * @param x a set
 * @param fr random number generator ([0, 1))
 * @returns [vᵢ, vᵢ] | vᵢ ∈ x
 */
declare function randomEntry<T>(x: Set<T>, fr?: ReadFunction<number>): [T, T];

/**
 * Pick an arbitrary subset.
 * [📘](https://github.com/nodef/extra-set/wiki/randomSubset)
 * @param x a set
 * @param n number of values [-1 ⇒ any]
 * @param fr random number generator ([0, 1))
 * @returns \{vᵢ, vⱼ, ...\} | vᵢ, vⱼ, ... ∈ x; |\{vᵢ, vⱼ, ...\}| = |x| if n<0 else n
 */
declare function randomSubset<T>(x: Set<T>, n?: number, fr?: ReadFunction<number>): Set<T>;
/**
 * Checks if set has a subset.
 * [📘](https://github.com/nodef/extra-set/wiki/hasSubset)
 * @param x a set
 * @param y search subset
 * @returns y ⊆ x?
 */
declare function hasSubset<T>(x: Set<T>, y: Set<T>): boolean;
/**
 * Check if set has a value.
 * [📘](https://github.com/nodef/extra-set/wiki/has)
 * @param x a set
 * @param v search value
 * @returns v ∈ x?
 */
declare function has<T>(x: Set<T>, v: T): boolean;
/**
 * Find first value passing a test (default order).
 * [📘](https://github.com/nodef/extra-set/wiki/find)
 * @param x a set
 * @param ft test function (v, v, x)
 * @returns first v | ft(v) = true; v ∈ x
 */
declare function find<T>(x: Set<T>, ft: TestFunction<T>): T;

/**
 * Find all values passing a test.
 * [📘](https://github.com/nodef/extra-set/wiki/findAll)
 * @param x a set
 * @param ft test function (v, v, x)
 * @returns [v₀, v₁, ...] | ft(vᵢ) = true; vᵢ ∈ x
 */
declare function findAll<T>(x: Set<T>, ft: TestFunction<T>): T[];

/**
 * Call a function for each value.
 * [📘](https://github.com/nodef/extra-set/wiki/forEach)
 * @param x a set
 * @param fp process function (v, v, x)
 */
declare function forEach<T>(x: Set<T>, fp: ProcessFunction<T>): void;
/**
 * Check if any value satisfies a test.
 * [📘](https://github.com/nodef/extra-set/wiki/some)
 * @param x a set
 * @param ft test function (v, v, x)
 * @returns true if ft(vᵢ) = true for some vᵢ ∈ x
 */
declare function some<T>(x: Set<T>, ft?: TestFunction<T> | null): boolean;
/**
 * Check if all values satisfy a test.
 * [📘](https://github.com/nodef/extra-set/wiki/every)
 * @param x a set
 * @param ft test function (v, v, x)
 * @returns true if ft(vᵢ) = true for all vᵢ ∈ x
 */
declare function every<T>(x: Set<T>, ft?: TestFunction<T> | null): boolean;
/**
 * Transform values of a set.
 * [📘](https://github.com/nodef/extra-set/wiki/map)
 * @param x a set
 * @param fm map function (v, v, x)
 * @returns \{fm(v₀), fm(v₁), ...\} | vᵢ ∈ x
 */
declare function map<T, U = T>(x: Set<T>, fm: MapFunction<T, T | U>): Set<T | U>;
/**
 * Transform values of a set.
 * [📘](https://github.com/nodef/extra-set/wiki/map$)
 * @param x a set (updated)
 * @param fm map function (v, v, x)
 * @returns x = \{fm(v₀), fm(v₁), ...\} | vᵢ ∈ x
 */
declare function map$<T>(x: Set<T>, fm: MapFunction<T, T>): Set<T>;
/**
 * Reduce values of set to a single value.
 * [📘](https://github.com/nodef/extra-set/wiki/reduce)
 * @param x a set
 * @param fr reduce function (acc, v, v, x)
 * @param acc initial value
 * @returns fr(fr(acc, v₀), v₁)... | fr(acc, v₀) = v₀ if acc not given
 */
declare function reduce<T, U = T>(x: Set<T>, fr: ReduceFunction<T, T | U>, acc?: T | U): T | U;
/**
 * Keep values which pass a test.
 * [📘](https://github.com/nodef/extra-set/wiki/filter)
 * @param x a set
 * @param ft test function (v, v, x)
 * @returns \{v₀, v₁, ...\} | ft(vᵢ) = true; vᵢ ∈ x
 */
declare function filter<T>(x: Set<T>, ft: TestFunction<T>): Set<T>;
/**
 * Keep values which pass a test.
 * [📘](https://github.com/nodef/extra-set/wiki/filter$)
 * @param x a set (updated)
 * @param ft test function (v, v, x)
 * @returns x = \{v₀, v₁, ...\} | ft(vᵢ) = true; vᵢ ∈ x
 */
declare function filter$<T>(x: Set<T>, ft: TestFunction<T>): Set<T>;
/**
 * Discard values which pass a test.
 * [📘](https://github.com/nodef/extra-set/wiki/reject)
 * @param x a set
 * @param ft test function (v, v, x)
 * @returns \{v₀, v₁, ...\} | ft(vᵢ) = false; vᵢ ∈ x
 */
declare function reject<T>(x: Set<T>, ft: TestFunction<T>): Set<T>;
/**
 * Discard values which pass a test.
 * [📘](https://github.com/nodef/extra-set/wiki/reject$)
 * @param x a set (updated)
 * @param ft test function (v, v, x)
 * @returns x = \{v₀, v₁, ...\} | ft(vᵢ) = false; vᵢ ∈ x
 */
declare function reject$<T>(x: Set<T>, ft: TestFunction<T>): Set<T>;
/**
 * Flatten nested set to given depth.
 * [📘](https://github.com/nodef/extra-set/wiki/flat)
 * @param x a nested set
 * @param n maximum depth [-1 ⇒ all]
 * @param fm map function (v, v, x)
 * @param ft flatten test function (v, v, x) [is]
 * @returns flat set
 */
declare function flat<T = any>(x: Set<T>, n?: number, fm?: MapFunction<T, any> | null, ft?: TestFunction<T> | null): Set<any>;
/**
 * Flatten nested set, based on map function.
 * [📘](https://github.com/nodef/extra-set/wiki/flatMap)
 * @param x a nested set
 * @param fm map function (v, v, x)
 * @param ft flatten test function (v, v, x) [is]
 * @returns flat set
 */
declare function flatMap<T = any>(x: Set<T>, fm?: MapFunction<T, any> | null, ft?: TestFunction<T> | null): Set<any>;
/**
 * Segregate values by test result.
 * [📘](https://github.com/nodef/extra-set/wiki/partition)
 * @param x a set
 * @param ft test function (v, v, x)
 * @returns [satisfies, doesnt]
 */
declare function partition<T>(x: Set<T>, ft: TestFunction<T>): [Set<T>, Set<T>];
/**
 * Segregates values by similarity.
 * [📘](https://github.com/nodef/extra-set/wiki/partitionAs)
 * @param x a set
 * @param fm map function (v, v, x)
 * @returns Map \{key ⇒ values\}
 */
declare function partitionAs<T, U = T>(x: Set<T>, fm: MapFunction<T, T | U>): Map<T | U, Set<T>>;
/**
 * Break set into chunks of given size.
 * [📘](https://github.com/nodef/extra-set/wiki/chunk)
 * @param x a set
 * @param n chunk size [1]
 * @param s chunk step [n]
 * @returns [x[0..n], x[s..s+n], x[2s..2s+n], ...]
 */
declare function chunk<T>(x: Set<T>, n?: number, s?: number): Set<T>[];
/**
 * Append values from sets.
 * [📘](https://github.com/nodef/extra-set/wiki/concat)
 * @param xs sets
 * @returns x₀ ∪ x₁ ∪ ... | [x₀, x₁, ...] = xs
 */
declare function concat<T>(...xs: Set<T>[]): Set<T>;
/**
 * Append values from sets.
 * [📘](https://github.com/nodef/extra-set/wiki/concat$)
 * @param x a set (updated)
 * @param ys other sets
 * @returns x = x ∪ y₀ ∪ y₁ ∪ ... | [y₀, y₁, ...] = ys
 */
declare function concat$<T>(x: Set<T>, ...ys: Iterable<T>[]): Set<T>;
/**
 * Join values together into a string.
 * [📘](https://github.com/nodef/extra-set/wiki/join)
 * @param x a set
 * @param sep separator [,]
 * @returns "$\{v₀\}$\{sep\}$\{v₁\}..." | vᵢ ∈ x
 */
declare function join<T>(x: Set<T>, sep?: string): string;
/**
 * Check if sets have no value in common.
 * [📘](https://github.com/nodef/extra-set/wiki/isDisjoint)
 * @param x a set
 * @param y another set
 * @returns x ∩ y = Φ?
 */
declare function isDisjoint<T>(x: Set<T>, y: Iterable<T>): boolean;
/**
 * Obtain values present in any set.
 * [📘](https://github.com/nodef/extra-set/wiki/union)
 * @param x a set
 * @param y another set
 * @returns x ∪ y = \{v | v ∈ x or v ∈ y\}
 */
declare function union<T>(x: Iterable<T>, y: Iterable<T>): Set<T>;
/**
 * Obtain values present in any set.
 * [📘](https://github.com/nodef/extra-set/wiki/union$)
 * @param x a set (updated)
 * @param y another set
 * @returns x = x ∪ y = \{v | v ∈ x or v ∈ y\}
 */
declare function union$<T>(x: Set<T>, y: Iterable<T>): Set<T>;
/**
 * Obtain values present in both sets.
 * [📘](https://github.com/nodef/extra-set/wiki/intersection)
 * @param x a set
 * @param y another set
 * @returns x ∩ y = \{v | v ∈ x, v ∈ y\}
 */
declare function intersection<T>(x: Set<T>, y: Iterable<T>): Set<T>;
/**
 * Obtain values present in both sets.
 * [📘](https://github.com/nodef/extra-set/wiki/intersection$)
 * @param x a set (updated)
 * @param y another set
 * @returns x = x ∩ y = \{v | v ∈ x, v ∈ y\}
 */
declare function intersection$<T>(x: Set<T>, y: Set<T>): Set<T>;
/**
 * Obtain values not present in another set.
 * [📘](https://github.com/nodef/extra-set/wiki/difference)
 * @param x a set
 * @param y another set
 * @returns x - y = \{v | v ∈ x, v ∉ y\}
 */
declare function difference<T>(x: Set<T>, y: Set<T>): Set<T>;
/**
 * Obtain values not present in another set.
 * [📘](https://github.com/nodef/extra-set/wiki/difference$)
 * @param x a set (updated)
 * @param y another set
 * @returns x = x - y = \{v | v ∈ x, v ∉ y\}
 */
declare function difference$<T>(x: Set<T>, y: Iterable<T>): Set<T>;
/**
 * Obtain values not present in both sets.
 * [📘](https://github.com/nodef/extra-set/wiki/symmetricDifference)
 * @param x a set
 * @param y another set
 * @returns x-y ∪ y-x
 */
declare function symmetricDifference<T>(x: Set<T>, y: Set<T>): Set<T>;
/**
 * Obtain values not present in both sets.
 * [📘](https://github.com/nodef/extra-set/wiki/symmetricDifference$)
 * @param x a set (updated)
 * @param y another set
 * @returns x = x-y ∪ y-x
 */
declare function symmetricDifference$<T>(x: Set<T>, y: Iterable<T>): Set<T>;
/**
 * List cartesian product of sets.
 * [📘](https://github.com/nodef/extra-set/wiki/cartesianProduct)
 * @param xs sets
 * @param fm map function (vs, vs)
 * @returns x₀ × x₁ × ... = \{\{v₀, v₁, ...\} | v₀ ∈ x₀, v₁ ∈ x₁, ...]\}
 */
declare function cartesianProduct<T, U = Set<T>>(xs: Set<T>[], fm?: MapFunction<Set<T>, Set<T> | U> | null): IterableIterator<Set<T> | U>;

export { type CombineFunction, type CompareFunction, type EndFunction, type MapFunction, type ProcessFunction, type ReadFunction, type ReduceFunction, type TestFunction, add, add$, cartesianProduct, chunk, compare, concat, concat$, count, countAs, cartesianProduct as default, difference, difference$, drop, drop$, entries, randomEntry as entry, every, filter, filter$, find, findAll, flat, flatMap, forEach, from, from$, has, hasSubset, head, intersection, intersection$, is, isDisjoint, isEmpty, isEqual, join, randomValue as key, values as keys, size as length, map, map$, max, min, partition, partitionAs, randomEntry, randomValue as randomKey, randomSubset, randomValue, range, reduce, reject, reject$, remove, remove$, find as search, findAll as searchAll, size, some, subsets, symmetricDifference, symmetricDifference$, tail, take, take$, union, union$, randomValue as value, values };
