My first solution, a straightforward implementation that was
originally recursive, turned iterative:
def pascal n
rows = []
# generate data
(0...n).each do |i|
rows << if i.zero?
[1]
else
rows[i-1].inject([0]) do |m, o|
m[0...-1] << (m[-1] + o) << o
end
end
end
# calc field width
width = rows[-1].max.to_s.length
# space out each row
rows.collect! do |row|
row.collect { |x| x.to_s.center(2 * width) }.join
end
# display triangle
rows.each { |row| puts row.center(rows[-1].length) }
end
My second solution, after reading some of the discussion, was an
attempt to not generate the whole tree in memory, but only one row at
a time:
class Integer
def fact
zero? ? 1 : (1..self).inject { |m, o| m * o }
end
def binom(k)
self.fact / (k.fact * (self - k).fact)
end
end
def pascal n
# calc field width
width = (n - 1).binom(n / 2).to_s.length
# keep only one row in memory
row = [1]
1.upto(n) do |i|
# print row
space = ' ' * width * (n-i)
puts space + row.collect { |x| x.to_s.center(2*width) }.join
# generate next row
row = row.inject([0]) { |m, o| m[0...-1] << (m[-1] + o) << o }
end
end
Either solution started with:
pascal (ARGV[0] || 10).to_i
I could have done some error checking (i.e. bad input) or cached some
values for speed (Integer.fact and Integer.binom, particularly), but I
got lazy...