Ruby, Day 3

Last day on Ruby!

Retrospectively, I didn’t knew Ruby before (and I still don’t know much about it, admittedly), but it’s been fun.

I’m not a big fan after what I saw. I still find it a bit messy, but that’s maybe because I’m not used to it enough. The “you can rewrite anything and change basic behavior” is very nice, but I seriously wonder how many times it has bitten back developers. If someone rewrites one of the basic methods in a big codebase, I can only imagine the consequences, if you are luck enough to see them right away…

However, I enjoyed scripting with Ruby very much, and it was a good brainteaser to try to find the effective way of doing those things in a language I completely ignored so far.

Anyway, here is my last homework!

Do

So, the goal here is to modify a class that reads CSV files and add an each method that will perform a block on a CsvRow object, object that is to be written. This object should have its method_missing overwritten so that you can access columns as if they were methods:

module ActsAsCsv
 
  def self.included(base)
    base.extend ClassMethods
  end
 
  module ClassMethods
    def acts_as_csv
      include InstanceMethods
    end
  end
 
  module InstanceMethods
 
    def read
      @csv_contents = []
      filename = self.class.to_s.downcase + '.csv'
      file = File.new(filename)
      @headers = file.gets.chomp.split(', ')
 
      file.each do |row|
        @csv_contents << row.chomp.split(', ')
      end
    end
 
    attr_accessor :headers, :csv_contents
 
    def initialize
      read 
    end
 
    def each(&block)
      @csv_contents.each { |line| block.call CsvRow.new(@headers, line) }
    end
 
  end
 
end
 
class RubyCsv  # no inheritance! You can mix it in
  include ActsAsCsv
  acts_as_csv
end
 
class CsvRow
  attr_accessor :headings, :values
 
  def initialize(headings, values)
    @headings = headings
    @values = Hash[headings.zip(values).map { |e| [e[0], e[1]] }]
  end
 
  def method_missing(name, *args)
    col = name.to_s
    @values[col]
  end
end
 
csv = RubyCsv.new
csv.each { |row| puts row.two }

Ruby, Day 2

Find

#File IO without block
#f = File.new("testfile", "r")
#f.close
 
#File IO with block, implicit call to f.close
#File.open("testfile", "r") do |aFile| end
 
#Hash to array
h = { 1 => 2, "cat" => "tom" }
a = h.to_a
 
#Array to hash
a = (1..10).to_a
h = Hash[a.map { |i| [i, i * 2] } ]
 
#Iterate through a hash
h.each { |i| puts "#{i[0]} : #{i[1]}" }
 
#Use array as stack
a.push 19
a.pop
 
#Arrays can be used as: stacks, sets, queues, dequeues, and fifos

Do

Print the content of an array of sixteen numbers, four numbers at a time, using just each. Now, do the same with each_slice in Enumerable:

#Using each (interesting fact: there is a closure on a here)
a.each { |i| if i % 4 == 0 then puts "#{a[i-4..i-1]}" end }
 
#Using each_slice 
a.each_slice(4) { |s| puts "#{s}" }

Rewrite the Tree class so it can be initialized with a nested structure with hashes and arrays:

#Initial code from the book
class Tree
  attr_accessor :children, :node_name
 
  def initialize(name, children=[])
    @children = children
    @node_name = name
  end
 
  def visit_all(&block)
    visit &block
    @children.each { |c| c.visit_all &block }
  end
 
  def visit(&block)
    block.call self
  end
end
 
t = Tree.new("Ruby", [Tree.new("Gem")])
t.visit_all { |t| puts "#{t.node_name}" }

Starting from that, this is what we want to be able to write:

Tree.new({ 'grandpa' => { 'dad' => { 'child 1' => {}, 'child 2' => {} }, 'uncle' => { 'child 3' => {}, 'child 4' => {} } } })

And here is my solution to it:

class Tree
  attr_accessor :children, :node_name
 
  def initialize(structure)
    structure.each do
      |key, value|
      @node_name = key
      @children = value.to_a.map { |e| Tree.new({ e[0] => e[1] }) }
    end
  end
 
  def visit_all(&block)
    visit &block
    @children.each { |c| c.visit_all &block }
  end
 
  def visit(&block)
    block.call self
  end
end
 
t = Tree.new({ 'grandpa' => { 'dad' => { 'child 1' => {}, 'child 2' => {} }, 'uncle' => { 'child 3' => {}, 'child 4' => {} } } })
t.visit_all { |t| puts "#{t.node_name}" }

Write a simple grep that will print the lines of a file having any occurrences of a phrase anywhere in that line. Use Regular Expressions and include line numbers:

regex = Regexp.new('sit amet')
ln = 0
 
IO.foreach("TestGrep.txt") do |line|
  ln = ln + 1
  puts "#{ln}: #{line}" if regex.match(line)
end

Ruby, Day 1

It’s funny because I never learned Ruby, I never wanted to because dynamic languages don’t move me much, but so far it’s been quite fun.

First, a link to http://ruby-doc.org/docs/ProgrammingRuby/ that is the main reference to every question on that language.

I’m not going to run through all the exercises, but I will put solutions of those I found interesting to solve.

Print “This is sentence number 1” where the number 1 changes from 1 to 10:

(1..10).each { |i| puts "This is sentence number #{i}" }

Bonus problem: write a program that picks a random number (I will do between 1 and 1024, how geeky!). Let the player guess a number, telling the player whether the guess is too low or too high:

max = 1024
 
guess = -1
number = rand(max) + 1
 
puts "Guess a number from 1 to #{max}"
 
until guess == number
  guess = gets.to_i
  puts "Number is greater than #{guess}" if number > guess
  puts "Number is lesser than #{guess}" if number < guess
end
 
puts "Well done!"

Seven Languages in Seven Weeks

A recently bought the book titles “Seven Languages in Seven Weeks”. The book has excellent reviews, and I have to say that in the list of languages it covers, I only have vague notions for some of them (Prolog, Clojure, Haskell), but absolutely no experience with any of them.

So, what I’m going to do is write my answers to the exercises on this blog, day by day (the book is divided by “days”) to keep track of my progress and findings. I started out by writing all of this in a text file for private use, but I figured that, after all, why not make it public?

This will probably look boring if you know any of these languages, but mind you that I have no experience whatsoever with nearly all of them.

So, let’s start with the very trendy Ruby!

Google Mail Ads

Just a fun thing that happened today: I was sending a mail in GMail, and noticed that the customized ads displayed something that could be considered “offensive” to me, in a fun way:

CSharpSucksAd

Mr. Google is lying. C# rocks!

← Previous PageNext Page →