ultra-mega-enumerator
Version:
Ultra Mega Enumerator is a lightweight library designed to enumerate various combinatorial objects.
313 lines • 12.5 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PCS12 = void 0;
const Utils_1 = require("../Utils");
const ForteCSV_1 = require("../ForteCSV");
const Composition_1 = require("./Composition");
const Combination_1 = require("./Combination");
const ImmutableCombination_1 = require("./ImmutableCombination");
const Necklace_1 = require("./Necklace");
class PCS12 extends ImmutableCombination_1.ImmutableCombination {
constructor(set) {
super(Combination_1.Combination.createWithSizeAndSet(12, set));
this.symmetries = null;
}
static identify(input) {
if (input.isEmpty())
return _a.empty();
if (input.getN() !== 12) {
throw new Error("PCS12::IdentifyChord the combination is not bounded by 12");
}
if (input.isEmpty()) {
return this.empty();
}
return this.ChordCombinationDict.get(input.combinationString()); // Using non-null assertion since checked earlier
}
static empty() {
return new _a(new Set());
}
getIntervals() {
return Composition_1.Composition.compositionFromCombination(this.transpose(-this.getForteNumberRotation()).combination).getCompositionAsArray();
}
static generate() {
const output = new Set();
const necklaceSet = Necklace_1.Necklace.generate(12, 2);
for (const necklace of necklaceSet) {
const period = necklace.getPeriod();
for (let j = 0; j < period; j++) {
const currentSet = new Set();
for (let k = 0; k < 12; k++) {
if (necklace[k] === 1) {
currentSet.add((12 - (k + 1) + j) % 12);
}
}
if (currentSet.size > 0) {
output.add(new _a(currentSet));
}
}
}
output.add(_a.empty());
return output;
}
getForteNumber() {
if (this.isEmpty())
return "0-1";
const o = _a.ForteNumbersDict.get(this.combinationString());
return o;
}
getMean() {
let sum = 0.0;
let count = this.getK(); // Number of set bits
for (let i = 0; i < 12; i++) {
if (this.get(i)) {
sum += i;
}
}
return count === 0 ? 0 : sum / count;
}
transpose(t) {
return _a.identify(this.rotate(t));
}
intersect(other) {
return _a.identify(super.intersect(other));
}
minus(other) {
return _a.identify(super.minus(other));
}
static getChords() {
const output = new Set();
for (let e of this.ChordCombinationDict.values()) {
output.add(e);
}
return output;
}
static fillForteNumbersDict() {
return __awaiter(this, void 0, void 0, function* () {
const forteRows = ForteCSV_1.FORTE_NUMBERS
.split("\n")
.map(l => l.split(",").map(s => s.replace(/"/g, '')));
const forteNumbersDict = new Map();
const forteNumbersRotationDict = new Map();
const forteNumbersToPCS12Dict = new Map();
const forteNumbersCommonNames = new Map();
for (let row of forteRows) {
//console.log("Processing row: " + row.toString())
const forteNumber = row[0];
const ns = (!row[1] || row[1].trim().length === 0) ? [] : row[1].split(/\s+/).map(num => Number(num));
const c = ImmutableCombination_1.ImmutableCombination.createWithSizeAndSet(12, new Set(ns));
const pcs12 = _a.identify(c);
if (pcs12.isEmpty()) {
forteNumbersDict.set(_a.empty().combinationString(), "0-1");
forteNumbersRotationDict.set(_a.empty().combinationString(), 0);
const str = "0-1.00";
forteNumbersToPCS12Dict.set(str, _a.empty());
}
else {
for (let i = 12; i >= 0; i--) {
const transposed = pcs12.transpose(i);
forteNumbersDict.set(transposed.combinationString(), forteNumber);
forteNumbersRotationDict.set(transposed.combinationString(), i);
const str = `${forteNumber}.${String(i).padStart(2, '0')}`;
forteNumbersToPCS12Dict.set(str, transposed);
}
}
}
_a.ForteNumbersDict = forteNumbersDict;
_a.ForteNumbersRotationDict = forteNumbersRotationDict;
_a.ForteNumbersToPCS12Dict = forteNumbersToPCS12Dict;
const forteNamesRows = ForteCSV_1.COMMON_NAMES
.split("\n")
.map(l => l.split(",").map(s => s.replace(/"/g, '')));
for (let row of forteNamesRows) {
const forteNumber = row[0];
const commonName = row[1];
forteNumbersCommonNames.set(forteNumber, commonName);
}
_a.ForteNumbersCommonNames = forteNumbersCommonNames;
});
}
getForteAB() {
const f = this.getForteNumber();
return f.includes("A") ? "A" : f.includes("B") ? "B" : "";
}
rotatedCompareTo(other, rotate) {
return this.combination.rotate(rotate).compareTo(other.combination.rotate(rotate));
}
static parseForte(input) {
if (!input) {
console.warn(`parseForte: Received invalid input "${input}".`);
return undefined; // Return undefined if input is invalid
}
const o = _a.ForteNumbersToPCS12Dict.get(input);
if (!o) {
console.warn(`parseForte: No PCS12 found for input "${input}".`);
}
return o;
}
combineWith(x) {
return _a.identify(this.mergeWith(x));
}
getCommonName() {
const forteNumber = this.getForteNumber();
if (forteNumber === undefined) {
return 'Unknown'; // or any other fallback string
}
return _a.ForteNumbersCommonNames.get(forteNumber);
}
getForteNumberOrder() {
let str = this.getForteNumber(); // Assumes this method is defined
str = str.replace("z", "").replace("A", "").replace("B", "").substring(str.indexOf("-") + 1);
return Number(str);
}
getForteNumberRotation() {
if (this.isEmpty())
return 0;
return _a.ForteNumbersRotationDict.get(this.combinationString());
}
toString() {
const str = `${this.getForteNumber()}.${String(this.getForteNumberRotation()).padStart(2, '0')}`;
return str;
}
getSymmetries() {
if (this.symmetries !== null)
return this.symmetries;
const o = [];
for (let i = 0; i < 24; i++) {
const axis = Math.floor(i / 2);
let found = true;
if (i % 2 === 0) {
for (let j = 0; j < 7; j++) {
if (this.get((axis + j) % 12) !== this.get((12 + axis - j) % 12)) {
found = false;
break;
}
}
}
else {
for (let j = 0; j < 6; j++) {
if (this.get((axis + j + 1) % 12) !== this.get((12 + axis - j) % 12)) {
found = false;
break;
}
}
}
if (found) {
o.push(i / 2.0);
}
}
this.symmetries = o;
return o;
}
static getForteChordDict() {
const chordDict = {};
// Assuming you want to populate it from the existing ChordDict
this.ForteNumbersToPCS12Dict.forEach((value, key) => {
chordDict[key] = value;
});
return chordDict;
}
static generateMaps() {
return __awaiter(this, void 0, void 0, function* () {
const chords = this.generate();
const chordCombinationDict = new Map();
for (const chord of chords) {
chordCombinationDict.set(chord.combinationString(), chord);
}
_a.ChordCombinationDict = chordCombinationDict;
yield this.fillForteNumbersDict(); // Load forte numbers after generating chords
});
}
calcCenterTuning(center) {
let o = 1.0;
const s = this.asSequence();
const m = new Map();
// Populate the map for center tuning with the values
for (let i = -5; i < 7; i++) {
m.set((center + i + 12) % 12, Math.pow(2.0, (i / 12.0)));
}
// Calculate product based on the sequence
for (const t of s) {
o *= m.get(t);
}
return Math.pow(o, 1.0 / s.length);
}
getTensionPartition() {
const ct = this.asSequence().map((n) => this.calcCenterTuning(n));
// Get unique |1.0 - d| values, sorted
const values = Array.from(new Set(ct.map(d => Math.abs(1.0 - d)))).sort((a, b) => a - b);
// Map each unique value to an index
const map = new Map();
values.forEach((d, i) => map.set(d, i));
// Build the output sequence
return ct.map(d => map.get(Math.abs(1.0 - d)));
}
static init() {
return __awaiter(this, void 0, void 0, function* () {
if (this._isInitialized) {
//console.log("PCS12 is already initialized.");
return;
}
if (this._isInitializing) {
//console.log("PCS12 is initializing.");
return;
}
this._isInitializing = true;
//console.log("Initializing PCS12...");
yield _a.generateMaps();
//console.log("PCS12 initialized successfully.");
this._isInitialized = true;
this._isInitializing = false;
});
}
static isInitialized() {
return this._isInitialized;
}
}
exports.PCS12 = PCS12;
_a = PCS12;
PCS12.ChordCombinationDict = new Map();
PCS12.ForteNumbersDict = new Map();
PCS12.ForteNumbersRotationDict = new Map();
PCS12.ForteNumbersToPCS12Dict = new Map();
PCS12.ForteNumbersCommonNames = new Map();
PCS12.ForteStringComparator = (o1, o2) => {
// Add null/undefined checks before proceeding
if (!o1 || !o2) {
console.error(`ForteStringComparator: Invalid input - o1: "${o1}", o2: "${o2}".`);
return 0; // Or handle it according to your logic, for instance, you could always treat undefined as less than defined
}
const p1 = _a.parseForte(o1);
const p2 = _a.parseForte(o2);
// Handle undefined cases gracefully
if (!p1 && !p2)
return 0; // Both are undefined, treat as equal
if (!p1)
return -1; // p1 is undefined, consider p2 greater
if (!p2)
return 1; // p2 is undefined, consider p1 greater
return Utils_1.CustomComparisonChain.start()
.setValues(p1, p2)
.compare((x, y) => Utils_1.Ordering.natural().getComparator()(x.getK(), y.getK()))
.compare((x, y) => Utils_1.Ordering.natural().getComparator()(x.getForteNumberOrder(), y.getForteNumberOrder()))
.compare((x, y) => {
const a = x.getForteAB();
const b = y.getForteAB();
return Utils_1.Ordering.natural().nullsFirst().getComparator()(a, b);
})
.compare((x, y) => Utils_1.Ordering.natural().getComparator()(x.getForteNumberRotation(), y.getForteNumberRotation()))
.result();
};
PCS12.ReverseForteStringComparator = (o1, o2) => _a.ForteStringComparator(o2, o1);
PCS12._isInitializing = false;
PCS12._isInitialized = false;
//# sourceMappingURL=PCS12.js.map