勝手に添削をさらに勝手に書き直す

rubyneko - 知人のRubyコードを勝手に添削してみたを見て、個人的に気になったところを勝手に直してみた。かなり、個人的な好みなので、これがいいのかわからないけど。

require 'pp'

#def functions

def make_cluster(centroid, num_array)
   c = num_array.select{|v| (centroid[0] - v)**2 < (centroid[1] - v)**2}
   [c,(num_array - c)]
end

def make_centroid(cluster)
  cluster.map do | c |
     c.size == 0 ? 0 : c.inject{|i,j| i + j}/c.size
  end
end

def calc_var(centroid, cluster)
   cluster.zip(centroid).map do | clu , cen |
      clu.inject(0.0){|i,j| i += (j - cen)**2}
   end
end


#end def functions

num_array = [1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 6.0, 7.5, 8.0, 8.5, 9.0, 10.0]

new_centroid = [0.0, 1.0]
centroid = [0.0, 0.0]
counter = 0
while centroid != new_centroid
   centroid = new_centroid
   cluster = make_cluster(centroid, num_array)

   puts "step#{counter}:"
   puts "centroid:"
   pp centroid

   #calc var
   puts "var:"
   pp calc_var(centroid, cluster)

   puts "cluster:"
   pp cluster

   new_centroid = make_centroid(cluster)
   counter += 1

   puts "\n"
end

まず、make_cluster関数は、別にもとのままでも良かったんだけど、勢いで書き直してみた。というか、if exp then a1 else a2 end << valという書き方ができるのを初めて知った。

make_centroid関数と、calc_var関数に関しては、先に結果の配列を作って、Rangeクラス使ってインデックスを作り、違う配列の同じインデックスの要素をつかって計算し、結果の配列のそのインデックスの位置に格納されていたんだけど、、それってzipしてmapでいいんじゃないかと。ここら辺は、haskellやりだしてから、自分の常套手段。

あと、最後の計算部分でloop使われていたんだけど、breakする条件があるのであれば、while使いたい。停止条件がうもれてしまうので。そのおかげで、元のソースより、出力される改行が一つ多くなってしまったんだけど。


ちなみに、ソースの長さはこんな感じになった。別に、ゴルフじゃないからいいんだけど。

: wc before.rb after.rb 
      65     147    1087 before.rb
      49     123     893 after.rb