パスカルの三角形〜なんか2次元配列,変〜

Haskellでは以前書きましたが,Rubyでは書いていなかったので,パスカルの三角形を書いてみます.


どうせならオブジェクト指向っぽくしてみましょう.先ずは適当にそれっぽく書いたものから.

class Pascal
  def initialize(height = 1, top = 1)
    @height = height > 0 ? height : 1
    @top = top
    
    i = 0
    @triangle = Array.new(@height){|e|
      e = Array.new(i += 1){nil}
    }
    
    self.calc
  end
  
  attr_reader :height
  attr_accessor :top
  
  def calc
    @triangle.each_index do |i|
      @triangle[i].each_index do |j|
        a = @triangle[i - 1][j] != nil ? @triangle[i - 1][j] : 0
        b = @triangle[i - 1][j + 1] != nil ? @triangle[i - 1][j + 1] : 0
        @triangle[i][j] = a + b != 0 ? a + b : top
      end
    end
  end
  
  def p_triangle
    @triangle.each do |e|
     p e
    end
  end
end

p = Pascal.new(5)

p.p_triangle

なんとなく,三角形の頂点を弄れるようにしたり,高さを変えて再計算できるようにしてみたり.
どうでも良い事だけど,pのあとに続く文によってpの挙動が変わるって凄いなぁ.
実行結果です.

$ ruby pascal.rb 
[1]
[1, 1]
[2, 1, 1]
[3, 2, 1, 1]
[5, 3, 2, 1, 1]

うぉおおぉぉい!それはフィボナッチダッツノ!!!これはこれで面白いので残しておこう.


どーも計算方法がおかしいので,calcを書き直し.

  def calc
    @triangle.each_index do |i|
      @triangle[i].each_index do |j|
        a = @triangle[i - 1][j - 1] != nil ? @triangle[i - 1][j - 1] : 0
        b = @triangle[i - 1][j] != nil ? @triangle[i - 1][j] : 0
        @triangle[i][j] = a + b != 0 ? a + b : top
      end
    end
  end

これでどうかな?

$ ruby pascal2.rb 
[1]
[2, 1]
[3, 3, 1]
[4, 6, 4, 1]
[5, 10, 10, 5, 1]

なんでだ?j = 0のときj - 1は-1だから,nilで0が入るんじゃないのか???
とりあえず,これなら確実.

  def calc
    @triangle.each_index do |i|
      @triangle[i].each_index do |j|
        if j == 0
          p @triangle[i - 1][j-1] # [i-1][j-1]を見るためのデバッグコード
          @triangle[i][0] = top
          next
        end
        a = @triangle[i - 1][j] != nil ? @triangle[i - 1][j] : 0
        b = @triangle[i - 1][j - 1] != nil ? @triangle[i - 1][j - 1] : 0
        @triangle[i][j] = a + b != 0 ? a + b : top
      end
    end
  end

格好悪い.試しに,これでjが0のときの[i - 1][j - 1]を見てみよう.

$ ruby pascal2.rb 
nil
1
1
1
1

も,もしかして・・・

[[1],[1,1],[1,2,1]]

が,内部的には[1,1,1,1,2,1]みたいな構造になっているのか?

        if j == 0
          p @triangle[i - 1][j - 5]
          @triangle[i][0] = top
          next
        end

ぐらいにし,比較し易いように弄って高さを10にしてみよう.

$ ruby pascal2.rb 
nil
[1]
nil
[1, 1]
nil
[1, 2, 1]
nil
[1, 3, 3, 1]
nil
[1, 4, 6, 4, 1]
1
[1, 5, 10, 10, 5, 1]
5
[1, 6, 15, 20, 15, 6, 1]
15
[1, 7, 21, 35, 35, 21, 7, 1]
35
[1, 8, 28, 56, 70, 56, 28, 8, 1]
70
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

こいつぁ間違いねぇな.ヘンテコな仕様なんだなぁ.