Historical difference between `/` and `÷` in mathematical expressions
R, 68 66 bytes
function(x,y,`=`=`/`)eval(parse(t=`if`(y<1918,x,gsub('=','/',x))))
Try it online!
Expects equality sign =
instead of ÷
and *
instead of ×
.
The code makes use of some nasty operator overloading, making advantage of the fact that =
is a right-to-left operator with very low precedence (the exact behavior that we want from pre-1918 ÷
), and R retains its original precedence when it is overloaded. The rest is automatically done for us by eval
.
As a bonus, here is the same exact approach implemented in terser syntax. This time our special division operator is tilde (~
):
Julia 0.7, 51 bytes
~=/;f(x,y)=eval(parse(y<1918?x:replace(x,'~','/')))
Try it online!
JavaScript (ES6), 130 129 120 bytes
Saved 9 bytes thanks to @ScottHamper
Takes input as (year)(expr)
. Expects %
and *
instead of ÷
and ×
.
y=>g=e=>(e!=(e=e.replace(/\([^()]*\)/,h=e=>eval(e.split`%`.reduceRight((a,c)=>y<1918?`(${c})/(${a})`:c+'/'+a))))?g:h)(e)
Try it online!
How?
Processing leaf expressions
The helper function \$h\$ expects a leaf expression \$e\$ as input, processes all %
symbols according to the rules of the year \$y\$ (defined in the parent scope) and evaluates the resulting string.
If \$y<1918\$, we transform X%Y
into (X)/(Y)
, to enforce low precedence and repeat this process for the entire string from right to left to enforce right-to-left associativity.
Examples:
8%2
becomes(8)/(2)
, whose simplified form is8/2
2+3%3+2
becomes(2+3)/(3+2)
8%2%2
becomes(8)/((2)/(2))
, whose simplified form is8/(2/2)
If \$y\ge 1918\$, each %
is simply turned into a /
.
h = e => // e = input string
eval( // evaluate as JS code:
e.split`%` // split e on '%'
.reduceRight((a, c) => // for each element 'c', starting from the right and
// using 'a' as the accumulator:
y < 1918 ? // if y is less than 1918:
`(${c})/(${a})` // transform 'X%Y' into '(X)/(Y)'
: // else:
c + '/' + a // just replace '%' with '/'
) // end of reduceRight()
) // end of eval()
Dealing with nested expressions
As mentioned above, the function \$h\$ is designed to operate on a leaf expression, i.e. an expression without any other sub-expression enclosed in parentheses.
That's why we use the helper function \$g\$ to recursively identify and process such leaf expressions.
g = e => ( // e = input
e != // compare the current expression with
( e = e.replace( // the updated expression where:
/\([^()]*\)/, // each leaf expression '(A)'
h // is processed with h
) // end of replace()
) ? // if the new expression is different from the original one:
g // do a recursive call to g
: // else:
h // invoke h on the final string
)(e) // invoke either g(e) or h(e)
Python 3.8 (pre-release), 324 310 306 bytes
lambda s,y:eval((g(s*(y<1918))or s).replace('%','/'))
def g(s):
if'%'not in s:return s
l=r=j=J=i=s.find('%');x=y=0
while j>-1and(x:=x+~-')('.find(s[j])%3-1)>-1:l=[l,j][x<1];j-=1
while s[J:]and(y:=y+~-'()'.find(s[J])%3-1)>-1:r=[r,J+1][y<1];J+=1
return g(s[:l]+'('+g(s[l:i])+')/('+g(s[i+1:r])+')'+s[r:])
Try it online!
Takes %
instead of ÷
and *
instead of ×