パスカルの三角形(Ruby)

パスカルの三角形とは、こんな感じのものです。

              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      

規則性がわかりますね。多項式 (a + b)n を展開すると、係数がこんな風に並びます。

Ruby関数型プログラミングっぽく書いてみました。結構きれいに書けます。

pascal = ->(n) {
  each_cons = ->(ar) {
    (ar.size < 2) ? [] : [ar[0] + ar[1]] + each_cons.(ar.drop(1))
  }
  n.zero? ? [1] : [1] + each_cons.(pascal.(n - 1)) + [1]
}

n = 8
n.times {|i| puts pascal.(i).join(" ").center(30)}

 

追記(2020/1/7)

Enumerator を使って。

def generate_pascal_triangle
  Enumerator.new do |y|
    y << [1]
    ary = [1, 1]
    loop do
      y << ary
      ary = [1] + ary.each_cons(2).map { |a, b| a + b } + [1]
    end
  end
end

n = 8
puts generate_pascal_triangle.take(n).map { |ary| ary.join(" ").center(30) }

 
パターンマッチを使って。

def calc_pascal_triangle(*args)
  case args
  in [1] then [[1]]
  in [2, Array => result] then result
  in [Integer => n]
    calc_pascal_triangle(n, [[1], [1, 1]])
  in [Integer => n, Array => result]
    ary = [1] + result[-1].each_cons(2).map { |a, b| a + b } + [1]
    calc_pascal_triangle(n - 1, result + [ary])
  end
end

n = 8
puts calc_pascal_triangle(n).map { |ary| ary.join(" ").center(30) }

パターンマッチ、意外とおもしろいな。無理やりだけれども、型記述や多重ディスパッチみたいなことも可能かも。Ruby に合うかどうかはわからないが。