コード中の文字の頻度分析

プログラムコード中の文字の頻度は言語によって相当にばらつきがあると思います。ある言語はピリオドが頻出するとか、別の言語はカッコの頻出頻度が高い、とか。そこで、

* 文字の頻度解析をするプログラムを作成し、
* 適当なプログラムに対して実行し、結果を出力して、そのような頻度になっている理由を教えてください。

(その言語で書かれた「典型的な」プログラムコード、といえるようなものがあると良いのですが・・)

簡単すぎるという方は、複数文字にしてみたり単語の頻度にしてみてください。

参考;Wikipedia 頻度分析

http://ja.wikipedia.org/wiki/%E9%A0%BB%E5%BA%A6%E5%88%86%E6%9E%90

エロと風俗情報満載 どう抜く?

というお題に対して以下のスクリプトが投稿されていた。

src = File.read(ARGV.shift)

hist = {}

src.each_byte do |c|
  c = c.chr
  if hist.member?(c)
    hist[c] += 1
  else
    hist[c] = 1
  end
end

hist.to_a.sort{|a,b| b[1] <=> a[1]}.each do |pair|
  puts "#{pair[0].inspect}: #{pair[1]}"
end


自分なりにちょっと書き換えてみた。

filename = ARGV.shift || 'c:/Ruby/lib/ruby/1.8/net/http.rb'
src = File.read(filename)
hist = Hash.new(0)

src.each_char {|c| hist[c] += 1 }
hist.sort_by {|k, v| -v }.each do |k, v|
  puts "#{k.inspect}: #{v}"
end


「hist」の場合分けは最初に「Hash.new(0)」で初期化しておけばいらなくなる。


「each_byte」で各要素に「chr」を使うよりも「each_char」を使った方が分かりやすいと思う。


配列にしてからソートするよりも「sort_by」を使った方が
value でソートしてるのが分かりやすいかと思って書き換えた。
降順にするのにも「-」付ければいいだけなので楽だし。


#{k} だと空白文字とか \n が分かりづらいけど
#{k.inspect} だと " " や "\n" って表示されるから分かりやすくなる。
普段あまり「inspect」使ってなかったから覚えておきたい。


実行結果

" ": 18101
"e": 4846
"t": 2987
"s": 2579
"r": 2527
"n": 2296
"\n": 2277
"o": 2252
"a": 1946
"d": 1761
"i": 1702
"T": 1216
"l": 1184
"p": 1127
"#": 1106
"c": 1090
"u": 955
"h": 918
".": 840
"_": 665
"H": 651
"P": 646
"f": 621
"y": 581
"'": 542
"=": 488
":": 478
"b": 464
"m": 461
",": 440
"(": 355
")": 355
"g": 338
"x": 317
"w": 317
"S": 281
"R": 280
"E": 259
"k": 243
"v": 240
"0": 236
"q": 221
"1": 215
"O": 205
"N": 176
"\"": 176
"-": 170
"@": 170
"+": 156
"/": 155
"A": 150
"C": 144
"D": 141
"2": 125
"|": 110
"B": 108
"4": 108
"Y": 103
"}": 102
"<": 102
"I": 102
"{": 102
"3": 93
"[": 93
"]": 93
">": 80
"?": 72
"U": 70
"5": 67
"M": 67
"j": 66
"\\": 59
"F": 55
"L": 51
"z": 43
"8": 43
"G": 42
"6": 34
"*": 33
"9": 30
"&": 29
";": 29
"V": 20
"W": 18
"X": 18
"Q": 17
"7": 15
"$": 14
"K": 11
"%": 10
"!": 7
"~": 7
"J": 5
"^": 3
"Z": 2
"`": 2