[解決済み] スニペットからプログラミング言語を検出する【終了しました
質問
コードのスニペットの中でどのプログラミング言語が使われているかを検出する最も良い方法は何でしょうか?
どのように解決するのですか?
スパムフィルタで使われている方法が非常に効果的だと思います。スニペットを単語に分割します。次に、これらの単語の出現を既知のスニペットと比較し、このスニペットが言語 X で書かれている確率を、関心のあるすべての言語について計算します。
http://en.wikipedia.org/wiki/Bayesian_spam_filtering
基本的なメカニズムがあれば、新しい言語を追加するのはとても簡単です。新しい言語のスニペット (オープン ソース プロジェクトを提供することもできます) をいくつか使って検出器を訓練するだけでよいのです。この方法では、C# のスニペットに "System" が、Ruby のスニペットに "puts" が表示される可能性があることを学習します。
私は実際にこの方法を使用して、フォーラム ソフトウェアのコード スニペットに言語検出を追加しました。それは、あいまいなケースを除いて、100% の確率で機能しました。
print "Hello"
コードを探します。
コードが見つからなかったので、新しいものを作りました。少し単純化されていますが、私のテストでは動作します。現在、RubyのコードよりもPythonのコードを多く与えると、このコードと言うことになりそうです。
def foo
puts "hi"
end
はPythonのコードです(実際はRubyですが)。これは、Pythonが
def
というキーワードもあるからです。ですから、もし1000倍の
def
が Python で 1000 回、100 回
def
が Ruby の場合、Python と表示されることがあります。
puts
と
end
は Ruby 固有のものです。言語ごとに見た単語を記録し、どこかでそれで割ることで解決できます(または、各言語で等量のコードを与えることで解決できます)。
お役に立てれば幸いです。
class Classifier
def initialize
@data = {}
@totals = Hash.new(1)
end
def words(code)
code.split(/[^a-z]/).reject{|w| w.empty?}
end
def train(code,lang)
@totals[lang] += 1
@data[lang] ||= Hash.new(1)
words(code).each {|w| @data[lang][w] += 1 }
end
def classify(code)
ws = words(code)
@data.keys.max_by do |lang|
# We really want to multiply here but I use logs
# to avoid floating point underflow
# (adding logs is equivalent to multiplication)
Math.log(@totals[lang]) +
ws.map{|w| Math.log(@data[lang][w])}.reduce(:+)
end
end
end
# Example usage
c = Classifier.new
# Train from files
c.train(open("code.rb").read, :ruby)
c.train(open("code.py").read, :python)
c.train(open("code.cs").read, :csharp)
# Test it on another file
c.classify(open("code2.py").read) # => :python (hopefully)
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン