A simple calculator in Ruby

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!

Advertisements
A simple calculator in Ruby

Playing with Ruby

Ruby is a wonderful programming language, and when I say wonderful I mean that basically it just makes you happy. As a Java programmer, there are so many things that I need to check and be careful about, and Ruby just makes it easier for you, taking care of you, and if I have one more glass of wine I might get carried away and say that it almost spoils you, makes you lazy – cause now when I have to implement an algorithm, I’d rather do it in Ruby rather than Java, or even PHP, which is still easier, but with all the ugly $-signs (yes, I am lazy when it comes to hold the shift key and press ‘4’, who’s the dumb-a$$ that came up with that stupid idea anyways, ha ?)

One of the things I first do when starting to learn a programming language is implementing a few basic stuff, for example, the famous Tower of Hanoi:

def hanoi(disc, src, hlp, dst)
    if disc > 0
        hanoi(disc-1, src, dst, hlp)
        puts "moving disc #{disc} from #{src} to #{dst}"
        hanoi(disc-1, hlp, src, dst)
    end
end

hanoi(3, 'src', 'hlp', 'dst')

It’s so beautiful to define factorial in one line:

def fact(n) (1..n).inject{|r,i| r*i } end 

And then I usually continue to merge-sort:

# sorting the array from _start index to the _end index
# using merge sort
def mergesort(arr)

    # stop condition
    return arr if arr.count == 0 || arr.count == 1 
    # split the range
    mid = arr.count/2

    # sort recursively both parts
    arr1 = mergesort(arr[0, mid]) 
    arr2 = mergesort(arr[mid, arr.count-mid])

    # and merge
    merged = []
    max_i, max_j = [arr1.count, arr2.count]
    i = j = 0
    while i < max_i && j < max_j
        if arr1[i] <= arr2[j]
            merged << arr1[i]
            i += 1
        else
            merged << arr2[j]
            j += 1
        end
    end

    # continue copying the rest:
    while i < max_i
        merged << arr1[i]
        i += 1
    end
    while j < max_j
        merged << arr2[j]
        j += 1
    end

    # return
    merged
end

arr = [2,3,4,5,6,1,7]
puts mergesort(arr)        	

and if we didn’t have enough, let’s implement quicksort as well:

def quick(arr)
  return [] if (arr.size == 0)    
  pivot = arr.pop
  left = Array.new
  right = Array.new
  arr.each { |i|
    if i < pivot
      left << i
    else
      right << i
    end
  }
  return quick(left) + [pivot] + quick(right)
end

a = [5,3,9,8,7,2,4,1,6,5]
p quick(a)

The downside of coding in an unfamiliar language is that your’e still captured in patterns that are perfect for other programming languages, only that in this one – you can do things in a more elegant & efficient way.

Until next time…ta-ta!

Playing with Ruby

NOP people and learning Ruby

Some people can’t just sit and do nothing, I know that cause I’m one of them… I call these people: *NOP people. Even a ride on the elevator is just enough time to check emails and tweeter, and that’s also why I always need a side project. Last year I committed to PHP and MySQL (LAMP), even though I read some awful things about it, I decided to learn some PHP because there are so many CMSs built with LAMP:WordPress, Drupal, Joomla… and carts as well: Magento, Zen cart, Open cart

For year 2013 I decided to learn Ruby and Ruby on Rails. For those of you who don’t know the difference, it’s simple:

Ruby – scripting language that has many cool features such as dynamic typing (also known as “duck typing”)

Ruby on Rails – web framework for Ruby that provides many libraries that’ll make your life much easier. RoR, like Ruby, is provided free and is open source.

I have to admit that until the end of February I thought that Python will be the winner but then I ran into Rubymonk and it just caught me. In parallel to Rubymonk, I re-solved about 30 challenges in codeeval – because of the first rule of programming: you can’t learn a new language just by reading!

When I started coding in Ruby, I was looking for a good IDE for Mac and after some Googling work I decided on Sublime Text Editor. It takes a little time getting used to it, but when you learn shortcuts like command+R – jump to another function, or, command + P – to browse between files, and the very convenient tab completion (ife, tab for if-else-end for example) and many other shortcuts which you can browse yourself by typing command + shift + P. God bless sublimeText!

I didn’t take any of the in from Try Ruby but I bet that they’re good, and I can say that because I took a few classes in Rails for Zombies and it was fun! I would definitely check out the other classes in codeschool.

On my next NOP of course..

______________________________________________________________________________.

*NOP – In computer science, NOP or NOOP (short for No Operation) is an assembly language instruction, sequence of computer programming language statements, or computer protocol command that effectively does nothing at all. (from wiki)

NOP people and learning Ruby