Today I ran (again) into the following question:
- Write a function that doesn’t use eval that calculates input strings with operators +,-,*,/ eg. “5+5*6+4/2″ should output 37
The first time I ran into this question I designed a solution, in Java, which had a SimpleCalculator class, and enam Operation
which supported the four basic arithmetic operations: +-*/ each of which had an apply
method etc. Very object oriented.
When I read this question today, I figured that it would be a nice exercise to do in Ruby – a few minutes later the result spread, elegantly, over less than 20 lines of code (and I bet that a professional Rubiest can do it in less)!
def is_number? expr return false if expr.nil? expr = "#{expr}" # we need this condition in case the expr is a number expr.match /^(\d+|\d+\.\d+)$/ # since match() is defined only for strings end def calc(expr) return expr.to_i if is_number? expr expr.gsub!(" ","") # clean the string from whitespaces # pay attention to the order: + and - should come before * and / # can you figure out why ? arr = expr.split /\+/ return arr.inject(0){|x,y| calc(x) + calc(y) } if arr.size > 1 arr = expr.split /\-/ return arr.inject(0){|x,y| calc(x) - calc(y) } if arr.size > 1 arr = expr.split /\*/ return arr.inject(1){|x,y| calc(x) * calc(y) } if arr.size > 1 arr = expr.split /\// return arr.inject {|x,y| calc(x) / calc(y) } if arr.size > 1 end puts calc("5+5* 6+4/2.0") #output 37
Do you have a better/shorter/more elegant solution ?
Please post it in the comments section!