(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Equation = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o solve('2+5+6') * * @param {String} expression * The expression to create an equation for (containing variables) * @return {Function} * The function which replaces variables with values in order * and solves the expression */ equation: function equation(expression) { var stack = parseExpression(expression); var variables = []; stack.forEach(function (a) { if (typeof a === 'string' && !_.isNumber(a) && !_operators2['default'][a] && a === a.toLowerCase()) { // grouped variables like (y) need to have their parantheses removed variables.push(_.removeSymbols(a)); } }); return function () { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } expression = expression.replace(/[a-z]*/g, function (a) { var index = variables.indexOf(a); if (index > -1) { return args[index] || 0; } return a; }); return Equation.solve(expression); }; } }; var solveStack = (function (_solveStack) { function solveStack(_x) { return _solveStack.apply(this, arguments); } solveStack.toString = function () { return _solveStack.toString(); }; return solveStack; })(function (stack) { // $0(stack); if (stack.some(Array.isArray)) { stack = stack.map(function (group) { if (!Array.isArray(group)) { return group; } return solveStack(group); }); return solveStack(stack); } else { return evaluate(stack); } }); var PRECEDENCES = Object.keys(_operators2['default']).map(function (key) { return _operators2['default'][key].precedence; }); var MAX_PRECEDENCE = Math.max.apply(Math, _toConsumableArray(PRECEDENCES)); var MIN_PRECEDENCE = Math.min.apply(Math, _toConsumableArray(PRECEDENCES)); /** * Parses the given expression into an array of separated * numbers and operators/functions. * The result is passed to parseGroups * * @param {String} expression * The expression to parse * @return {Array} * The parsed array */ var parseExpression = function parseExpression(expression) { var stream = new _ReadStream2['default'](expression), stack = [], record = ''; // Create an array of separated numbers & operators while (stream.next()) { var cur = stream.current(); if (cur === ' ') { continue; } // it's probably a function with a length more than one if (!_.isNumber(cur) && !_operators2['default'][cur] && cur !== '.') { record += cur; } else if (record.length) { stack.push(record, cur); record = ''; } else if (_.isNumber(stack[stack.length - 1]) && (_.isNumber(cur) || cur === '.')) { stack[stack.length - 1] += cur; } else { stack.push(cur); } } if (record.length) { stack.push(record); } return parseGroups(stack); }; /** * Takes the parsed array from parseExpression and * groups up expressions in parantheses in deep arrays * * Example: 2+(5+4) becomes [2, [5, '+', 4]] * * @param {Array} stack * The parsed expression * @return {Array} * Grouped up expression */ var parseGroups = function parseGroups(stack) { // Parantheses become inner arrays which will then be processed first var sub = 0; return stack.reduce(function (a, b) { if (b.indexOf('(') > -1) { if (b.length > 1) { _.dive(a, sub).push(b.replace('(', ''), []); } else { _.dive(a, sub).push([]); } sub++; } else if (b === ')') { sub--; } else { _.dive(a, sub).push(b); } return a; }, []); }; /** * Gives information about an operator's format * including number of left and right arguments * * @param {String/Object} operator * The operator object or operator name (e.g. +, -) * @return {Object} * An object including the count of left and right arguments */ var formatInfo = function formatInfo(operator) { var op = typeof operator === 'string' ? _operators2['default'][operator] : operator; if (!op) { return null; } var format = op.format.split('1'), left = format[0].length, right = format[1].length; return { left: left, right: right }; }; /** * Groups up operators and their arguments based on their precedence * in deep arrays, the higher the priority, the deeper the group. * This simplifies the evaluating process, the only thing to do is to * evaluate from bottom up, evaluating deep groups first * * @param {Array} stack * The parsed and grouped expression * @return {Array} * Grouped expression based on precedences */ var sortStack = (function (_sortStack) { function sortStack(_x2) { return _sortStack.apply(this, arguments); } sortStack.toString = function () { return _sortStack.toString(); }; return sortStack; })(function (stack) { var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = stack.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var _step$value = _slicedToArray(_step.value, 2); var index = _step$value[0]; var item = _step$value[1]; if (Array.isArray(item)) { stack.splice(index, 1, sortStack(item)); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } for (var i = MIN_PRECEDENCE; i <= MAX_PRECEDENCE; i++) { for (var index = 0; index < stack.length; ++index) { var item = stack[index]; var op = _operators2['default'][item]; if (!op || op.precedence !== i) { continue; } var _formatInfo = formatInfo(op); var left = _formatInfo.left; var right = _formatInfo.right; var group = stack.splice(index - left, left + right + 1, []); stack[index - left] = group; for (var y = 0; y < i; y++) { group = [group]; } index -= right; } } return stack; }); /** * Evaluates the given math expression. * The expression is an array with an operator and arguments * * Example: evaluate([2, '+', 4]) == 6 * * @param {Array} stack * A single math expression * @return {Number} * Result of the expression */ var evaluate = function evaluate(stack) { var _operators$op; var op = findOperator(stack); if (!op) { return stack[0]; } var _formatInfo2 = formatInfo(op); var left = _formatInfo2.left; var leftArguments = stack.slice(0, left), rightArguments = stack.slice(left + 1); return (_operators$op = _operators2['default'][op]).fn.apply(_operators$op, _toConsumableArray(leftArguments).concat(_toConsumableArray(rightArguments))); }; /** * Finds the first operator in an array and returns it * * @param {Array} arr * The array to look for an operator in * @return {Object} * The operator object or null if no operator is found */ var findOperator = function findOperator(arr) { var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = arr[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var o = _step2.value; if (typeof o === 'string') { return o; } } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2['return']) { _iterator2['return'](); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return null; }; /** * Replaces constants in a string with their values * * @param {String} expression * The expression to replace constants in * @return {String} * The expression with constants replaced */ var replaceConstants = function replaceConstants(expression) { return expression.replace(/[A-Z]*/g, function (a) { var c = _constants2['default'][a]; if (!c) { return a; } return typeof c === 'function' ? c() : c; }); }; exports['default'] = Equation; module.exports = exports['default']; },{"./constats":1,"./helpers":2,"./operators":4,"./readstream":5}],4:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /* * Operators and Functions * fn: function used to evaluate value * format: the format using which arguments are parsed: * 0 indicates an argument and 1 indicates the operator * 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 */ exports['default'] = { '^': { fn: function fn(a, b) { return Math.pow(a, b); }, format: '010', precedence: 0 }, '*': { fn: function fn(a, b) { return a * b; }, format: '010', precedence: 1 }, '/': { fn: function fn(a, b) { return a / b; }, format: '010', precedence: 1 }, '%': { fn: function fn(a, b) { return a % b; }, format: '010', precedence: 1 }, '\\': { fn: function fn(a, b) { return Math.floor(a / b); }, format: '010', precedence: 1 }, '+': { fn: function fn(a, b) { return a + b; }, format: '010', precedence: 2 }, '-': { fn: function fn(a, b) { return a - b; }, format: '010', precedence: 2 }, '!': { fn: function fn(a) { var sum = 1; for (var i = 0; i < a; ++i) { sum *= i; } return sum; }, format: '01', precedence: 2 }, log: { fn: Math.log, format: '10', precedence: -1 }, ln: { fn: Math.log, format: '10', precedence: -1 }, lg: { fn: function fn(a) { return Math.log(a) / Math.log(2); }, format: '10', precedence: -1 }, sin: { fn: Math.sin, format: '10', precedence: -1 }, cos: { fn: Math.cos, format: '10', precedence: -1 }, tan: { fn: Math.tan, format: '10', precedence: -1 }, cot: { fn: Math.cot, format: '10', precedence: -1 } }; module.exports = exports['default']; },{}],5:[function(require,module,exports){ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); exports['default'] = function (string) { var i = 0, buffer = []; return { next: function next() { buffer.push(string[i]); if (i >= string.length) { return null; } return string[i++]; }, current: function current() { return string[i - 1]; }, index: function index() { return i - 1; }, to: function to(n) { var temp = ''; var dest = i + n; for (i = i; i < dest; ++i) { temp += [string[i]]; } return temp; }, drain: function drain() { return buffer.splice(0, buffer.length); }, replace: (function (_replace) { function replace(_x, _x2, _x3) { return _replace.apply(this, arguments); } replace.toString = function () { return _replace.toString(); }; return replace; })(function (start, end, replace) { var temp = string.split(''); temp.splice(start, end, replace); string = temp.join(''); i = i - (end - start); }), go: function go(n) { i += n; }, all: function all() { return string; } }; }; module.exports = exports['default']; },{}]},{},[3])(3) });