```#!/usr/bin/env ruby
#
# pascal.rb - Pretty-print Pascal's Triangle
#
# Copyright (C) 2006 Louis J. Scoras
#
# This program is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public
# either version 2 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU General Public License for more
# details.
#
# [http://www.gnu.org/copyleft/gpl.html]

# Here's my solution for Ruby Quiz 84.  I realize that you can calculate the
# last row in the expansion using the binomial theorem, but you'll need to
# iterate through each row anyway to print the numbers out, so I just went
# with a caching method.
#
# I was going to implement a persistant disk cache, but alas I find myself
# currently stuck on a windows machine, which takes all the fun out of it--
# for me at least :)
#
# Thanks to Dirk and James for a great quiz.

require 'enumerator'

class PascalsRow

def initialize(numbers = , depth = 0)
@numbers = numbers
@depth   = depth
end

def even?
@depth % 2 == 0
end

def calculate_next
sums = if @numbers.length == 1

else
@numbers.enum_cons(2).collect {|j,k| j+k}
end

sums = sums << sums.last if even? && @depth != 0
self.class.new( + sums, @depth + 1)
end

def canonical
half = @numbers.dup
half.pop
half.pop unless even?
@numbers + half.reverse
end

def to_s
canonical.join(' ')
end

canonical.collect do |n|
digits  = n.to_s
padding = ((word_size - digits.length) / 2.0).ceil
digits +
end.join
end

private
' ' * [size, min_length].max
end
end

class PascalsTriangle
def initialize
@rows = [PascalsRow.new]
end

def iterate_rows(n, &block)
current_row = @rows.first
block.call(current_row) if block

n.times do |n|
current_row = if @rows[n+1]
@rows[n+1]
else
current_row = current_row.calculate_next
@rows[n+1]  = current_row
end
block.call(current_row) if block
end
current_row
end

def pretty(n)
last_line = iterate_rows(n)
word_size = last_line.numbers.last.to_s.length