Refactor (2)
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
/** Returns a random element of the array */
|
||||
export const sample = <T>(arr: readonly T[]): T =>
|
||||
arr[Math.floor(Math.random() * arr.length)] as T;
|
||||
|
||||
export function sampleMany<T>(arr: T[], n: number = arr.length): T[] {
|
||||
/** Returns random N elements of the array */
|
||||
export function sampleMany<T>(arr: readonly T[], n: number = arr.length): T[] {
|
||||
if (n > arr.length) return sampleMany(arr, arr.length);
|
||||
const copy = [...arr];
|
||||
for (let i = 0; i < n; i++) {
|
||||
@@ -10,3 +12,47 @@ export function sampleMany<T>(arr: T[], n: number = arr.length): T[] {
|
||||
}
|
||||
return copy.slice(0, n);
|
||||
}
|
||||
|
||||
/** Returns a powerset of the array */
|
||||
export const power = <T>(arr: readonly T[]) =>
|
||||
arr.reduce((a, v) => a.concat(a.map((r) => r.concat(v))), [[]] as T[][]);
|
||||
|
||||
/** Returns all the permutations of the array */
|
||||
export function permutate<T>(arr: readonly T[]): T[][] {
|
||||
if (arr.length === 0) return [[]];
|
||||
const result: T[][] = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const current = arr[i];
|
||||
const remaining = [...arr.slice(0, i), ...arr.slice(i + 1)];
|
||||
for (const perm of permutate(remaining)) {
|
||||
result.push([current as T, ...perm]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Returns the maximal elements of the array w.r.t. the preorder */
|
||||
export function maximal<T>(
|
||||
arr: readonly T[],
|
||||
preorder: (x: T, y: T) => boolean,
|
||||
): T[] {
|
||||
const res: T[] = [];
|
||||
outer: for (const x of arr) {
|
||||
for (let i = 0; i < res.length; ) {
|
||||
const y = res[i] as T;
|
||||
const xLeY = preorder(x, y);
|
||||
const yLeX = preorder(y, x);
|
||||
|
||||
if (xLeY) {
|
||||
continue outer;
|
||||
}
|
||||
if (yLeX) {
|
||||
res.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
res.push(x);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
78
packages/utils/src/bitset.ts
Normal file
78
packages/utils/src/bitset.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
/** Generates a wrapper for bitset operations.
|
||||
* Works as an efficient replacement of `Set<T>` if the universal set is known.
|
||||
*/
|
||||
export class BitSet<T> {
|
||||
readonly universe: readonly T[];
|
||||
readonly empty: number;
|
||||
readonly all: number;
|
||||
|
||||
constructor(universe: readonly T[]) {
|
||||
this.universe = universe;
|
||||
this.empty = 0;
|
||||
this.all = 2 ** universe.length - 1;
|
||||
}
|
||||
|
||||
/** Create a bitset that represents the given values.
|
||||
* The value that is not in the universe is ignored.
|
||||
*/
|
||||
create(...values: readonly T[]) {
|
||||
return this.encode(new Set(values));
|
||||
}
|
||||
|
||||
/** Create a bitset from the given set.
|
||||
* The value that is not in the universe is ignored.
|
||||
*/
|
||||
encode(set: Set<T>): number {
|
||||
let x = 0;
|
||||
for (let i = 0; i < this.universe.length; i++) {
|
||||
if (set.has(this.universe[i] as T)) {
|
||||
x |= 1 << i;
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
/** Create a set from the given bitset. */
|
||||
decode(x: number): Set<T> {
|
||||
if (x < this.empty || x > this.all) throw Error("invalid bits");
|
||||
const decoded = new Set<T>();
|
||||
for (let j = 0; j < this.universe.length; j++) {
|
||||
if ((x & (1 << j)) !== 0) decoded.add(this.universe[j] as T);
|
||||
}
|
||||
return decoded;
|
||||
}
|
||||
|
||||
/** Returns the union of all the given bitsets. */
|
||||
union(...xs: readonly number[]): number {
|
||||
return xs.reduce((x, y) => x | y, this.empty);
|
||||
}
|
||||
|
||||
/** Returns the intersection of all the given bitsets. */
|
||||
intersection(...xs: readonly number[]): number {
|
||||
return xs.reduce((x, y) => x & y, this.all);
|
||||
}
|
||||
|
||||
/** Returns the bitset that is obtained from `x` by removing all the elements in `y`. */
|
||||
difference(x: number, y: number) {
|
||||
return x & (this.all - y);
|
||||
}
|
||||
|
||||
/** Returns if `x` and `y` are disjoint. */
|
||||
isDisjoint(x: number, y: number): boolean {
|
||||
return (x & y) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if `x` is a subset of `y`.
|
||||
*/
|
||||
isSubset(x: number, y: number): boolean {
|
||||
return (x & y) === x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if `x` is a superset of `y`.
|
||||
*/
|
||||
isSuperset(x: number, y: number): boolean {
|
||||
return (x & y) === y;
|
||||
}
|
||||
}
|
||||
9
packages/utils/src/index.ts
Normal file
9
packages/utils/src/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from "./array";
|
||||
|
||||
export * from "./bitset";
|
||||
|
||||
export * from "./headless";
|
||||
|
||||
export * from "./multiset";
|
||||
|
||||
export * from "./vector";
|
||||
Reference in New Issue
Block a user