#!/usr/bin/python # globals verbose = False # set to True if you want debug info printed max_iter = 1000 # this stops infinate loops incase the code does not allow for some input def solve(problem_str): """ This task was to create a program that can process simple maths equations without the use of any external libraries, lambdas, eval() etc. See Stack Overflow question here for more details: http://stackoverflow.com/questions/21573436/solving-math-in-python-without-any-built-in-eval-functions-or-external-libraries/21580431#21580431 """ def multiply(arg_list): x = 1 for i in arg_list: x *= i return x def find_innermost(x_str): a, b, c = [-1], [0], 0 while True: start = a[-1]+1 # get position just after last opening bracket as start a.append(x_str.find('(', start)) # find next ( b.append(x_str.find(',', start)) # find next , c = x_str.find(')', start) # find next ) # if closing bracket is first or no more opening brackets left if (a[-1] > c) or (a[-1] == -1): # add to this to allow for more than 2 args by getting last comma before )? if (b[-2] > a[-3]) and (b[-2] < a[-2]): # if there is a comma between opening brackets 2 & 3 steps ago return x_str[b[-2]+1:c+1] else: return x_str[a[-3]+1:c+1] if len(a) > max_iter: raise Exception("Stuck in find_innermost loop") def do_sum(x_str): # get function arguements as integers from command string args = [int(x) for x in x_str[x_str.find('(')+1:x_str.find(')')].split(',')] task = x_str[:3].lower() # get function to be performed from command string if task == 'add': return sum(args) elif task == 'sub': return args[0] - sum(args[1:]) elif task == 'abs': if len(args) > 1: raise Exception("Only one arguement can be supplied for abs() function") return abs(args.pop()) elif task == 'mul': return multiply(args) else: print x_str + ': Task not recognised, please modify program or input' raise Exception("Invalid input") # solve function starts here... i = 0 while True: i += 1 if verbose: print 'debug: problem_str:', problem_str # find innermost nested problem if >1 opening bracket... if problem_str.count('(') > 1: x_str = find_innermost(problem_str) else: x_str = problem_str if verbose: print '.'*6, 'x_str:\t', x_str # process individual problem extracted from string... x = do_sum(x_str) if verbose: print '.'*6, 'x:\t', x, '\n' # replace individual problem with solution in full problem string... problem_str = problem_str.replace(x_str, str(x)) # return result if no problems remaining in string... if problem_str.count('(') == 0: return int(problem_str) if i >= max_iter: raise Exception("Stuck in main loop") # test solve function... p1 = 'abs(add(add(9465,38),multiply(add(63303,146),46)))' p2 = 'abs(add(multiply(95,multiply(-1,multiply(13,18875))),multiply(-1,add(18293,26))))' p3 = 'abs(add(subtract(add(add(151,26875),122),254),subtract(237,multiply(-1,56497))))' r1, r2, r3 = solve(p1), solve(p2), solve(p3) print 'p1 evaluates to:', r1 print 'p2 evaluates to:', r2 print 'p3 evaluates to:', r3