ultra-mega-enumerator
Version:
Ultra Mega Enumerator is a lightweight library designed to enumerate various combinatorial objects.
460 lines • 17.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Sequence = exports.Combiner = exports.Operation = void 0;
const Numbers_1 = require("../Numbers");
// Define Operation Enum
var Operation;
(function (Operation) {
Operation["Add"] = "Add";
Operation["Subtract"] = "Subtract";
Operation["Multiply"] = "Multiply";
Operation["Divide"] = "Divide";
Operation["X"] = "X";
Operation["Y"] = "Y";
Operation["Power"] = "Power";
Operation["Log"] = "Log";
Operation["Min"] = "Min";
Operation["Max"] = "Max";
Operation["MaxZeroX"] = "MaxZeroX";
Operation["MinZeroX"] = "MinZeroX";
Operation["MaxZeroY"] = "MaxZeroY";
Operation["MinZeroY"] = "MinZeroY";
Operation["Modulo"] = "Modulo";
Operation["Bounce"] = "Bounce";
Operation["And"] = "And";
//Nand = 'Nand',
Operation["Or"] = "Or";
//Nor = 'Nor',
//Implication = 'Implication',
//ReverseImplication = 'ReverseImplication',
Operation["Xor"] = "Xor";
//Xnor = 'Xnor',
Operation["ShiftLeft"] = "ShiftLeft";
Operation["ShiftRight"] = "ShiftRight";
Operation["LCM"] = "LCM";
Operation["GCD"] = "GCD";
Operation["Equal"] = "Equal";
Operation["NotEqual"] = "NotEqual";
Operation["LessThan"] = "LessThan";
Operation["LessThanOrEqual"] = "LessThanOrEqual";
Operation["GreaterThan"] = "GreaterThan";
Operation["GreaterThanOrEqual"] = "GreaterThanOrEqual";
Operation["Binomial"] = "Binomial";
Operation["ExpandBits"] = "ExpandBits";
Operation["ExpandBitsFill"] = "ExpandBitsFill";
Operation["CantorIntervalBinaryNumber"] = "CantorIntervalBinaryNumber";
Operation["PermuteBits"] = "PermuteBits";
Operation["HardThreshold"] = "HardThreshold";
})(Operation || (exports.Operation = Operation = {}));
// Define Combiner Enum
var Combiner;
(function (Combiner) {
Combiner["Product"] = "Product";
Combiner["NegativeProduct"] = "NegativeProduct";
Combiner["Convolution"] = "Convolution";
Combiner["Triangular"] = "Triangular";
Combiner["Recycle"] = "Recycle";
Combiner["LCM"] = "LCM";
Combiner["Apply"] = "Apply";
Combiner["Reduce"] = "Reduce";
Combiner["MixedRadix"] = "Mixed Radix";
Combiner["Bits"] = "Bits";
Combiner["Trits"] = "Trits";
})(Combiner || (exports.Combiner = Combiner = {}));
const ops = new Map([
[Operation.Add, (x, y) => x + y],
[Operation.Subtract, (x, y) => x - y],
[Operation.Multiply, (x, y) => x * y],
[Operation.Divide, (x, y) => y !== 0 ? Math.floor(x / y) : 0],
[Operation.X, (x, y) => x],
[Operation.Y, (x, y) => y],
[Operation.Power, (x, y) => Math.round(Math.pow(x, y))],
[Operation.Log, (x, y) => y > 1 && x > 0 ? Math.floor(Math.log(x) / Math.log(y)) : 0],
[Operation.Min, (x, y) => Math.min(x, y)],
[Operation.Max, (x, y) => Math.max(x, y)],
[Operation.Modulo, (x, y) => y !== 0 ? x % y : 0],
[Operation.Bounce, (x, y) => {
if (y === 0)
return 0;
const mod = x % (2 * y);
return mod <= y ? mod : 2 * y - mod;
}],
[Operation.And, (x, y) => x & y],
//[Operation.Nand, (x, y) => ~(x & y)],
[Operation.Or, (x, y) => x | y],
//[Operation.Nor, (x, y) => ~(x | y)],
//[Operation.Implication, (x, y) => (~x) | y],
//[Operation.ReverseImplication, (x, y) => (~y) | x],
[Operation.Xor, (x, y) => x ^ y],
//[Operation.Xnor, (x, y) => ~(x ^ y)],
[Operation.ShiftLeft, (x, y) => x << y],
[Operation.ShiftRight, (x, y) => x >> y],
[Operation.LCM, (x, y) => Numbers_1.Numbers.lcm(x, y)],
[Operation.GCD, (x, y) => Numbers_1.Numbers.gcd(x, y)],
[Operation.Equal, (x, y) => (x === y ? 1 : 0)],
[Operation.NotEqual, (x, y) => (x !== y ? 1 : 0)],
[Operation.LessThan, (x, y) => (x < y ? 1 : 0)],
[Operation.LessThanOrEqual, (x, y) => (x <= y ? 1 : 0)],
[Operation.GreaterThan, (x, y) => (x > y ? 1 : 0)],
[Operation.GreaterThanOrEqual, (x, y) => (x >= y ? 1 : 0)],
[Operation.Binomial, (x, y) => Numbers_1.Numbers.binomial(x, y)],
[Operation.ExpandBits, (x, y) => Numbers_1.Numbers.expandBits(x, y, '0')],
[Operation.ExpandBitsFill, (x, y) => Numbers_1.Numbers.expandBits(x, y, 'bit')],
[Operation.CantorIntervalBinaryNumber, (x, y) => Numbers_1.Numbers.CantorIntervalBinaryNumber(x, y)],
[Operation.PermuteBits, (x, y) => Numbers_1.Numbers.permuteBits(x, y)],
[Operation.MaxZeroX, (x, y) => Math.max(0, x)],
[Operation.MinZeroX, (x, y) => Math.min(0, x)],
[Operation.MaxZeroY, (x, y) => Math.max(0, y)],
[Operation.MinZeroY, (x, y) => Math.min(0, y)],
[Operation.HardThreshold, (x, y) => Math.abs(x) > Math.abs(y) ? 0 : x],
]);
class Sequence {
constructor(...items) {
this.items = items !== null && items !== void 0 ? items : [];
}
toString() {
return this.toArray().join(' ');
}
add(item) {
this.items.push(item);
}
size() {
return this.items.length;
}
get(index) {
return this.items[index];
}
set(index, value) {
this.items[index] = value;
}
toArray() {
return this.items;
}
// New signs method
signs() {
const signArray = this.items.map(item => {
if (item > 0)
return 1;
else if (item < 0)
return -1;
return 0;
});
return new Sequence(...signArray); // Create a new Sequence with sign values
}
isNatural() {
return this.items.every(n => n >= 0);
}
difference() {
if (this.size() < 2) {
throw new Error("Difference requires at least two elements.");
}
const output = this.items.slice(1).map((item, index) => item - this.items[index]);
return new Sequence(...output);
}
cyclicalDifference() {
if (this.size() == 0) {
return new Sequence();
}
if (this.size() == 1) {
return new Sequence(...[0]);
}
const output = this.items.map((item, index) => {
return this.items[(index + 1) % this.size()] - item;
});
return new Sequence(...output);
}
antidifference(k) {
const output = new Array(this.size() + 1);
output[0] = k;
for (let i = 0; i < this.size(); i++) {
output[i + 1] = output[i] + this.items[i];
}
return new Sequence(...output);
}
cyclicalAntidifference(k) {
const output = new Array(this.size());
output[this.size() - 1] = k;
for (let i = 0; i < this.size(); i++) {
output[i] = output[(i - 1 + this.size()) % this.size()] + this.items[(i - 1 + this.size()) % this.size()];
}
return new Sequence(...output);
}
getSymmetries() {
const symmetries = [];
const n = this.size();
for (let i = 0; i < n * 2; i++) {
let axis = Math.floor(i / 2);
let found = true;
if (i % 2 === 0) {
for (let j = 0; j < 1 + Math.floor(n / 2); j++) {
if (this.get((axis + j) % n) !== this.get((n + axis - j) % n)) {
found = false;
break;
}
}
}
else {
for (let j = 0; j < 1 + Math.floor(n / 2); j++) {
if (this.get((axis + j + 1) % n) !== this.get((n + axis - j) % n)) {
found = false;
break;
}
}
}
if (found) {
symmetries.push(i / 2);
}
}
return symmetries;
}
static parse(s) {
const output = new Sequence();
const trimmed = s.trim().replace(/[,]/g, "");
let str0 = trimmed.startsWith('[') && trimmed.endsWith(']')
? trimmed.substring(1, trimmed.length - 1)
: trimmed;
const ss = str0.split(/\s+/);
for (const i of ss) {
if (i.trim() !== '') {
output.add(parseInt(i.trim()));
}
}
return output;
}
getMean() {
return this.sum() / this.size();
}
sum() {
return this.items.reduce((a, b) => a + b, 0);
}
getMin() {
return Math.min(...this.items);
}
getMax() {
return Math.max(...this.items);
}
rotate(n) {
const rotatedItems = [...this.items.slice(-n), ...this.items.slice(0, -n)];
const resultSeq = new Sequence();
for (const item of rotatedItems) {
resultSeq.add(item);
}
return resultSeq;
}
static fromArray(arr) {
const seq = new Sequence();
for (const item of arr) {
seq.add(item);
}
return seq;
}
// Frequency map
frequencyMap() {
const freqMap = new Map();
for (const item of this.items) {
freqMap.set(item, (freqMap.get(item) || 0) + 1);
}
return freqMap;
}
static genRnd(length, amp, sum, maxAmp, exclude0) {
if (length <= 1 || amp < 1 || maxAmp < 2 || (exclude0 && maxAmp < 2) ||
(Math.abs(sum) >= maxAmp)) {
throw new Error("Invalid parameters for random sequence generation.");
}
const sequence = new Sequence();
let currVal = sum;
sequence.add(currVal);
const possibleValues = [];
while (sequence.size() < length) {
possibleValues.length = 0;
for (let i = -amp; i <= amp; i++) {
if (Math.abs(currVal + i) < maxAmp && (i !== 0 || !exclude0)) {
possibleValues.push(i);
}
}
if (possibleValues.length === 0)
break;
const randomIndex = Math.floor(Math.random() * possibleValues.length);
currVal += possibleValues[randomIndex];
sequence.add(currVal);
}
return sequence;
}
// Calculate interval vector for a specific condition
static calculateIntervalVector(n, conditionFn) {
const m = Math.floor(n / 2);
const result = new Sequence();
for (let i = 1; i <= m; i++) {
let count = 0;
for (let j = 0; j < n; j++) {
if (conditionFn(j) && conditionFn((i + j) % n)) {
count++;
}
}
if (i === m && n % 2 === 0) {
count = Math.floor(count / 2);
}
result.add(count);
}
return result;
}
// Calculate interval vector for a boolean array
static calcIntervalVector(input) {
const n = input.length;
return this.calculateIntervalVector(n, (j) => input[j]);
}
// Calculate interval vector for a BitSet (presented as an array as TypeScript doesn't have BitSet)
static calcIntervalVectorBitSet(input, n) {
return this.calculateIntervalVector(n, (j) => input[j]);
}
// For distinct values in a sequence input
static calcIntervalVectorDistinct(sequence) {
const output = new Map();
const distinctValues = new Set(sequence.toArray());
for (const value of distinctValues) {
const booleanArray = sequence.toArray().map(item => item === value);
const intervalVector = this.calcIntervalVector(booleanArray);
output.set(value, intervalVector);
}
return output;
}
// Alternative overload to handle Integer[] while avoiding code duplication
static calcIntervalVectorInts(input) {
const sequence = new Sequence(...input);
return this.calcIntervalVectorDistinct(sequence);
}
static combine(combiner, operation, x, y) {
const o = new Sequence();
const operationFn = ops.get(operation);
const lcm = Numbers_1.Numbers.lcm(x.size(), y.size());
switch (combiner) {
case Combiner.Apply:
for (let i = 0; i < y.size(); i++) {
if (operationFn) {
o.add(operationFn(x.get(y.get(i) % x.size()), y.get(i % y.size())));
}
}
break;
case Combiner.LCM:
for (let i = 0; i < lcm; i++) {
if (operationFn) {
o.add(operationFn(x.get(i / (lcm / x.size()) >> 0), y.get(i / (lcm / y.size()) >> 0)));
}
}
break;
case Combiner.Recycle:
for (let i = 0; i < lcm; i++) {
if (operationFn) {
o.add(operationFn(x.get(i % x.size()), y.get(i % y.size())));
}
}
break;
case Combiner.Product:
for (let i = 0; i < x.size(); i++) {
for (let j = 0; j < y.size(); j++) {
if (operationFn) {
o.add(operationFn(x.get(i), y.get(j)));
}
}
}
break;
case Combiner.NegativeProduct:
for (let z = 0; z < 2; z++) {
for (let i = 0; i < x.size(); i++) {
for (let j = 0; j < y.size(); j++) {
if (z == 0)
o.add(0);
else if (operationFn) {
o.set((((i * y.size()) - (y.size() - 1) + j) + o.size()) % o.size(), operationFn(x.get(i), y.get(j)));
}
}
}
}
break;
case Combiner.Convolution:
for (let i = 0; i < x.size(); i++)
o.add(0);
for (let i = 0; i < o.size(); i++) {
for (let j = 0; j < y.size(); j++) {
if (operationFn) {
let v = operationFn(x.get(i), y.get(j));
o.set((i + j) % o.size(), o.get((i + j) % o.size()) + v);
}
}
}
break;
case Combiner.Triangular:
for (let i = 0; i < x.size(); i++) {
for (let j = 0; j < y.size(); j++) {
if (j <= i && operationFn) {
o.add(operationFn(x.get(i), y.get(j)));
}
}
}
break;
case Combiner.Reduce:
for (let i = 0; i < x.size(); i++) {
if (operationFn) {
o.add(y.toArray().reduce((a, b) => operationFn(a, b), x.get(i)));
}
}
break;
case Combiner.MixedRadix:
// This array will collect each combination (each row is an array of digits)
const result = [];
// Initialize the current combination with zeros
const current = new Array(x.size()).fill(0);
while (true) {
result.push([...current]);
if (current.every((value, i) => Math.abs(value) === Math.abs(x.get(i)) - 1)) {
break;
}
for (let i = 0; i < x.size(); i++) {
if (x.get(i) === 0)
break;
if (Math.abs(current[i]) < Math.abs(x.get(i)) - 1) {
if (x.get(i) < 0)
current[i]--;
if (x.get(i) > 0)
current[i]++;
break;
}
else {
current[i] = 0;
}
}
}
if (operationFn) {
const combined = result.map(row => row.map((value, index) => operationFn(value, y.get(index % y.size()))).reduce((a, b) => a + b, 0));
for (let z of combined)
o.add(z);
}
break;
case Combiner.Bits:
for (let i = 0; i < x.size(); i++) {
let b = Numbers_1.Numbers.toBinary(x.get(i), y.get(i % y.size()));
for (let j = 0; j < b.length; j++) {
if (operationFn) {
o.add(operationFn(b[j], Math.pow(2, y.get(i % y.size()) < 0 ? j : b.length - 1 - j)));
}
}
}
break;
case Combiner.Trits:
for (let i = 0; i < x.size(); i++) {
let b = Numbers_1.Numbers.toBalancedTernary(x.get(i), y.get(i % y.size()));
for (let j = 0; j < b.length; j++) {
if (operationFn) {
o.add(operationFn(b[j], Math.pow(3, y.get(i) < 0 ? j : b.length - 1 - j)));
}
}
}
break;
}
return o;
}
;
}
exports.Sequence = Sequence;
;
//# sourceMappingURL=Sequence.js.map