# Pascal's Triangle (#84)
#   solution by Michael C Nelson
#
# The basic idea is that this takes advantage of the fact that empty 
cells can
# be represented as zeros. For example,
#
#             1                0 1 0
#            1 1   is like,   0 1 1 0
#           1 2 1            0 1 2 1 0
#          1 3 3 1            1 3 3 1
#
# In this way we can just populate the topmost 1 and basically get the 
other
# diagonal edge 1's for free just by going though each row below it one 
at a
# time, and for each cell adding the diagonal upper ones to that cell.
#
# This is taken a step further in that the spaces between each number 
can be
# zeros as well, like,
#
#             1
#            101
#           10201
#          1030301
#
# Since these are zeros as well we can sum up all the spaces in between 
them as
# well, because they will all turn out to be zero in the end. This makes 
the
# code a bit simpler.
#
# Also the zeros are not explicitly set but are implemented in the 
hash's
# default value block (each row is a hash). This also handles values 
outside of
# the specified size range and returns 0 to handle edge cases for the 
final
# row. Also this handles mirroring of the pyramid as only the left half
# (including the middle column) is stored in the hash rows. This allows 
the
# filling out of the pyramid section to only operate on the left half as 
an
# optimization.
#
# When printed, all zeros are displayed as spaces, to make the final 
printout
# of the pyramid.
#
#             1                     000010000
#            1 1   is really like,  000101000
#           1 2 1                   001020100
#          1 3 3 1                  010303010
#
# Also note that the 'size' defined for the hight of the pyramid is also 
the
# same as the width of half the pyramid plus the middle, this is used
# interchangeably in the code.

# get the size from the command line, or use default, helped in testing
size =  (ARGV[0] || 10).to_i
total_width = 2*size-1

# Build an empty pyramid. Only half of the pyramid is held in the Array 
of
# Hashes, the right half is just a mirror of the left.
pascal = (0..size).map do
  Hash.new do |hash, key|
    if key > size && key <= total_width
      # mirror it
      hash[2*size-key]
    else
      # for everything else we can't find return zero
      0
    end
  end
end

# Seed the pyramid (this is the topmost middle "1").
pascal[0][size] = 1

# Build out the pyramid starting from the top down to the bottom. This
# optimizes a bit by only adding one half of the pyramid, which is 
mirrored by
# the Array of Hashes. Also, this only adds the area in the pyramid in 
order to
# avoid adding a bunch of zeros in the upper unused sections (there is 
still a
# bunch of zero adding within the pyramid but this makes the code a bit
# simpler). Note:  this could add the whole area and it would still 
work.
cell_width = 0
(1...size).each do |y|
  (size-y..size).each do |x|
    value = pascal[y-1][x-1] + pascal[y-1][x+1]
    unless value.zero?
      pascal[y][x] = value
      cell_width = value.to_s.length if cell_width < value.to_s.length
    end
  end
end

# Print out the result based on the cell_width.
(0...size).each do |y|
  (1..total_width).each do |x|
    if pascal[y][x].zero?
      print " "*cell_width
    else
      printf("%#{cell_width}d", pascal[y][x])
    end
  end
  print "\n"
end

-- 
Posted via http://www.ruby-forum.com/.