三角暗算其の二
前やった三角暗算,もっとシンプルになったので,もう一度考えてみる.
三角暗算シンプル版
名付けて,三角暗算其の二です.今回のは,入力周りとアルゴリズムを簡単にしました.
#! /opt/local/bin/ruby class Array def to_i! self.map!{|e| e.to_i} end def sankaku if self.size == 1 self[0] elsif self.size > 1 new_arr = [] (0 ... (self.size - 1)).each{ |i| new_arr[i] = self[i] + self[i + 1] } new_arr.sankaku end end end puts "Please input numbers by separating with a space" print ">" l = gets.chomp nums = l.split(/\s+/) if nums[0] =~ /^$/ nums.shift end nums.to_i! puts "result:#{nums.sankaku}" => $ ruby sankaku2.rb Please input numbers by separating with a space > 1 2 3 4 5 6 7 result:256
前のアレは,作った当時の心境を回想してみると,
三角暗算と言えば最低でも3つは計算できるよな.てことは,3つの計算方法を先に考えるか.例えばa,b,cとすると,三角暗算するとa+2b+cだ.とりあえずコレをメソッドにして,それだと柔軟性が無いから何個でも計算できるようにするか.
というように,「三角暗算は3つでやるもの」という視界から抜け出せず,挙げ句,三角暗算のアルゴリズムが,もっと簡単であるという事に気づかなかったんですね.
途中経過を表示
折角,一段ずつ計算するので,これを三角暗算っぽく表示すると楽しいかも.とか思いながら,書いてみた.ゴチャゴチャしてるので,読まない方が良いと思う.
#! /opt/local/bin/ruby class Array def to_i! self.map!{|e| e.to_i} end def depth count = 0 return lambda{ count += 1 } end def sankaku(depth = lambda{0}) # depth省略可能 d = depth.call (0 ... d).each{ print " " } if self.size == 1 puts self[0] self[0] elsif self.size > 1 new_arr = [] (0 ... (self.size - 1)).each{ |i| new_arr[i] = self[i] + self[i + 1] } self.each{ |e| print "#{e} " } puts if (d > 0) (0 ... d).each{ print " " } (0 ... (self.size - 1)).each{ print " +" } puts else (0 ... (self.size - 1)).each{ print " +" } puts end new_arr.sankaku(depth) end end end puts "Please input numbers by separating with a space" print ">" l = gets.chomp nums = l.split(/\s+/) if nums[0] =~ /^$/ nums.shift end nums.to_i! depth = nums.depth # 深さを求める puts "result:#{nums.sankaku(depth)}" => $ ruby sankaku3.rb Please input numbers by separating with a space >1 2 3 4 1 2 3 4 + + + 3 5 7 + + 8 12 + 20 result:20
アホみたいにゴチャゴチャしてるなぁ.ちなみに出力結果,4つぐらいならまだマシだけど,5つからズレまくります.
呼ばれた回数を数えたいがために,わざわざlambdaを使いたかったので変に長くなってますが,この辺りは幾らでも改良の余地がありそう*1.
で,考えてみた
さっきよりは,まだマシ.
#! /opt/local/bin/ruby class Array def to_i! self.map!{|e| e.to_i} end def d_count count = 0 return lambda{count += 1} end def sankaku self.to_i! d = d_count self.u_sankaku(d) end def u_sankaku(depth) d = depth.call (0 ... d).each{ print " " } if self.size == 1 puts self[0] self[0] elsif self.size > 1 new_arr = [] (0 ... (self.size - 1)).each{ |i| new_arr[i] = self[i] + self[i + 1] } self.each{ |e| print "#{e} " } puts (0 ... d).each{ print " " } (0 ... (self.size - 1)).each{ print " +" } puts new_arr.u_sankaku(depth) end end end puts "Please input numbers by separating with a space" print ">" l = gets.chomp nums = l.split(/\s+/) if nums[0] =~ /^$/ nums.shift end puts "result:#{nums.sankaku}" => $ ruby sankaku4.rb Please input numbers by separating with a space >1 2 3 4 1 2 3 4 + + + 3 5 7 + + 8 12 + 20 result:20
なんというか,sankakuの下に本体(u_sankaku)を置く事で,インタフェースはそのままに,実装方法(本体を呼ぶ方法)はsankakuで固定されている(引数も渡さなくて良い)ので,ユーザがdepthを定義しないで良いと.さらに,to_i!まで勝手にやるので,さらに楽かな.
俺流・仕様と実装の分離!俺流・カプセル化!考えてみると,上のゴチャゴチャ版は,
depth = lambda{puts "hoge"}
とかワケの分からん事をされたら,ひとたまりもありませんね.危ない.
結果的に
一番上が一番すき.HTMLだと,tableタグとか使えばもう少し綺麗に表示できるかな.そこでerubyですか.