-3

I am developing a Calculator in JavaScript. Using the Regular Expressions and the formula below:

8.77 + $59.09 + 8   7.6 - ((1)) + 7e-2 + 4.9e11 + cos((pi/3) + 1) + cos(((6+3)) + 1) +1.12e+12 * x_variable + e - sin(((pi/4))) / tan(4)

how can I return the following array? If not possible with the use of RegEx, then with any other good strategies to achieve this?

['8.77', '$', '59.09', '87.6', '1', '7e-2', '4.9e11', 'cos', 'pi/3', '1', 'cos', '6+3', '1', '1.12e+12', 'x_variable', 'e', 'sin', 'pi/4', 'tan', '4']

I will also be happy with this result as well:

['8.77', '$', '59.09', '87.6', '1', '7e-2', '4.9e11', 'cos', 'pi', '3', '1', 'cos', '6', '3', '1', '1.12e+12', 'x_variable', 'e', 'sin', 'pi', '4', 'tan', '4']

Please note that the value of the standalone "e" is 2.7182818285, and "1.12e+12" is just an exponential number which contains "e" character, and "e" is at the end of "x_variable" string as well. Also, there are spaces in "8 7.6".

Sonny K
  • 63
  • 8
  • Don't you also need the operators so you can know what to do with the numbers? – Buddy Sep 08 '15 at 23:13
  • 1
    Regex probably isn't the best way to do this. A parser might be more in line with what you'd want to create. – arcyqwerty Sep 08 '15 at 23:15
  • 2
    Regex isn't the right tool for this. You'll have to use a parser, tokenize, generate an AST, evaluate according to mathematical rules like precedence etc. Same reason [why you can't parse HTML with regex](http://stackoverflow.com/q/1732348/575527). There are a lot of examples on this topic online. It even shows up when talking about data structures, real-world applications of binary trees. – Joseph Sep 08 '15 at 23:19
  • At this time, I really don't need the operators back. I wrote a parser in my Calculator app, but its not a good one; this is why I am reaching out for help. Does anyone know of any good open-source parser on the GitHub to help me with this? – Sonny K Sep 08 '15 at 23:35

1 Answers1

1

As remarked in comment above, you really shouldn't do this.

But just for the fun of it...

Array.prototype.concat.apply(
  [],
  '8.77 + $59.09 + 8   7.6 - ((1)) + 7e-2 + 4.9e11 + cos((pi/3) + 1) + cos(((6+3)) + 1) +1.12e+12 * x_variable + e - sin(((pi/4))) / tan(4)'
    .replace(/[\s()]/g, '')
    .replace(/([-+*\/])/g, ' $1 ')
    .replace(/(\d+e) (([-|+]) )?(\d+)/g, '$1$3$4')
    .split(/(sin|cos|tan|\$)/g)
    .map(function(e) {
      return e.split(/ /g);
    })
)
.filter(function(e) {
  return e.match(/./g) && !e.match(/^[-+*/]$/g);
})

yields you the second result.

Handling solve, as per comments below:

Array.prototype.concat.apply(
  [],
  '8.77 + $59.09 + 8 7.6 - ((1)) + 7e-2 + 4.9e11 + cos((pi/3) + 1) + cos(((6+3)) + 1) +1.12e+12 * x_variable + e - sin(((pi/4))) / tan(4) + ncr(2;y_variable) + solve("2(a-2)+3a+3=13"; "a"; 1; 5)'
    .replace(/[\s]/g, '')
    .replace(/([-+*\/;])/g, ' $1 ')
    .replace(/(\d+e) (([-|+]) )?(\d+)/g, '$1$3$4')
    .replace(/solve\("([^"]*)"\s*;\s*"(.)"/g, function(m) { return m.replace(/\s/g, '').replace(/solve\("(.*)"\s*;\s*"(.)"/g, 'solve $1 $2'); })
    .replace(/[()]/g, '')
    .split(/(sin|cos|tan|\$|ncr)/g)
    .map(function(e) {
      return e.split(/ /g);
    })
)
.filter(function(e) {
  return e.match(/./g) && !e.match(/^[-+*/;]$/g);
})

which yields

["8.77", "$", "59.09", "87.6", "1", "7e-2", "4.9e11", "cos", "pi", "3", "1", "cos", "6", "3", "1", "1.12e+12", "x_variable", "e", "sin", "pi", "4", "tan", "4", "ncr", "2", "y_variable", "solve", "2a-2+3a+3=13", "a", "1", "5"]
arcyqwerty
  • 10,325
  • 4
  • 47
  • 84
  • Yes, there's simpler ways. I'm shooting for regexes everywhere, even where a simpler solution exists. – arcyqwerty Sep 08 '15 at 23:44
  • The code snippet you added worked like a charm! thank you – Sonny K Sep 09 '15 at 18:12
  • Is there a way to extend upon your code snippet to handle the below formula? 8.77 + $59.09 + 8 7.6 - ((1)) + 7e-2 + 4.9e11 + cos((pi/3) + 1) + cos(((6+3)) + 1) +1.12e+12 * x_variable + e - sin(((pi/4))) / tan(4) + ncr(2;3) + solve("2(a-2)+3a+3=13"; "a"; 1; 5) – Sonny K Sep 09 '15 at 19:44
  • What's the expected output? Once again, I don't recommend using the regex approach and what I've written already is untested and probably full of bugs and corner cases. – arcyqwerty Sep 09 '15 at 20:11
  • New Formula: 8.77 + $59.09 + 8 7.6 - ((1)) + 7e-2 + 4.9e11 + cos((pi/3) + 1) + cos(((6+3)) + 1) +1.12e+12 * x_variable + e - sin(((pi/4))) / tan(4) + ncr(2;y_variable) + solve("2(a-2)+3a+3=13"; "a"; 1; 5) Result = ['8.77', '$', '59.09', '87.6', '1', '7e-2', '4.9e11', 'cos', 'pi', '3', '1', 'cos', '6', '3', '1', '1.12e+12', 'x_variable', 'e', 'sin', 'pi', '4', 'tan', '4', 'ncr', '2', 'y_variable', 'solve("2(a-2)+3a+3=13"; "a"; 1; 5)'] – Sonny K Sep 09 '15 at 20:36
  • Actually what you wrote worked out great for me. I've tested it against all possible formula test I had. The only issue that i have right now is the Solve() function in formula strings. It would be great just get the entire Solve() functions back in seperate array cells. – Sonny K Sep 09 '15 at 21:03
  • The `solve()` case is a bit tricky strictly using regexes since JS regexes don't support recursion (for matching parens). That task, however, could be done pretty easily (as could most of this problem) without regexes. – arcyqwerty Sep 09 '15 at 21:38
  • I could pretty reasonably get you `[solve, "2(a-2)+3a+3=13", a, 1, 5]` using regexes. The problem with parens is that your inner expressions can have them and there's no regex-y way to match them – arcyqwerty Sep 09 '15 at 21:42
  • Is there a way to use a separate RegEx to only extract way all the Solve() functions (Ques1) prior to executing the code snippet you provided above? If yes, also is there a way to use another RegEx to just return a list of only all Solve() funcs prior to striping them away in my Ques1 question? For example: [ 'solve("2(a-2)+3a+3=13"; "a"; 1; 5)', 'solve("x^2-6x+5=0"; "x")' ]. – Sonny K Sep 09 '15 at 21:46
  • Once again, it's tough to do with regexes since there's no support for recursion for matching the parens. It's easily possible to extract the `Solve()` functions, just not with [js] regexes. – arcyqwerty Sep 09 '15 at 22:39
  • I wish JS was more powerful to do this. With your help, I am now light years ahead of what I had originally written. In one of your earlier comments, you mentioned that you could extend the original code snippet to also output the result of ['solve', '2(a-2)+3a+3=13', 'a', '1', '5']. I tried to modify your code to do this, but I had no luck. When you have a free moment, would you provide me with this code extension to get this result? Thanks – Sonny K Sep 10 '15 at 02:39
  • Running to another issue with a simpler math expression; using this expression: -1+(-2.3+5.01) + (-0.32*444). how to return ['-1', '+', '(', '-2.3', '+', '5.01', ')', '+', '(', '-0.32', '*', '444, ')'] back? I used JS code formula.match(/[^\d]+|[\d.]+/g) and its failing for me. – Sonny K Oct 05 '15 at 03:16