tags:

views:

347

answers:

2

I tried to make a small script to evaluate post-fix expressions in Ruby.

def evaluate_post(expression)

    my_stack = Stack.new

    expression.each_char do |ch|        
    begin    
        # Get individual characters and try to convert it to integer
        y = Integer(ch)

        # If its an integer push it to the stack
        my_stack.push(ch)

    rescue    
        # If its not a number then it must be an operation
        # Pop the last two numbers
        num2 = my_stack.pop.to_i            
        num1 = my_stack.pop.to_i


        case ch
        when "+"   
         answer = num1 + num2     
        when "*"     
         answer = num1* num2    
        when "-"      
         answer = num1- num2     
        when "/"      
         answer = num1/ num2    
        end   

        # If the operation was other than + - * / then answer is nil
        if answer== nil
     my_stack.push(num2)
     my_stack.push(num1)
        else
     my_stack.push(answer)
     answer = nil
        end
    end
    end

    return my_stack.pop
end
  1. I dont know a better way to check if the character in the expression is an Integer without using this crude method or Regular Expressions. Do you guys have any suggestions?
  2. Is there a way to abstract the cases. Is there an eval("num1 ch num2") function in Ruby?
+2  A: 

I don't know ruby so I don't answer your questions. There is an algorithmic problem there, though. For add, multiply the order of operands doesn't matter but for subtraction and division, you should subtract and divide the first operand by the second. The first is the one deeper in stack. As a result, you should swap these two lines:

num1 = my_stack.pop.to_i
num2 = my_stack.pop.to_i
Mehrdad Afshari
thanks. i will do that.
kunjaan
+2  A: 

if you want to check if a string is an integer, Integer() is an elegant way to do it, because it makes sure your definition of an integer matches ruby's. if you would rather not use that because it throws an exception, regular expressions work nicely - why avoid them? also, note that in the integer case, you can simply push y onto your stack, not ch, and not need the to_i calls when popping. as for the other question, ruby does indeed have an eval.

y = Integer(ch) rescue nil   
if y  
  stack.push(y)  
else  
  num2, num1 = stack.pop(2)  
  a = eval "#{num2} #{ch} #{num1}" # see mehrdad's comment for why not num1 ch num2  
  stack.push(a)  
end
Martin DeMello