UNPKG

ultra-mega-enumerator

Version:

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

460 lines 17.4 kB
"use strict"; 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