Two Symbol Math

8

1

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.

Socratic Phoenix

Posted 2016-09-04T20:04:27.220

Reputation: 1 629

2

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.

– Linus – 2016-09-04T20:32:37.777

1@Linus: It also isn't equivalent when y=0, but I'm guessing the challenge implicitly assumes that n/d => d != 0. – Tim Čas – 2016-09-04T20:59:50.010

@TimČas ahh! Didn't think of that. I'll update the challenge, just know it will have to be handled properly – Socratic Phoenix – 2016-09-04T21:44:00.787

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. – Steven H. – 2016-09-06T03:29:19.417

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)? – Adám – 2016-09-06T07:29:32.047

@Adam you only have to handle "0" itself, I'll update the challenge – Socratic Phoenix – 2016-09-06T09:32:13.957

Can we assume that there will be no spaces in the input or do we have to strip them? – Beta Decay – 2016-09-06T09:58:12.963

@BetaDecay handle them... But they're not required in output. – Socratic Phoenix – 2016-09-06T10:13:45.517

Answers

4

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!

Beta Decay

Posted 2016-09-04T20:04:27.220

Reputation: 21 478

Honestly, I've no idea what dark magic you've employed, but +1 for FGITW – Socratic Phoenix – 2016-09-05T19:51:13.993

@SocraticPhoenix Haha the dark magic is called regex ;) – Beta Decay – 2016-09-05T19:54:27.673

1

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.

Adám

Posted 2016-09-04T20:04:27.220

Reputation: 37 779

0

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

Riley

Posted 2016-09-04T20:04:27.220

Reputation: 11 345