Archive for the ‘Programming’ Category

Ruby: Watch a file for changes

Monday, December 28th, 2009

I was writing a script that does numerical differentiation, which required a lot of tweaking. I thought it would be quite cool to be able to see the results of the script automatically, whenever I made a change to the script, without having to run it again.

So I quickly wrote this up:

require 'digest/md5'
 
$md5 = ''
 
def watch(file, timeout, &cb)
  $md5 = Digest::MD5.hexdigest(File.read(file))
  loop do
    sleep timeout
    if ( temp = Digest::MD5.hexdigest(File.read(file)) ) != $md5
      $md5 = temp
      cb.call(file)
    end
  end
end

That is the main function. It will wait for a fixed amount of time, get a hash of the file and compare it with a previous version. If it has changed, then it executes the callback which you have specified.

Here is an example of how it can be used:

$num = 0
watch '../num_diff.rb', 1 do |file|
  puts "\e[31m MODIFIED: \e[0m \e[34m #{file} \e[0m (#{$num}, #{Time.now})"
  puts "\e[32m     -- EXECUTING -- \e[0m"
  puts
  puts `ruby #{file}`
  puts
  puts "\e[32m -- FINISHED EXECUTION -- \e[0m"
  puts
  $num += 1
end

This is what the output looks like:
Screenshot

Implementation of Octave’s diag in Ruby

Sunday, December 13th, 2009

GNU Octave has a diag function which behaves like this:

octave> diag([1,2,3])
ans =
 
Diagonal Matrix
 
   1   0   0
   0   2   0
   0   0   3

To be more clear,
 diag \left( \begin{array}{ccc} 1 & 2 & 3 \end{array} \right) = \left(   \begin{array}{ccc}  1 & 0 & 0 \\ 0 & 2 & 0 \\ 0 & 0 & 3    \end{array}    \right)

Here is an implementation of the diag function in Ruby:

# Create a diagonal matrix given a vector (or an array), 
# placing the entries of the vector on the diagonal of 
# the matrix.
# For example, diag([1,2,3]) would give:
# [ 1 0 0 ]
# [ 0 2 0 ]
# [ 0 0 3 ]
# That would actually be a 2D matrix like this 
#  [[1, 0, 0], [0, 2, 0], [0, 0, 3]]
# The array returned has to be converted to a matrix by doing 
#  Matrix[ *diag(vector) ]
def diag(vector)
  n = vector.size
  matrix = []
  n.times do |i|
    matrix << Array.new(n) { |x| (x == i) ? vector[x] : 0 }
  end
  matrix
end

You can also get the code in this gist; use it as you wish.

Project Euler Problem 40

Thursday, October 29th, 2009

Project Euler Problem 40

In my opinion, this was the easiest problem so far. The brute-force method is easy to implement and runs very fast.

This is the code:

$fraction = ''
 
1.upto(1000000) do |i|
  $fraction << i.to_s
end
 
def d_(n)
  $fraction[n-1].to_i
end
 
puts d_(1) * d_(10) * d_(100) * d_(1000) * d_(10000) * d_(100000) * d_(1000000)

It runs in slightly lesser than one second.

The last line isn’t very Ruby-ish because I copied it from the problem description page, because I’m too lazy to write it myself. That’s also why I have a d_(n) function.

Project Euler Problem 21 (Ruby)

Thursday, September 24th, 2009

If you intend to solve the problem on your own, I wouldn’t recommend reading any further.

Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).
If d(a) = b and d(b) = a, where a \neq b, then a and b are an amicable pair and each of a and b are called amicable numbers.

For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.

Evaluate the sum of all the amicable numbers under 10000.

(Problem 21 – Project Euler)

def d(n)
  total = 0
  1.upto n/2 do |i|
    if (n % i) == 0
      total += i
    end  
  end
  total
end
 
amicable_sum = 0
 
10000.times do |a|
  b = d(a)
  if d(b) == a && b > a
    amicable_sum += a + b
  end
end
 
puts amicable_sum

My version of d(n) isn’t as efficient as the one in the PDF you get after solving the problem, but it gets the job done.

Running it takes around 8.5 seconds on my machine. That’s not too bad for ~20 lines of code.

Automatically Resize Large Images with Javascript

Sunday, May 24th, 2009

When you allow users to submit content, and allow that content to include images, there’s always a chance that some user will submit a really large image that will break your layout. One way to solve that is to check the content for large images and resize them using a server-side program. However, sometimes, that is simply not possible. In those cases, we use what’s left- Javascript. (more…)

Zenity.rb

Tuesday, May 12th, 2009

Zenity is a command line based tool that helps shell scripts display GTK dialog boxes as a more interactive way to display error messages, get user input and other stuff like that. (more…)

Getting a Method to Accept an Arbitrary Number of Arguments in Ruby

Saturday, May 9th, 2009

(more…)

Very Simple Metronome in Ruby

Thursday, April 23rd, 2009

A metronome is basically something that beeps periodically, indicating the exact tempo of some music. I wanted one for my guitar practice, but the only one in Ubuntu’s repos (GTick) wouldn’t work, so I wrote this up. (more…)

How to Learn a New Programming Language

Saturday, April 4th, 2009

Learning a new language isn’t the easiest thing to do. It can, however, be a very rewarding experience if you are persistent enough. Luckily, if you know how to code in one language, it is much, much easier to learn another language. Here are some tips that can help you. (more…)

Implemeting HQ9+ in 10 lines of Ruby

Friday, April 3rd, 2009

HQ9+ is a excessively simple esoteric programming language. It has only four commands:
H: Print “Hello, World!”
Q: Prints the contents of the program onto the screen
9: Print the canonical lyrics of the song, “99 bottles of beer”.
+: Increment the accumulator

Here’s the entire implementation:

1
2
3
4
5
6
7
8
9
10
def hq9(src)
  src.downcase.split('').each do |i|
    case i
      when 'h'; puts "Hello, World!"
      when 'q'; puts src
      when '9'; 99.downto(0) { |b| puts "#{b==0?'No more b':"#{b} B"}ottle#{'s'if b!=1} of beer on the wall, #{b==0?'No more':b} bottle#{'s'if b!=1} of beer.#{b==0?"nGo to the store and buy some more, 99 bottles of beer on the wall.":"nTake one down and pass it around, #{b-1} bottle#{'s'if b!=2} of beer on the wall.nn"}" }
      when '+'; $i = $i ? $i + 1 : 0;
    end
  end
end

Note: I got the lyric printing code from here.