Added Sigma operator – support for more complex operators 🌟

Fix README.md links pointing to Equation.js instead of Equation
Bump version to 1.3.0
This commit is contained in:
Mahdi Dibaiee
2015-06-21 23:32:12 +04:30
parent 6a5120ec22
commit 485ebb3c9d
10 changed files with 219 additions and 31 deletions

View File

@ -80,6 +80,13 @@ let Equation = {
};
},
// 2x + 5x * x => 7x^2
simplify(expression) {
let stack = parseExpression(expression);
console.log(stack);
},
registerOperator(key, options) {
operators[key] = options;
},
@ -90,7 +97,13 @@ let Equation = {
};
const solveStack = stack => {
if (stack.some(Array.isArray)) {
// if an operator takes an expression argument, we should not dive into it
// and solve the expression inside
const hasExpressionArgument = stack.some(a => {
return operators[a] && operators[a].hasExpression;
});
if (!hasExpressionArgument && stack.some(Array.isArray)) {
stack = stack.map(group => {
if (!Array.isArray(group)) {
return group;
@ -122,6 +135,12 @@ const MIN_PRECEDENCE = Math.min(...PRECEDENCES);
* The parsed array
*/
const parseExpression = expression => {
// function arguments can be separated using comma,
// but we parse as groups, so this is the solution to getting comma to work
// sigma(0, 4, 2@) becomes sigma(0)(4)(2@) so every argument is parsed
// separately
expression = expression.replace(/,/g, ')(');
let stream = new ReadStream(expression),
stack = [],
record = '',
@ -202,19 +221,19 @@ const parseExpression = expression => {
*/
const parseGroups = stack => {
// Parantheses become inner arrays which will then be processed first
let sub = 0;
let depth = 0;
return stack.reduce((a, b) => {
if (b.indexOf('(') > -1) {
if (b.length > 1) {
_.dive(a, sub).push(b.replace('(', ''), []);
_.dive(a, depth).push(b.replace('(', ''), []);
} else {
_.dive(a, sub).push([]);
_.dive(a, depth).push([]);
}
sub++;
depth++;
} else if (b === ')') {
sub--;
depth--;
} else {
_.dive(a, sub).push(b);
_.dive(a, depth).push(b);
}
return a;
}, []);

View File

@ -1,3 +1,5 @@
import Equation from 'equation';
/*
* Operators and Functions
* fn: function used to evaluate value
@ -6,6 +8,11 @@
* e.g: factorial is 01, add is 010, like 2!, 2+2
* precedence: determines which operators should be evaluated first
* the lower the value, the higher the precedence
* hasExpression: determines if any of the operator arguments are an expression
* This way, arguments will not be solved by equation and instead
* you have to call solve on each argument yourself.
* You get the arguments as parsed arrays sigma(0, 5, 2@) becomes
* sigma(0, 5, [2, '*', '@']). See sigma operator for reference
*/
export default {
'^': {
@ -98,5 +105,22 @@ export default {
fn: Math.floor,
format: '10',
precedence: -1
},
'sigma': {
fn(from, to, expression) {
const expr = expression.join('').replace(/,/g, '');
const regex = new RegExp(ITERATOR_SIGN, 'g');
let sum = 0;
for (let i = from; i <= to; i++) {
sum += Equation.solve(expr.replace(regex, i));
}
return sum;
},
format: '1000',
hasExpression: true,
precedence: -1
}
};
const ITERATOR_SIGN = '@';