Refactor (2)
This commit is contained in:
215
packages/utils/tests/array.test.ts
Normal file
215
packages/utils/tests/array.test.ts
Normal file
@@ -0,0 +1,215 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { maximal, permutate, power, sample, sampleMany } from "../src/array";
|
||||
|
||||
describe("array utilities", () => {
|
||||
describe("sample", () => {
|
||||
it("should return an element from the array", () => {
|
||||
const arr = [1, 2, 3, 4, 5];
|
||||
const result = sample(arr);
|
||||
expect(arr).toContain(result);
|
||||
});
|
||||
|
||||
it("should work with single element array", () => {
|
||||
const arr = [42];
|
||||
expect(sample(arr)).toBe(42);
|
||||
});
|
||||
|
||||
it("should work with different types", () => {
|
||||
const strArr = ["a", "b", "c"];
|
||||
const result = sample(strArr);
|
||||
expect(strArr).toContain(result);
|
||||
});
|
||||
});
|
||||
|
||||
describe("sampleMany", () => {
|
||||
it("should return n random elements", () => {
|
||||
const arr = [1, 2, 3, 4, 5];
|
||||
const result = sampleMany(arr, 3);
|
||||
expect(result).toHaveLength(3);
|
||||
for (const item of result) {
|
||||
expect(arr).toContain(item);
|
||||
}
|
||||
});
|
||||
|
||||
it("should return all elements when n equals array length", () => {
|
||||
const arr = [1, 2, 3];
|
||||
const result = sampleMany(arr, 3);
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result.sort()).toEqual(arr.sort());
|
||||
});
|
||||
|
||||
it("should return all elements when n is greater than array length", () => {
|
||||
const arr = [1, 2, 3];
|
||||
const result = sampleMany(arr, 5);
|
||||
expect(result).toHaveLength(3);
|
||||
expect(result.sort()).toEqual(arr.sort());
|
||||
});
|
||||
|
||||
it("should return all elements when n is not provided", () => {
|
||||
const arr = [1, 2, 3, 4];
|
||||
const result = sampleMany(arr);
|
||||
expect(result).toHaveLength(4);
|
||||
expect(result.sort()).toEqual(arr.sort());
|
||||
});
|
||||
|
||||
it("should return empty array for empty input", () => {
|
||||
const arr: number[] = [];
|
||||
const result = sampleMany(arr, 3);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it("should not return duplicate elements", () => {
|
||||
const arr = [1, 2, 3, 4, 5];
|
||||
const result = sampleMany(arr, 5);
|
||||
const uniqueSet = new Set(result);
|
||||
expect(uniqueSet.size).toBe(result.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe("power", () => {
|
||||
it("should return powerset of array", () => {
|
||||
const arr = [1, 2];
|
||||
const result = power(arr);
|
||||
expect(result).toHaveLength(4);
|
||||
expect(result).toContainEqual([]);
|
||||
expect(result).toContainEqual([1]);
|
||||
expect(result).toContainEqual([2]);
|
||||
expect(result).toContainEqual([1, 2]);
|
||||
});
|
||||
|
||||
it("should return [[]] for empty array", () => {
|
||||
const arr: number[] = [];
|
||||
const result = power(arr);
|
||||
expect(result).toEqual([[]]);
|
||||
});
|
||||
|
||||
it("should handle three elements", () => {
|
||||
const arr = [1, 2, 3];
|
||||
const result = power(arr);
|
||||
expect(result).toHaveLength(8);
|
||||
expect(result).toContainEqual([]);
|
||||
expect(result).toContainEqual([1]);
|
||||
expect(result).toContainEqual([2]);
|
||||
expect(result).toContainEqual([3]);
|
||||
expect(result).toContainEqual([1, 2]);
|
||||
expect(result).toContainEqual([1, 3]);
|
||||
expect(result).toContainEqual([2, 3]);
|
||||
expect(result).toContainEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("should work with strings", () => {
|
||||
const arr = ["a", "b"];
|
||||
const result = power(arr);
|
||||
expect(result).toHaveLength(4);
|
||||
expect(result).toContainEqual([]);
|
||||
expect(result).toContainEqual(["a"]);
|
||||
expect(result).toContainEqual(["b"]);
|
||||
expect(result).toContainEqual(["a", "b"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("permutate", () => {
|
||||
it("should return all permutations of array", () => {
|
||||
const arr = [1, 2];
|
||||
const result = permutate(arr);
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result).toContainEqual([1, 2]);
|
||||
expect(result).toContainEqual([2, 1]);
|
||||
});
|
||||
|
||||
it("should return [[]] for empty array", () => {
|
||||
const arr: number[] = [];
|
||||
const result = permutate(arr);
|
||||
expect(result).toEqual([[]]);
|
||||
});
|
||||
|
||||
it("should handle single element", () => {
|
||||
const arr = [1];
|
||||
const result = permutate(arr);
|
||||
expect(result).toEqual([[1]]);
|
||||
});
|
||||
|
||||
it("should handle three elements", () => {
|
||||
const arr = [1, 2, 3];
|
||||
const result = permutate(arr);
|
||||
expect(result).toHaveLength(6);
|
||||
expect(result).toContainEqual([1, 2, 3]);
|
||||
expect(result).toContainEqual([1, 3, 2]);
|
||||
expect(result).toContainEqual([2, 1, 3]);
|
||||
expect(result).toContainEqual([2, 3, 1]);
|
||||
expect(result).toContainEqual([3, 1, 2]);
|
||||
expect(result).toContainEqual([3, 2, 1]);
|
||||
});
|
||||
|
||||
it("should work with strings", () => {
|
||||
const arr = ["a", "b", "c"];
|
||||
const result = permutate(arr);
|
||||
expect(result).toHaveLength(6);
|
||||
// Check that all permutations are unique
|
||||
const stringified = result.map((p) => p.join(""));
|
||||
const unique = new Set(stringified);
|
||||
expect(unique.size).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe("maximal", () => {
|
||||
it("should return maximal elements with simple less-than preorder", () => {
|
||||
const arr = [1, 2, 3, 2, 1];
|
||||
const result = maximal(arr, (x, y) => x <= y);
|
||||
expect(result).toEqual([3]);
|
||||
});
|
||||
|
||||
it("should handle incomparable elements", () => {
|
||||
// Divisibility preorder: x <= y if x divides y
|
||||
const arr = [2, 3, 4, 6, 8, 9];
|
||||
const divides = (x: number, y: number) => y % x === 0;
|
||||
const result = maximal(arr, divides);
|
||||
// 8 and 9 are maximal (nothing in the array is divisible by them except themselves)
|
||||
expect(result.sort()).toEqual([6, 8, 9]);
|
||||
});
|
||||
|
||||
it("should return all elements when all are incomparable", () => {
|
||||
const arr = [1, 2, 3];
|
||||
// Always false preorder means all elements are incomparable
|
||||
const result = maximal(arr, () => false);
|
||||
expect(result.sort()).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("should handle empty array", () => {
|
||||
const arr: number[] = [];
|
||||
const result = maximal(arr, (x, y) => x <= y);
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it("should handle single element", () => {
|
||||
const arr = [42];
|
||||
const result = maximal(arr, (x, y) => x <= y);
|
||||
expect(result).toEqual([42]);
|
||||
});
|
||||
|
||||
it("should handle subset preorder", () => {
|
||||
// Subset preorder on sets represented as arrays
|
||||
const arr = [[1], [2], [1, 2], [2, 3], [1, 2, 3]];
|
||||
const isSubset = (x: number[], y: number[]) =>
|
||||
x.every((elem) => y.includes(elem));
|
||||
const result = maximal(arr, isSubset);
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0]).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
it("should remove duplicate maximal elements", () => {
|
||||
const arr = [3, 1, 2, 3, 2];
|
||||
const result = maximal(arr, (x, y) => x <= y);
|
||||
expect(result).toEqual([3]);
|
||||
});
|
||||
|
||||
it("should preserve order of maximal elements", () => {
|
||||
// Divisibility preorder: x <= y if x divides y
|
||||
const arr = [2, 6, 4, 3, 9, 8];
|
||||
const divides = (x: number, y: number) => y % x === 0;
|
||||
const result = maximal(arr, divides);
|
||||
// Check that the maximal elements appear in the same order as in the original array
|
||||
expect(result).toEqual([6, 9, 8]);
|
||||
});
|
||||
});
|
||||
});
|
||||
371
packages/utils/tests/bitset.test.ts
Normal file
371
packages/utils/tests/bitset.test.ts
Normal file
@@ -0,0 +1,371 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { BitSet } from "../src/bitset";
|
||||
|
||||
describe("BitSet", () => {
|
||||
// Test with string universe
|
||||
const stringUniverse = ["a", "b", "c", "d", "e"];
|
||||
const stringBitSet = new BitSet<string>(stringUniverse);
|
||||
|
||||
// Test with number universe
|
||||
const numberUniverse = [1, 2, 3, 4, 5, 6, 7, 8];
|
||||
const numberBitSet = new BitSet<number>(numberUniverse);
|
||||
|
||||
describe("constructor", () => {
|
||||
it("should initialize with correct universe", () => {
|
||||
expect(stringBitSet.universe).toEqual(stringUniverse);
|
||||
expect(numberBitSet.universe).toEqual(numberUniverse);
|
||||
});
|
||||
|
||||
it("should calculate empty as 0", () => {
|
||||
expect(stringBitSet.empty).toBe(0);
|
||||
expect(numberBitSet.empty).toBe(0);
|
||||
});
|
||||
|
||||
it("should calculate all correctly", () => {
|
||||
expect(stringBitSet.all).toBe(0b11111); // 2^5 - 1 = 31
|
||||
expect(numberBitSet.all).toBe(0b11111111); // 2^8 - 1 = 255
|
||||
});
|
||||
});
|
||||
|
||||
describe("create", () => {
|
||||
it("should create empty bitset when no values provided", () => {
|
||||
const bitset = stringBitSet.create();
|
||||
expect(bitset).toBe(0);
|
||||
});
|
||||
|
||||
it("should create bitset from single value", () => {
|
||||
const bitset = stringBitSet.create("a");
|
||||
const reference = new Set(["a"]);
|
||||
expect(stringBitSet.decode(bitset)).toEqual(reference);
|
||||
});
|
||||
|
||||
it("should create bitset from multiple values", () => {
|
||||
const bitset = stringBitSet.create("a", "c", "e");
|
||||
const reference = new Set(["a", "c", "e"]);
|
||||
expect(stringBitSet.decode(bitset)).toEqual(reference);
|
||||
});
|
||||
|
||||
it("should ignore values not in universe", () => {
|
||||
const bitset = stringBitSet.create("a", "z", "b", "x");
|
||||
const reference = new Set(["a", "b"]);
|
||||
expect(stringBitSet.decode(bitset)).toEqual(reference);
|
||||
});
|
||||
|
||||
it("should handle duplicate values", () => {
|
||||
const bitset = stringBitSet.create("a", "a", "b", "b");
|
||||
const reference = new Set(["a", "b"]);
|
||||
expect(stringBitSet.decode(bitset)).toEqual(reference);
|
||||
});
|
||||
});
|
||||
|
||||
describe("encode", () => {
|
||||
it("should encode empty set to 0", () => {
|
||||
const set = new Set<string>();
|
||||
expect(stringBitSet.encode(set)).toBe(0);
|
||||
});
|
||||
|
||||
it("should encode full set correctly", () => {
|
||||
const set = new Set(stringUniverse);
|
||||
expect(stringBitSet.encode(set)).toBe(stringBitSet.all);
|
||||
});
|
||||
|
||||
it("should encode subset correctly", () => {
|
||||
const set = new Set(["b", "d"]);
|
||||
const bitset = stringBitSet.encode(set);
|
||||
expect(stringBitSet.decode(bitset)).toEqual(set);
|
||||
});
|
||||
|
||||
it("should ignore elements not in universe", () => {
|
||||
const set = new Set(["a", "x", "y", "c"]);
|
||||
const bitset = stringBitSet.encode(set);
|
||||
const expected = new Set(["a", "c"]);
|
||||
expect(stringBitSet.decode(bitset)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("decode", () => {
|
||||
it("should decode 0 to empty set", () => {
|
||||
expect(stringBitSet.decode(0)).toEqual(new Set());
|
||||
});
|
||||
|
||||
it("should decode all bits to full set", () => {
|
||||
expect(stringBitSet.decode(stringBitSet.all)).toEqual(
|
||||
new Set(stringUniverse),
|
||||
);
|
||||
});
|
||||
|
||||
it("should decode specific bits correctly", () => {
|
||||
// bits: 10101 = positions 0, 2, 4 = 'a', 'c', 'e'
|
||||
const bitset = 0b10101;
|
||||
expect(stringBitSet.decode(bitset)).toEqual(new Set(["a", "c", "e"]));
|
||||
});
|
||||
|
||||
it("should throw error for invalid bits (negative)", () => {
|
||||
expect(() => stringBitSet.decode(-1)).toThrow("invalid bits");
|
||||
});
|
||||
|
||||
it("should throw error for invalid bits (too large)", () => {
|
||||
expect(() => stringBitSet.decode(stringBitSet.all + 1)).toThrow(
|
||||
"invalid bits",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("union", () => {
|
||||
it("should return empty for no arguments", () => {
|
||||
expect(stringBitSet.union()).toBe(0);
|
||||
});
|
||||
|
||||
it("should return same value for single argument", () => {
|
||||
const bitset = stringBitSet.create("a", "b");
|
||||
expect(stringBitSet.union(bitset)).toBe(bitset);
|
||||
});
|
||||
|
||||
it("should compute union correctly", () => {
|
||||
const set1 = new Set(["a", "b"]);
|
||||
const set2 = new Set(["b", "c"]);
|
||||
const set3 = new Set(["d"]);
|
||||
|
||||
const bitset1 = stringBitSet.encode(set1);
|
||||
const bitset2 = stringBitSet.encode(set2);
|
||||
const bitset3 = stringBitSet.encode(set3);
|
||||
|
||||
const unionBitset = stringBitSet.union(bitset1, bitset2, bitset3);
|
||||
const unionSet = stringBitSet.decode(unionBitset);
|
||||
|
||||
// Reference using standard Set
|
||||
const referenceUnion = new Set([...set1, ...set2, ...set3]);
|
||||
expect(unionSet).toEqual(referenceUnion);
|
||||
});
|
||||
|
||||
it("should handle union with empty sets", () => {
|
||||
const bitset1 = stringBitSet.create("a", "b");
|
||||
const empty = stringBitSet.empty;
|
||||
|
||||
expect(stringBitSet.union(bitset1, empty)).toBe(bitset1);
|
||||
expect(stringBitSet.union(empty, bitset1)).toBe(bitset1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("intersection", () => {
|
||||
it("should return all bits for no arguments", () => {
|
||||
// This is because reduce with no initial value uses first element
|
||||
expect(stringBitSet.intersection()).toBe(stringBitSet.all);
|
||||
});
|
||||
|
||||
it("should return same value for single argument", () => {
|
||||
const bitset = stringBitSet.create("a", "b");
|
||||
expect(stringBitSet.intersection(bitset)).toBe(bitset);
|
||||
});
|
||||
|
||||
it("should compute intersection correctly", () => {
|
||||
const set1 = new Set(["a", "b", "c"]);
|
||||
const set2 = new Set(["b", "c", "d"]);
|
||||
const set3 = new Set(["c", "d", "e"]);
|
||||
|
||||
const bitset1 = stringBitSet.encode(set1);
|
||||
const bitset2 = stringBitSet.encode(set2);
|
||||
const bitset3 = stringBitSet.encode(set3);
|
||||
|
||||
const intersectionBitset = stringBitSet.intersection(
|
||||
bitset1,
|
||||
bitset2,
|
||||
bitset3,
|
||||
);
|
||||
const intersectionSet = stringBitSet.decode(intersectionBitset);
|
||||
|
||||
// Reference using standard Set
|
||||
const referenceIntersection = new Set(
|
||||
[...set1].filter((x) => set2.has(x) && set3.has(x)),
|
||||
);
|
||||
expect(intersectionSet).toEqual(referenceIntersection);
|
||||
});
|
||||
|
||||
it("should handle intersection with empty set", () => {
|
||||
const bitset1 = stringBitSet.create("a", "b");
|
||||
const empty = stringBitSet.empty;
|
||||
|
||||
expect(stringBitSet.intersection(bitset1, empty)).toBe(empty);
|
||||
expect(stringBitSet.intersection(empty, bitset1)).toBe(empty);
|
||||
});
|
||||
|
||||
it("should handle disjoint sets", () => {
|
||||
const bitset1 = stringBitSet.create("a", "b");
|
||||
const bitset2 = stringBitSet.create("c", "d");
|
||||
|
||||
expect(stringBitSet.intersection(bitset1, bitset2)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("difference", () => {
|
||||
it("should compute difference correctly", () => {
|
||||
const set1 = new Set(["a", "b", "c", "d"]);
|
||||
const set2 = new Set(["b", "d"]);
|
||||
|
||||
const bitset1 = stringBitSet.encode(set1);
|
||||
const bitset2 = stringBitSet.encode(set2);
|
||||
|
||||
const differenceBitset = stringBitSet.difference(bitset1, bitset2);
|
||||
const differenceSet = stringBitSet.decode(differenceBitset);
|
||||
|
||||
// Reference using standard Set
|
||||
const referenceDifference = new Set(
|
||||
[...set1].filter((x) => !set2.has(x)),
|
||||
);
|
||||
expect(differenceSet).toEqual(referenceDifference);
|
||||
});
|
||||
|
||||
it("should return empty when subtracting from empty", () => {
|
||||
const bitset = stringBitSet.create("a", "b");
|
||||
expect(stringBitSet.difference(stringBitSet.empty, bitset)).toBe(0);
|
||||
});
|
||||
|
||||
it("should return original when subtracting empty", () => {
|
||||
const bitset = stringBitSet.create("a", "b");
|
||||
expect(stringBitSet.difference(bitset, stringBitSet.empty)).toBe(bitset);
|
||||
});
|
||||
|
||||
it("should return empty when subtracting self", () => {
|
||||
const bitset = stringBitSet.create("a", "b", "c");
|
||||
expect(stringBitSet.difference(bitset, bitset)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isDisjoint", () => {
|
||||
it("should return true for disjoint sets", () => {
|
||||
const set1 = new Set(["a", "b"]);
|
||||
const set2 = new Set(["c", "d"]);
|
||||
|
||||
const bitset1 = stringBitSet.encode(set1);
|
||||
const bitset2 = stringBitSet.encode(set2);
|
||||
|
||||
expect(stringBitSet.isDisjoint(bitset1, bitset2)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for overlapping sets", () => {
|
||||
const set1 = new Set(["a", "b", "c"]);
|
||||
const set2 = new Set(["c", "d", "e"]);
|
||||
|
||||
const bitset1 = stringBitSet.encode(set1);
|
||||
const bitset2 = stringBitSet.encode(set2);
|
||||
|
||||
expect(stringBitSet.isDisjoint(bitset1, bitset2)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return true when one or both sets are empty", () => {
|
||||
const bitset = stringBitSet.create("a", "b");
|
||||
const empty = stringBitSet.empty;
|
||||
|
||||
expect(stringBitSet.isDisjoint(empty, empty)).toBe(true);
|
||||
expect(stringBitSet.isDisjoint(bitset, empty)).toBe(true);
|
||||
expect(stringBitSet.isDisjoint(empty, bitset)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isSubset", () => {
|
||||
it("should return true for subset", () => {
|
||||
const set1 = new Set(["a", "b"]);
|
||||
const set2 = new Set(["a", "b", "c", "d"]);
|
||||
|
||||
const bitset1 = stringBitSet.encode(set1);
|
||||
const bitset2 = stringBitSet.encode(set2);
|
||||
|
||||
expect(stringBitSet.isSubset(bitset1, bitset2)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for non-subset", () => {
|
||||
const set1 = new Set(["a", "b", "e"]);
|
||||
const set2 = new Set(["a", "b", "c", "d"]);
|
||||
|
||||
const bitset1 = stringBitSet.encode(set1);
|
||||
const bitset2 = stringBitSet.encode(set2);
|
||||
|
||||
expect(stringBitSet.isSubset(bitset1, bitset2)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return true for equal sets", () => {
|
||||
const bitset = stringBitSet.create("a", "b", "c");
|
||||
expect(stringBitSet.isSubset(bitset, bitset)).toBe(true);
|
||||
});
|
||||
|
||||
it("should handle empty set as subset", () => {
|
||||
const bitset = stringBitSet.create("a", "b");
|
||||
const empty = stringBitSet.empty;
|
||||
|
||||
expect(stringBitSet.isSubset(empty, bitset)).toBe(true);
|
||||
expect(stringBitSet.isSubset(empty, empty)).toBe(true);
|
||||
expect(stringBitSet.isSubset(bitset, empty)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isSuperset", () => {
|
||||
it("should return true for superset", () => {
|
||||
const set1 = new Set(["a", "b", "c", "d"]);
|
||||
const set2 = new Set(["a", "b"]);
|
||||
|
||||
const bitset1 = stringBitSet.encode(set1);
|
||||
const bitset2 = stringBitSet.encode(set2);
|
||||
|
||||
expect(stringBitSet.isSuperset(bitset1, bitset2)).toBe(true);
|
||||
});
|
||||
|
||||
it("should return false for non-superset", () => {
|
||||
const set1 = new Set(["a", "b", "c"]);
|
||||
const set2 = new Set(["a", "b", "d"]);
|
||||
|
||||
const bitset1 = stringBitSet.encode(set1);
|
||||
const bitset2 = stringBitSet.encode(set2);
|
||||
|
||||
expect(stringBitSet.isSuperset(bitset1, bitset2)).toBe(false);
|
||||
});
|
||||
|
||||
it("should return true for equal sets", () => {
|
||||
const bitset = stringBitSet.create("a", "b", "c");
|
||||
expect(stringBitSet.isSuperset(bitset, bitset)).toBe(true);
|
||||
});
|
||||
|
||||
it("should handle empty set", () => {
|
||||
const bitset = stringBitSet.create("a", "b");
|
||||
const empty = stringBitSet.empty;
|
||||
|
||||
expect(stringBitSet.isSuperset(bitset, empty)).toBe(true);
|
||||
expect(stringBitSet.isSuperset(empty, empty)).toBe(true);
|
||||
expect(stringBitSet.isSuperset(empty, bitset)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("edge cases and performance", () => {
|
||||
it("should handle large universe efficiently", () => {
|
||||
const largeUniverse = Array.from({ length: 30 }, (_, i) => i);
|
||||
const largeBitSet = new BitSet(largeUniverse);
|
||||
|
||||
expect(largeBitSet.all).toBe(2 ** 30 - 1);
|
||||
|
||||
const set = new Set([0, 5, 10, 15, 20, 25, 29]);
|
||||
const bitset = largeBitSet.encode(set);
|
||||
expect(largeBitSet.decode(bitset)).toEqual(set);
|
||||
});
|
||||
|
||||
it("should maintain consistency across operations", () => {
|
||||
const a = stringBitSet.create("a", "b");
|
||||
const b = stringBitSet.create("b", "c");
|
||||
const c = stringBitSet.create("c", "d");
|
||||
|
||||
// (A ∪ B) ∩ C = (A ∩ C) ∪ (B ∩ C)
|
||||
const left = stringBitSet.intersection(stringBitSet.union(a, b), c);
|
||||
const right = stringBitSet.union(
|
||||
stringBitSet.intersection(a, c),
|
||||
stringBitSet.intersection(b, c),
|
||||
);
|
||||
expect(left).toBe(right);
|
||||
|
||||
// A - (B ∪ C) = (A - B) ∩ (A - C)
|
||||
const left2 = stringBitSet.difference(a, stringBitSet.union(b, c));
|
||||
const right2 = stringBitSet.intersection(
|
||||
stringBitSet.difference(a, b),
|
||||
stringBitSet.difference(a, c),
|
||||
);
|
||||
expect(left2).toBe(right2);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user