ultra-mega-enumerator
Version:
Ultra Mega Enumerator is a lightweight library designed to enumerate various combinatorial objects.
229 lines • 8.29 kB
JavaScript
"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