UNPKG

ultra-mega-enumerator

Version:

Ultra Mega Enumerator is a lightweight library designed to enumerate various combinatorial objects.

229 lines 8.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Combination = void 0; const CombinationEnumeration_1 = require("./../enumerations/CombinationEnumeration"); const BitSet_1 = require("./BitSet"); const Numbers_1 = require("../Numbers"); const Utils_1 = require("../Utils"); /** * Class representing a Combination, which extends BitSet to manage combinations * of bits. It includes additional methods specific to combination logic. */ class Combination extends BitSet_1.BitSet { constructor(n) { super(n); } getN() { return this.n; } static fromBooleanArray(array) { const combination = new Combination(array.length); for (let i = 0; i < array.length; i++) { combination.set(i, array[i]); } return combination; } static createWithSizeAndSet(n, set) { // Create a boolean array of size n const booleanArray = Array.from({ length: n }, (_, index) => set.has(index)); // Use the fromBooleanArray method to create the Combination instance const combination = Combination.fromBooleanArray(booleanArray); // Return the new ImmutableCombination instance return combination; } asSequence() { const seq = []; for (let i = this.nextSetBit(0); i >= 0; i = this.nextSetBit(i + 1)) { seq.push(i); } return seq; } combinationString() { const str = Array.from(this.getTrueBits()).map((s) => s.toString()).join(" "); return str; } getIntervalVector() { return Utils_1.Utils.calcIntervalVector(this.getBitSetAsNumberArray()); } getCombinationAsArray() { const o = []; for (let i = this.nextSetBit(0); i >= 0; i = this.nextSetBit(i + 1)) { o.push(i); } return o; } // Method to find the intersection of two combinations intersect(c) { const n = Math.min(this.getN(), c.getN()); const intersectionBits = Array(n).fill(false); for (let i = 0; i < n; i++) { intersectionBits[i] = this.get(i) && c.get(i); // Bitwise AND operation } return Combination.fromBooleanArray(intersectionBits); } // Method to subtract one combination from another minus(c) { const resultBits = Array(this.getN()).fill(false); // Initialize with false const n = Math.min(this.getN(), c.getN()); for (let i = 0; i < this.getN(); i++) { resultBits[i] = this.get(i); // Start with current combination bits } // for each index, set to false if both combinations have the bit set to true for (let i = 0; i < n; i++) { if (this.get(i) && c.get(i)) { resultBits[i] = false; // Remove the bit if it exists in both } else { resultBits[i] = this.get(i); // Keep the original bit if it doesn't exist in c } } return Combination.fromBooleanArray(resultBits); } // Static method to merge two combinations static merge(a, b) { const maxN = Math.max(a.getN(), b.getN()); const mergedBits = Array(maxN).fill(false); for (let i = 0; i < a.getN(); i++) { mergedBits[i] = mergedBits[i] || a.get(i); // Bitwise OR operation } for (let i = 0; i < b.getN(); i++) { mergedBits[i] = mergedBits[i] || b.get(i); // Bitwise OR operation } return Combination.fromBooleanArray(mergedBits); } mergeWith(a) { return Combination.merge(this, a); } symmetricDifference(y) { const x = new BitSet_1.BitSet(Math.max(this.getN(), y.getN())); x.or(this); x.xor(y); return Combination.fromBooleanArray(x.getBitSetAsBooleanArray()); } // Rotate the bits in the combination rotate(t) { const result = new Combination(this.size()); for (let i = 0; i < this.size(); i++) { result.set(i, this.get((i - t + this.size()) % this.size())); } return result; } // Static method to generate a random combination of size k from n static generateRandom(n, k) { const combination = new Combination(n); let count = 0; const selectedIndices = new Set(); while (count < k) { const index = Math.floor(Math.random() * n); if (!selectedIndices.has(index)) { combination.set(index, true); selectedIndices.add(index); count++; } } return combination; } // A method to convert from a binary array to a Combination instance static combinationFromBinaryArray(bitArray) { const combination = new Combination(bitArray.length); bitArray.forEach((bit, index) => { combination.set(index, bit); }); return combination; } static combinationFromBitSet(x) { const instance = new Combination(x.size()); instance.copyFrom(x); return instance; } // Implementing the partition function that accepts a sequence partition(sequence) { const partitionArray = sequence.map(i => i); return this.partitionByIndices(partitionArray); } // Implementing the private partition function with Integer array partitionByIndices(partition) { if (partition.length !== this.cardinality()) { throw new Error("Invalid partition size compared to combination size."); } const min = Math.min(...partition); const max = Math.max(...partition); if (min !== 0 || max > this.cardinality()) { throw new Error("Invalid partition values."); } const set = []; for (let i = this.nextSetBit(0); i >= 0; i = this.nextSetBit(i + 1)) { set.push(i); } const combinations = new Array(max + 1); const bitSets = new Array(max + 1); for (let i = 0; i <= max; i++) { bitSets[i] = new BitSet_1.BitSet(this.size()); for (let j = 0; j < partition.length; j++) { if (partition[j] === i) { bitSets[i].set(set[j]); } } combinations[i] = new Combination(this.size()); combinations[i].copyFrom(bitSets[i]); // Assuming a hypothetical copyFrom method exists } return combinations; } // Method to copy from another BitSet if needed copyFrom(bitSet) { this.bits = new Set(bitSet.getTrueBits()); } copy() { const o = new Combination(this.n); o.copyFrom(this); return o; } // Equals Implementation equals(obj) { if (obj == null || !(obj instanceof Combination)) { return false; } return this.compareTo(obj) === 0; } // To String Implementation toString() { let output = ''; for (let i = this.nextSetBit(0); i >= 0; i = this.nextSetBit(i + 1)) { output += `${i}, `; } if (output.length > 0) { output = output.substring(0, output.length - 2); // Remove trailing comma } return `{${output}}`; } static generateAll(n, k) { const cnt = Numbers_1.Numbers.binomial(n, k); const combinations = new Array(cnt); const combinationEnumeration = new CombinationEnumeration_1.CombinationEnumeration(n, k); for (let i = 0; i < cnt; i++) { combinations[i] = combinationEnumeration.nextElement(); } return combinations; } // List all combinations that have 1 more element than this one static combinationRefinements(c) { const n = c.size() - c.cardinality(); if (n === 0) { return []; } const o = []; let k = 0; for (let i = 0; i < n; i++) { while (c.get(k)) { k++; } const b = new BitSet_1.BitSet(c.size()); b.or(c); b.set(k++); o.push(Combination.combinationFromBitSet(b)); } return o; } } exports.Combination = Combination; //# sourceMappingURL=Combination.js.map