UNPKG

moment-of-symmetry

Version:

Moment of Symmetry (MOS) musical scale generation and analysis for Javascript

94 lines 3.35 kB
"use strict"; 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