8
\$\begingroup\$

Introduction

The four basic math operators (+, -, *, /) can be reduced to just two, due to the fact that:

x + y = x - (-y)
x * y = x / (1/y), y != 0
x * 0 = 0/x

Challenge

The challenge is to take input as a "string" containing:

  • Numbers
  • Single character variables ("x", "y")
  • The four basic math operators (+, -, *, /)
  • Parenthesis

and output a string manipulated so that it would produce the same mathematical result as the input, but containing only the mathematical symbols '-' and '/'

Specifics

  • Input can be in any acceptable form (file, STDIN, etc.) and may be represented as a string or character array (but not an array of arrays)
  • Output can be in any acceptable form (file, STDIN, etc.) and may be represented as a string or character array (but not an array of arrays)
  • You must recognize and maintain balanced parenthesis
  • Standard loopholes are disallowed
  • It is your choice if you want to represent x + y as x - -y or x - (-y)
  • You must maintain the order of operations
  • You never have to handle invalid input
  • Input can be empty or a single number/variable, in that case the program should output the input
  • Note: You do not have to use the substitutions in the introduction, so long as input = output, your program could change 2 * 2 to 8/2, if you wanted
  • You can assume that "0" is the only way a zero will appear in the equation (I.e. you don't have to handle 1 * (4 - 4))
  • Suggestion: to test your program, go to this website type in input = output, where input is the input, and output is the output, and if the result is "true" your program handled that case successfully (example, example)

Test Cases

Below are some test cases, input as a single string and output as a single string.

x + y
x - (-y)

x * y
x / (1/y)

x / y
x / y

x - y
x - y

1
1

5
5

-6
-6

+x
x

1 + (x * 4) - (512 * 3)
1 - (-(x / (1/4))) - (512 / (1/3))

1 - 3 / 4 + l / g
1 - 3/4 - (-(l / g))

5 * 0 / 2
0/5 / 2

(a + g) * 0
0/(a - (-g))

Scoring

It's , so shortest answer in bytes wins. Ties are resolved by first-post.

\$\endgroup\$
  • 2
    \$\begingroup\$ By the way x / 1/y = x/y because division isn't associative. I know what you're thinking, but even WolframAlpha doesn't recognize that you want spaces to change the order of operations.... so you probably should rethink this or not cite that as a valid way to check things. \$\endgroup\$ – Linus Sep 4 '16 at 20:32
  • 1
    \$\begingroup\$ @Linus: It also isn't equivalent when y=0, but I'm guessing the challenge implicitly assumes that n/d => d != 0. \$\endgroup\$ – Tim Čas Sep 4 '16 at 20:59
  • \$\begingroup\$ @TimČas ahh! Didn't think of that. I'll update the challenge, just know it will have to be handled properly \$\endgroup\$ – Socratic Phoenix Sep 4 '16 at 21:44
  • \$\begingroup\$ As it stands, there's very little stopping us from simply evaluating the expression and returning the result (they're mathematically equal, after all). I'd recommend changing that, unless you want v to be a proper solution in Pyth. \$\endgroup\$ – Steven H. Sep 6 '16 at 3:29
  • \$\begingroup\$ Wait, so if there are variables (like x and y), how can we divide without risking division by zero? 5 * (a - b) if a=b. And do we have to detect things like 5 * (a - a)? How about 5 * (4 - 4) and 5 * (a / a - 1) or 5 * (4 / 4 - 1)? \$\endgroup\$ – Adám Sep 6 '16 at 7:29
4
\$\begingroup\$

Python 3, 267 bytes

Thanks to @ConorO'Brien

import re
q=re.sub
g=lambda m:'--'+m.group()[1:]
h=lambda m:'/(1/'+m.group()[1:]+')'
i=lambda m:'0/'+m.group()[:-2]
print(q(r'\*[^\(\)]+',h,q(r'[^\(\)]\*0',i,q(r'\+[^\(\)]+',g,q(r'\*\([^\)]+\)',h,q(r'\([^\)]+\)\*0',i,q(r'\+\([^\)]+\)',g,input().replace(' ',''))))))))

Ideone it!

\$\endgroup\$
  • \$\begingroup\$ Honestly, I've no idea what dark magic you've employed, but +1 for FGITW \$\endgroup\$ – Socratic Phoenix Sep 5 '16 at 19:51
  • \$\begingroup\$ @SocraticPhoenix Haha the dark magic is called regex ;) \$\endgroup\$ – Beta Decay Sep 5 '16 at 19:54
1
\$\begingroup\$

Dyalog APL, 42 bytes

This maintains APLs order of operations. Note that ÷x is 1÷x

'\+' '×'⎕R'--' '÷÷'('(.*)×0'⎕R'0÷\1'~∘' ')

TryAPL online!

( on the result of...

~∘' ' remove spaces

'(.*)×0'⎕R'0÷\1' replace anything followed by "×0" with "0÷" followed by it

) evaluate...

'\+' '×'⎕R'--' '÷÷' replace "+" with "--" and "×" with "÷÷"

To verify:

  1. Assign random non-zero numbers to x, y, l, g, and a.

  2. Execute the original expressions.

  3. Execute the modified expressions.

  4. Compare the results.

\$\endgroup\$
0
\$\begingroup\$

SED 272 246 239 213

s,^\+,,;s,[^+*/()-]\+,(&),g;t;:;s,)[^)]*)\*(0,&,;tr;s,\((.*)\)\*(0),(0/\1),;ty;s,\*([^)]*(,&,;tr;s,\*\(([^)]*)\),/(1/\1),;ty;s,\+([^)]*(,&,;tr;s,\+\(([^)]*)\),-(-\1),;ty;p;q;:r;s,(\([^()]*\)),!\1@,;t;:y;y,!@,(),;b

Take input without spaces (e.g. x+y*2).
This is one of the few cases where it is actually shorter to just escape ( and ) for capture groups instead of using -r. I'm sure this can be golfed more, but I'm happy for now.

Ungolfed, with comments:

s,^\+,, #remove leading +
s,[^+*/()-]\+,(&),g #suround numbers/variables in ()
t start #reset the test because the line above will always match

:start
#------------- deal with *0 ------------------
s,)[^)]*)\*(0,&, #remove inner matching ()
t replace
s,\((.*)\)\*(0),(0/\1),
t y
#------------- deal with generic * -----------
s,\*([^)]*(,&, #remove inner matching ()
t replace
s,\*\(([^)]*)\),/(1/\1),
t y
#------------- deal with + -------------------
s,\+([^)]*(,&, #remove inner matching ()
t replace
s,\+\(([^)]*)\),-(-\1),
t y

b end #all done, branch to the end

#------------- replace a set of () with !@ ---
#repeated application of this helps find the matching ( or )
:replace
s,(\([^()]*\)),!\1@,
t start

:y
y,!@,(),
b start

:end
\$\endgroup\$

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.