Mathematical substitution
Haskell, 474 362 bytes
The function f takes a string as input and prints the results
g '+'=(+);g '-'=(-);g '*'=(*);g '/'=(\a b->a*b/b/b)
p[]=[]
p(o:x:y)=[(flip(g o)$n,' ':o:' ':show n)|n<-v]:p r where
[f,e,s]=z;(z,h)=reads('[':y)!!0;(w,m)=reads(x:y)!!0;(v,r)|x=='['=(z,h)|x=='{'=([f,f+s..e],h)|True=([w],m)
h '}'=']';h x=x
d(a,b)=putStrLn.drop 3$foldl(++)""b++" = "++show(foldl(flip($))0a)
f t=mapM_(d.unzip)$sequence$p(filter(/=' ')$'+':map h t)
tests :
main=do
f "4.4 / [1,2.2] + {0,2,1}"
putStrLn""
f "[1,2] / 0 + 5"
putStrLn""
f "{0,2,1} + {0,1,1}"
output:
4.4 / 1.0 + 0.0 = 4.4
4.4 / 1.0 + 1.0 = 5.4
4.4 / 1.0 + 2.0 = 6.4
4.4 / 2.2 + 0.0 = 2.0
4.4 / 2.2 + 1.0 = 3.0
4.4 / 2.2 + 2.0 = 4.0
1.0 / 0.0 + 5.0 = NaN
2.0 / 0.0 + 5.0 = NaN
0.0 + 0.0 = 0.0
0.0 + 1.0 = 1.0
1.0 + 0.0 = 1.0
1.0 + 1.0 = 2.0
2.0 + 0.0 = 2.0
2.0 + 1.0 = 3.0
JavaScript (ES6), 213 211 bytes
f=x=>(a=0,x=x.replace(/\[.+?]|{.+?}/,r=>([i,l,n]=a=r.slice(1,-1).split`,`,r[0]>"]"&&eval(`for(a=[];n>0?i<=+l:i>=+l;i-=-n)a.push(i)`),"x")),a?a.map(n=>f(x.replace("x",n))).join``:x+` = ${r=eval(x),r<1/0?r:NaN}
`)
Explanation
A recursive function that executes the expression if it does not contain any multi-number or range generators, or if it does contain one of these generators, calls itself with the generator replaced with each number produced by it.
Dividing by 0
in JavaScript produces Infinity
, so Infinity
can simply be replaced with NaN
.
Using this method the multi-generators are parsed from back-to-front instead of front-to-back like in the test cases. This just means the order of the output expressions is different sometimes.
f=x=>(
a=0, // initialise a to false
x=x.replace(/\[.+?]|{.+?}/,r=>( // find the first multi-generator
[i,l,n]= // i = start, l = stop, n = step
a=r.slice(1,-1).split`,`, // a = each number of generator
r[0]>"]"&& // if a range generator was found
eval(` // use eval to enable for loop here
for(a=[];n>0?i<=+l:i>=+l;i-=-n)a.push(i) // add each number of the range to a
`),
"x" // replace the generator with "x"
)),
a? // if a multi-generator was found
a.map(n=> // for each number n in a
f(x.replace("x",n)) // call itself with n inserted
)
.join`` // combine the output of each result
:x+` = ${r=eval(x), // evaluate the expression
r<1/0?r:NaN}
` // replace Infinity with NaN
)
Test
Test does not use destructuring assignments for browser compatibility.
f=x=>(a=0,x=x.replace(/\[.+?]|{.+?}/,r=>(a=r.slice(1,-1).split`,`,r[0]>"]"&&eval(`i=a[0],l=a[1],n=a[2];for(a=[];n>0?i<=+l:i>=+l;i-=-n)a.push(i)`),"x")),a?a.map(n=>f(x.replace("x",n))).join``:x+` = ${r=eval(x),r<1/0?r:NaN}
`)
<input type="text" id="input" value="4.4 / [1,2.2] + {0,2,1}" />
<button onclick="result.textContent=f(input.value)">Go</button>
<pre id="result"></pre>
Python 3, 387 Bytes
def a(q,d=-1,f='',g=float,h=print):
if any((c in q)for c in'[]{}'):
for i,b in enumerate(q):
if d!=-1:
if b in'}]':
e=f.split(",")
if b=='}':
r=g(e[0]);s=[]
while r<=g(e[1]):s.append(str(r));r+=g(e[2])
e[:]=s[:]
[a(q[:d]+n+q[i+1:])for n in e];return
f+=b
if b in'[{':d=i
else:
h(q+" = ",end='')
try:h(str(eval(q)))
except:h("NaN")
You can test it with the following code:
tests=['3 * [3,2]', '{1,2,3}', '{0,2,1} + {0,1,1}',
'6/[2,3]', '{1.5,2.5,0.5}', '3-{6,5,-1}',
'5/{-1,1,1}', '4.4 / [1,2.2] + {0,2,1}',
'[1,2] / 0 + 5']
for n in tests:
print(n)
a(n)
print()
Here is the code ungolfed:
def eval_statement(query):
left_bracket_index = -1
inside_bracket_content = ''
if any((bracket in query) for bracket in '[]{}'):
for i, character in enumerate(query):
if left_bracket_index != -1:
if character in '}]':
params = inside_bracket_content.split(",")
if character == '}':
value = float(params[0])
values = []
while value <= float(params[1]):
values.append(str(value))
value += float(params[2])
params[:] = values[:]
for param in params:
new_query = query[:left_bracket_index] + param + query[i + 1:]
eval_statement(new_query)
return
inside_bracket_content += character
if character in '[{':
left_bracket_index = i
else:
print(query + " = ", end='')
try:
print(str(eval(query)))
except:
print("NaN")
It works by finding the first set of brackets of any type, and then looping through all the values inside it, by replacing the brackets and its contents with the value and running the method recursively. It uses eval
once there are no brackets in the line. It returns NaN
if there is an exception running eval
.