昨日は酔っ払いながらn-gramと遊ぶ。
お陰で、とある自殺回数が多い作家様が書いた斜陽という作品は「お母さま」が325回出きたり(お母さま言い過ぎ)、ギロチンが24回出てくる(そんなに使ってたっけ?)ことが分かった。
分かったからどうだと言われると困る。語尾とかの傾向を見て「女性っぽい小説」、「男性っぽい小説」とかを見分けるくらいはできるかもしれないが。
にしても、文章解析の為にはやるべき下準備が多い。他人様の書いたソース読んだり、知らない概念を勉強したり。自分は頭悪いと1日5回くらい思う。その後、俺って天才と2回くらい思う。そんな日々。
$KCODE = 'UTF-8'
require 'kconv'
if ARGV.length < 2
p "@param inFile"
p "@param gram = 3 (min 2)"
p "@param minAppear = 5"
p "@param outFile = result.txt"
exit
end
# 入力ファイル名
inFile = ARGV[0]
# 区切り指定
gram = 3
gram = ARGV[1].to_i if ARGV[1]
# 出力最低出現回数(デフォルト5。5回以上登場する言葉を表示)
minAppear = 5
minAppear = ARGV[2].to_i if ARGV[2]
# 出力ファイル
outFile = "result.txt"
outFile = ARGV[3] if ARGV[3]
# 辞書
dic = {}
# ファイル読み込み
file = File::open(inFile, "r") do | file |
content = file.read.toutf8
# 「。」、改行、括弧などで分割
sentences = content.split(/。|「|」|《|》|<|>|<|>|『|』|(|)|\(|\)|\r\n/)
# さらに「、」で分割
content = []
sentences.each do | sentence |
content.push(sentence.split("、"))
end
# 辞書作成
content.each do | sentence |
sentence.each do | words |
# 空白除去
words.strip!
words.gsub!(" ", "")
# 1文字ずつ分割
words = words.split(//u)
(0..100000).each do | num |
# 指定文字ずつ区切る
word = words[num, gram]
break if word == nil or word.length != gram
if dic[word]
dic[word] += 1
else
dic[word] = 1
end
end
end
end
end
File::open(outFile, "w") do | file |
dic.sort { | a, b |
b[1] <=> a[1]
}.each { | key, value |
file.puts "#{key} : #{value}" if value >= minAppear
}
end