class Fractify::Calculator
Public Class Methods
evaluate(formula)
click to toggle source
# File lib/fractify/calculator.rb, line 6 def evaluate(formula) fraction_string = '' current_rank = 0 incorrect_syntax, inside_of_a_fraction, minus_registered, operator_awaiting_an_argument, last_char_is_a_closed_bracket = false at_least_one_fraction = false fraction = nil operators = Fractify::OperatorArray.new index = 0 formula.each_char do |char| if inside_of_a_fraction if char == ')' fraction_string = "(#{fraction_string})" unless Fractify::Fraction.valid?(fraction_string) incorrect_syntax = true break end fraction = Fractify::Fraction.new(string: fraction_string) operators.last.to_right = fraction if at_least_one_fraction last_char_is_a_closed_bracket = true fraction_string = '' inside_of_a_fraction = false operator_awaiting_an_argument = false minus_registered = false current_rank -= 3 at_least_one_fraction = true else fraction_string += char end elsif char == '(' if last_char_is_a_closed_bracket incorrect_syntax = true break end current_rank += 3 minus_registered = false if minus_registered elsif char == ')' last_char_is_a_closed_bracket = true if current_rank.zero? incorrect_syntax = true break end current_rank -= 3 elsif Fractify::Fraction.numeric?(char) || char == '.' if current_rank.zero? incorrect_syntax = true break end unless inside_of_a_fraction inside_of_a_fraction = true operator_awaiting_an_argument = false if minus_registered fraction_string += '-' minus_registered = false operators.pop end end last_char_is_a_closed_bracket = false fraction_string += char elsif char == '-' minus_registered = true operator_awaiting_an_argument = true operator = Fractify::Operator.new(char, calculate_rank(current_rank, char), fraction) operators.push(operator) last_char_is_a_closed_bracket = false elsif char_is_an_operator(char) if operator_awaiting_an_argument || inside_of_a_fraction incorrect_syntax = true break end last_char_is_a_closed_bracket = false operator_awaiting_an_argument = true operator = Fractify::Operator.new(char, calculate_rank(current_rank, char), fraction) operators.push(operator) elsif char != ' ' incorrect_syntax = true break end index += 1 end if operator_awaiting_an_argument || inside_of_a_fraction || incorrect_syntax return nil end operators.sort_descending! operators.each do |op| case op.operator_character when '+' fraction = op.to_left + op.to_right when '-' fraction = op.to_left - op.to_right when '*' fraction = op.to_left * op.to_right when '/' fraction = op.to_left / op.to_right when ':' fraction = op.to_left / op.to_right when '÷' fraction = op.to_left / op.to_right when '^' fraction = op.to_left**op.to_right end left = op.to_left operators.each do |o| o.to_left = fraction if o.to_left == left o.to_right = fraction if o.to_right == left end op.executed! if op != operators.last new_op_index = find_operator_with_left(operators, op.to_right) operators[new_op_index].to_left = op.to_left unless new_op_index.negative? end end fraction end
valid?(formula)
click to toggle source
# File lib/fractify/calculator.rb, line 134 def valid?(formula) fraction_string = '' current_rank = 0 incorrect_syntax, inside_of_a_fraction, minus_registered, operator_awaiting_an_argument, last_char_is_a_closed_bracket = false at_least_one_fraction = false index = 0 formula.each_char do |char| if inside_of_a_fraction if char == ')' fraction_string = "(#{fraction_string})" unless Fractify::Fraction.valid?(fraction_string) incorrect_syntax = true break end last_char_is_a_closed_bracket = true fraction_string = '' inside_of_a_fraction = false operator_awaiting_an_argument = false minus_registered = false current_rank -= 3 at_least_one_fraction = true else fraction_string += char end elsif char == '(' if last_char_is_a_closed_bracket incorrect_syntax = true break end current_rank += 3 minus_registered = false if minus_registered elsif char == ')' last_char_is_a_closed_bracket = true if current_rank.zero? incorrect_syntax = true break end current_rank -= 3 elsif Fractify::Fraction.numeric?(char) || char == '.' if current_rank.zero? incorrect_syntax = true break end unless inside_of_a_fraction inside_of_a_fraction = true operator_awaiting_an_argument = false if minus_registered fraction_string += '-' minus_registered = false end end last_char_is_a_closed_bracket = false fraction_string += char elsif char == '-' minus_registered = true operator_awaiting_an_argument = true last_char_is_a_closed_bracket = false elsif char_is_an_operator(char) if operator_awaiting_an_argument || inside_of_a_fraction incorrect_syntax = true break end last_char_is_a_closed_bracket = false operator_awaiting_an_argument = true elsif char != ' ' incorrect_syntax = true break end index += 1 end if operator_awaiting_an_argument || inside_of_a_fraction incorrect_syntax = true end !incorrect_syntax end
Private Class Methods
calculate_rank(current_rank, operator)
click to toggle source
# File lib/fractify/calculator.rb, line 223 def calculate_rank(current_rank, operator) case operator when '*' current_rank + 1 when '/' current_rank + 1 when ':' current_rank + 1 when '÷' current_rank + 1 when '^' current_rank + 2 else current_rank end end
char_is_an_operator(char)
click to toggle source
# File lib/fractify/calculator.rb, line 240 def char_is_an_operator(char) %w[+ - * / : ÷ ^].include? char end
find_operator_with_left(operators, fraction)
click to toggle source
# File lib/fractify/calculator.rb, line 244 def find_operator_with_left(operators, fraction) counter = 0 operators.each do |op| return counter if op.to_left == fraction && op.not_executed? counter += 1 end -1 end