Hi,

here is my solution and a unit test. The triangle is calculated and  
stored as an array  of
arrays first. Then it's converted to a string.

I couldn't resist to add a pair iterator to class Array...

Regards,
Boris

# pascal.rb
class Array
   # iterate through pairs of consecutive elements
   def each_pair
     (0..size-2).each do |i|
       yield(self[i], self[i+1])
     end
   end
end

class Pascal
   def initialize(n)
     @triangle = [[1]]
     2.upto(n) do
       @triangle << calc_row(lastrow)
     end
   end

   def lastrow; @triangle[-1]; end

   # calculate row given the previous row
   def calc_row(previous)
     thisrow = [1]
     previous.each_pair do |x, y|
       thisrow << x + y
     end
     thisrow << 1
   end

   def to_s
     cellwidth   = lastrow.max.to_s.size
     indentation = lastrow.size - 1
     emptycell   = ' ' * cellwidth
     s = ''
     @triangle.each do |row|
       s << emptycell * indentation
       s << row.map{|cell| cell.to_s.center(cellwidth)}.join(emptycell)
       s << "\n"
       indentation -= 1
     end
     s
   end
end

if $0 == __FILE__
   puts Pascal.new(ARGV[0].to_i).to_s
end




# pascal_test.rb
require 'pascal'
require 'test/unit'

class PascalTest < Test::Unit::TestCase
   def test_1
     expected = "1\n"
     assert_equal expected, Pascal.new(1).to_s
   end

   def test_2
     assert_equal <<EXPECTED, Pascal.new(2).to_s
1
1 1
EXPECTED
   end

   def test_3
     assert_equal <<EXPECTED, Pascal.new(3).to_s
   1
1 1
1 2 1
EXPECTED
   end

   def test_10
     assert_equal <<EXPECTED, Pascal.new(10).to_s
                             1
                          1     1
                       1     2     1
                    1     3     3     1
                 1     4     6     4     1
              1     5    10    10     5     1
           1     6    15    20    15     6     1
        1     7    21    35    35    21     7     1
     1     8    28    56    70    56    28     8     1
1     9    36    84    126   126   84    36     9     1
EXPECTED
   end
end