3
\$\begingroup\$

String is given in form of a variable. Let's call that variable s. It is known that the string looks like a calculation expression using +, -, *, /. There's no parentheses.

Calculate the expression inside the string and store the result in variable r (you can assume it's already declared). All the divisions can be performed without remainders (4-6*3/8 is invalid because 8 is not divisible by 3). Length of string is not limited. String can't contain 0.

Challenge is not supposed to give advantage for some languages, so I decided to change some math rules:

Operators precedence is a little bit different than it is in math and programming language expressions: multiplication/division is still higher than addition/substraction. However, if there're some multiplications/divisions in a row, it is performed right-to-left. Addition/substraction is preformed left-to-right.

Sample s and r:

2+5-6/9*8+7 -> 2

1/3*6-6 -> 12

The shortest code (in bytes) wins.

\$\endgroup\$
  • \$\begingroup\$ You know, you can also just say don't use any eval equivalents. \$\endgroup\$ – marinus Jan 6 '14 at 0:02
  • 3
    \$\begingroup\$ Nice point. But new math rules sound like more fun ;) \$\endgroup\$ – gthacoder Jan 6 '14 at 0:03
  • 2
    \$\begingroup\$ You're also not really supposed to change the question after you post it, because you could invalidate previously posted answers. In this case it doesn't matter, but to iron out any mistakes/gotchas, you can post your question in the sandbox (on meta) first to discuss it. \$\endgroup\$ – marinus Jan 6 '14 at 0:08
  • \$\begingroup\$ Yeah, I know. I was thinking not much people viewed the question text at that point, so I could change it a little bit. "In runtime." Sorry. \$\endgroup\$ – gthacoder Jan 6 '14 at 0:12
  • \$\begingroup\$ @gthacoder Only me and marinus :) I've added on a solution that meets all the new requirements. \$\endgroup\$ – Timtech Jan 6 '14 at 0:13
2
\$\begingroup\$

Perl 5, 27 20

s/(.)\//1\/$1*/g;print eval

Edit:

s/\//**-1*/g;$r=eval

Assuming the input of:

$_ = "2+5-6/9*8+7";
> $r = 2

and

$_ = "1/3*6-6";
> $r = 12

This regex is based in the mathematical theory of @ybeltukov, I'm new to regex so it probably could be much better.

\$\endgroup\$
6
\$\begingroup\$

Mathematica (41)

s = "2+5-6/9*8+7";
ToExpression@StringReplace[s,"/"->"^-1 "]

2

Correct me if I'm wrong

\$\endgroup\$
3
\$\begingroup\$

Ruby, 24

 r=eval s.gsub ?/,'**-1*'

Thank you to @ybeltukov for the Mathematica technique. I thought there might be a substitution that could be used to leverage eval and yours was much simpler than the crazy regexes I was trying!

This shortcut effectively changes the operator precedence in s to what the question requires. It has the side effect of sometimes resulting in a Rational object type (e.g. 2/1 == 2). The results are correct for the cases I've tried.

\$\endgroup\$
2
\$\begingroup\$

JavaScript (213 characters compacted, 133 if I'm willing to sacrifice my soul)

For clarity, this is the code before I compacted it down (JS-Fiddle of it):

function math(match, leftDigit, operator, rightDigit, offset, string) {
    var L = parseInt(leftDigit)
    var R = parseInt(rightDigit)
    switch (operator)
    {
        case '*': return R*L;
        case '\/': return R/L;
        case '+': return L+R;
        case '-': return L-R;
    }
};

multAndDivRegex = /(\-?\d+)([\*\/])(\-?\d+)(?=[^\*\/]*$)/; //Right to left
addAndSubRegex = /(\-?\d+)([\+\-])(\-?\d+)/; // Left to right

while(multAndDivRegex.test(str)) {
    str = str.replace(multAndDivRegex, math);
}

while(addAndSubRegex.test(str)) {
    str = str.replace(addAndSubRegex, math);
}

Here it is compacted down to 213 characters (containing some extra help from Toni Almeida) (JS-Fiddle of it):

function m(x,l,o,r){
    L=~~l;R=~~r;
    return o=='*'?R*L:o=='/'?R/L:o=='+'?L+R:L-R
}

for(M=/(\-?\d+)([\*\/])(\-?\d+)(?=[^\*\/]*$)/;M.test(s);s=s.replace(M,m));
for(A=/(\-?\d+)([\+\-])(\-?\d+)/;A.test(r=s);s=s.replace(A,m));

Since I'm ending lines with semi-colons, all removable whitespace was ignored for character counting, but left in for clarity.

I can get it down to 133 characters if I use eval(), but that's not how I roll... (JS-Fiddle)

function m(x,l,o,r){return o=='*'?~~r*~~l:~~r/~~l}for(M=/(\-?\d+)([\*\/])(\-?\d+)(?=[^\*\/]*$)/;M.test(s);s=s.replace(M,m));r=eval(s)

This solution would mean that people can enter ANY JavaScript code they want! The 303 character version does not execute any JavaScript; it only does math.

\$\endgroup\$
  • 1
    \$\begingroup\$ May I say, I loved this challenge! :D \$\endgroup\$ – IQAndreas Jan 6 '14 at 11:46
  • \$\begingroup\$ Well done! Here is a compacted version of your huge switch statment: o=='*'?R*L:o=='\/'?R/L:o=='+'?L+R:o=='-'?L-R:0 \$\endgroup\$ – António Almeida Jan 7 '14 at 9:12
  • \$\begingroup\$ By the way, you can save 4 characters by removing { and } from you while's, as they have only 1 instruction, they are useless. \$\endgroup\$ – António Almeida Jan 7 '14 at 9:15
  • \$\begingroup\$ Here is, 257 char version: jsfiddle.net/promatik/5W3nQ/2 \$\endgroup\$ – António Almeida Jan 7 '14 at 9:27
  • \$\begingroup\$ @ToniAlmeida Magnificent! Thanks. I trimmed off a few more characters in addition to that after re-reading the rules about allowing the use of s and r instead of input/output functions: jsfiddle.net/IQAndreas/5W3nQ/3 \$\endgroup\$ – IQAndreas Jan 9 '14 at 18:53
1
\$\begingroup\$

Python 3, 35

r=int(eval(s.replace("/","**-1*")))

Python 3, 30

If you are not scared of floating point value, try this one.

r=eval(s.replace("/","**-1*"))

Both of them evaluate the string s and store the result in variable r

\$\endgroup\$
  • \$\begingroup\$ This doesn't work. It gives 0 for "4/2" \$\endgroup\$ – recursive Jan 9 '14 at 21:42
0
\$\begingroup\$

GTB, 6

x?_)→R

6 chars and 6 bytes

EDIT - now that the original question has changed, here's some bloated code:

@iS_,"*")\\iS_,"/$_4;I,1,l?A;)-1:s;A;,2I,1)+A;&s;A;,1I→_&x?_)→R

I think I did a pretty good job; I made it only 63 characters ;) more than 1,000% bloat

\$\endgroup\$
  • \$\begingroup\$ I changed question a little bit. Now it is as supposed. \$\endgroup\$ – gthacoder Jan 5 '14 at 23:55
  • \$\begingroup\$ I changed answer a little bit. Now it is as required. \$\endgroup\$ – Timtech Jan 6 '14 at 0:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.