moment-of-symmetry
Version:
Moment of Symmetry (MOS) musical scale generation and analysis for Javascript
94 lines • 3.35 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.bjorklundStr = exports.bjorklund = void 0;
/**
* Implementation of Bjorklund's algorithm for generating even distributions
*/
const xen_dev_utils_1 = require("xen-dev-utils");
/**
* Generate an array of evenly distributed booleans using Bjorklund's algorithm
* @param numberOfTrue Number of true elements
* @param numberOfFalse Number of false elements
* @param trueValue Value to use for true elements
* @param falseValue Value to use for false elements
* @returns Array of evenly distributed values
*/
function bjorklund(numberOfTrue, numberOfFalse, trueValue, falseValue) {
if (numberOfTrue < 0 || numberOfFalse < 0) {
throw new Error('Number of elements must be non-negative');
}
if (numberOfTrue === 0) {
return Array(numberOfFalse).fill(falseValue);
}
if (numberOfFalse === 0) {
return Array(numberOfTrue).fill(trueValue);
}
const d = (0, xen_dev_utils_1.gcd)(numberOfTrue, numberOfFalse);
if (d === 1) {
let [countFirst, countSecond] = [numberOfTrue, numberOfFalse];
let first = trueValue;
let second = falseValue;
const result = [];
while (countSecond !== 1) {
if (countFirst > countSecond) {
[countFirst, countSecond] = [countSecond, countFirst - countSecond];
[first, second] = [first, second];
}
else {
countSecond = countSecond - countFirst;
[first, second] = [second, first];
}
}
for (let i = 0; i < countFirst; i++) {
result.push(first);
}
result.push(second);
return result;
}
else {
// multiperiod MOS
return Array(d)
.fill(bjorklund(numberOfTrue / d, numberOfFalse / d, trueValue, falseValue))
.flat();
}
}
exports.bjorklund = bjorklund;
/**
* Generate a string of evenly distributed 'L' and 's' characters using Bjorklund's algorithm
* @param numberOfLarge Number of large steps
* @param numberOfSmall Number of small steps
* @returns String of evenly distributed 'L' and 's' characters
*/
function bjorklundStr(numberOfLarge, numberOfSmall) {
if (isNaN(numberOfLarge) || isNaN(numberOfSmall)) {
throw new Error('Invalid input');
}
const d = (0, xen_dev_utils_1.gcd)(numberOfLarge, numberOfSmall);
if (d === 1) {
let [countFirst, countSecond] = [numberOfLarge, numberOfSmall];
let first = 'L';
let second = 's';
const result = [];
while (countSecond !== 1) {
if (countFirst > countSecond) {
[countFirst, countSecond] = [countSecond, countFirst - countSecond];
[first, second] = [first, second];
}
else {
countSecond = countSecond - countFirst;
[first, second] = [second, first];
}
}
for (let i = 0; i < countFirst; i++) {
result.push(first);
}
result.push(second);
return result.join('');
}
else {
// multiperiod MOS
return bjorklundStr(numberOfLarge / d, numberOfSmall / d).repeat(d);
}
}
exports.bjorklundStr = bjorklundStr;
//# sourceMappingURL=bjorklund.js.map