Last active
June 8, 2018 16:59
-
-
Save FrancoB411/4c4dccc888ce674f72a0202e17c67e49 to your computer and use it in GitHub Desktop.
Refactored to have a cleaner API, so users can calculate without explicitly newing up the class.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Calculator | |
ORDERED_OPERATIONS = %W(* / + -) # maintainable, add new operations easily | |
# no need to new up if you don't want to. | |
def self.calculate(input) | |
new.calculate(input) | |
end | |
# There is a pathological case where unknown operators are entered. | |
# So input validations would be a good idea in a production setting. | |
def calculate(input) | |
input = input.split(" ") # doesn't mutate the original input, may have tradeoffs in terms of memory for very long inputs | |
while input.length > 1 do # imperative, so 71% faster than recursive according to profiler | |
ORDERED_OPERATIONS.each do | op | # runs through each operation til it exhausts them in order | |
i = input.find_index(op) | |
# N**2 worst case, but each iteration will be N-2 for each found operation, so closer to N*(N/2) avg. | |
# Since N = 4 in the ORDERED_OPERATIONS array it's more like constant. | |
if i | |
prev = input[i-1].to_f # seemed more readable not to dry these up. | |
nex = input[i+1].to_f | |
result = operate(prev, op, nex) # now it accepts whatever operations you want, even custom methods | |
input = update_input_with_result(input, result, i) # naming is hard | |
end | |
end | |
end | |
input.first | |
end | |
private | |
def operate(prev, op, nex) | |
prev.send(op, nex) | |
end | |
def update_input_with_result(input, result, i) | |
input.slice!((i-1)..(i+1)) #extract evaluated items | |
input[i-1] = result #insert result into input | |
input | |
end | |
end | |
input = '7 - 2 + 3 / 4 * 5' | |
expected = (7 - (2 + (3 / (4 * 5.to_f)))) | |
actual = Calculator.calculate(input) | |
puts actual | |
puts (expected == actual) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment