Skip to content

Instantly share code, notes, and snippets.

@PraveshKoirala
Created September 15, 2017 18:38
Show Gist options
  • Save PraveshKoirala/88f554515768b41b90629fa2ca81926b to your computer and use it in GitHub Desktop.
Save PraveshKoirala/88f554515768b41b90629fa2ca81926b to your computer and use it in GitHub Desktop.
Developed for /r/dailyprogrammer challenge #331
import re
from operator import mul, pow, add, sub, div
__author__ = 'pravesh'
def get_simple_statement(statement):
template=r"((\-?\d+(?:\.\d+)?)\%s(\-?\d+(?:\.\d+)?))(?!\^)"
for opstr, opfunc in [("^", pow), ("*", mul), ("/", div), ("+", add), ("-", sub)]:
template_str = template % opstr
while opstr in statement:
#todo associativity for ^ operator
match = re.findall(template_str, statement)
if opstr=="-" and not match: break
eqn, a, b = match[0]
c = str(opfunc(float(a), float(b)))
statement = statement.replace(eqn, c)
return statement
replace_all = lambda st, (old, new): st.replace(old, new)
def get_func_call(statement, index):
para_index = statement.find("(", index)
para_count = 1
while para_count!=0:
para_index += 1
if statement[para_index] == ")":
para_count-= 1
elif statement[para_index] == "(":
para_count+=1
if para_count == 1 and statement[para_index] == ",":
statement = statement[:para_index] + "$" + statement[para_index+1:]
return statement[index: para_index+1]
def func_replace(statement, funcs):
# replace the function statements
for fname, fvalue in funcs.items():
index = 0
while index!=-1:
index = statement.find(fname+"(")
if index != -1:
func_call = get_func_call(statement, index)
arg_values = map(lambda w: "(" + w + ")", func_call[len(fname)+1:-1].split("$"))
func_call = func_call.replace("$", ",")
replaced_call = reduce(replace_all, zip(fvalue["args"], arg_values), fvalue["def"])
statement = statement.replace(func_call, replaced_call)
return statement
def evaluate(statement, vars, funcs):
while "(" in statement:
# get all the (a+b+c...) i.e. bracketed values first
priority_eq = re.findall(r"\([0-9\.\+\-\^\*/_]+?\)", statement)
# evaluate the expressions sans the brackets .. i.e. evaluate(a+b+c)
values = map(get_simple_statement, [peq[1:-1] for peq in priority_eq])
# replace in the equation
statement = reduce(replace_all, zip(priority_eq, values), statement)
return get_simple_statement(statement)
def get_results(line, vars, funcs):
result = None
var = None
if "=" in line:
func_match = re.findall(r"(\w+)\((.*)\)=(.*)", line)
if func_match:
fname, args, definition = func_match[0]
args = args and args.split(",") or []
# sig = r"{fname}\({args}\)".format(fname=fname, args=",".join([r"(\-?\d+(?:\.\d+)?)"]*len(args)))
funcs[fname] = {"args": args, "def": definition}
return "\n"
# either a variable assignment or function assignment
var_match = re.findall(r"([a-z]\w*)=(.*)", line)
if var_match:
var, line = var_match[0]
# lazy replace function
line = func_replace(line, funcs)
line = reduce(replace_all, vars.items(), line)
result = evaluate(line, vars, funcs)
if var:
vars[var] = result
return result
def main():
print "Interactive interpreter: type statements and press enter. type exit to exit"
vars, funcs = {}, {}
while True:
input = raw_input("").strip().replace(" ", "")
if input == "exit":
return 0
print get_results(input, vars, funcs)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment