約6万語を含む英語のスペル辞書からアナグラムを探す
約6万語を含む英語のスペル辞書を使って、アナグラムとなっている単語をリストアップする。「珠玉のプログラミング」にある手法で、ソートした文字列で比較せよっていう話。それだけの話だから、すぐに試せるとか思ってやってみたけど、実際にやってみると結構あちこちでつまづいて20分ぐらいかかった。デフォルトでUTF-8を想定している外部文字エンコーディングにたいして、ISO-8859が来ると文字列マッチングのような処理でinvalidだと怒られて落ちる、とか。
入力ファイル(/usr/share/myspell/dicts/en_US.dic)は、
Abuja abundance/SM abundant/Y abused/E abuse/GVZDSRB abuser/M abuses/E abusing/E abusiveness/SM abusive/YP abut/LS abutment/SM abutted abutter/MS : :
という感じ。何やら文法情報のようなメタ情報も入ってる。
アクセント記号のついた外来語やアポストロフィのついた単語は無視。
FILE = "/usr/share/myspell/dicts/en_US.dic" list = {} File.open(FILE, "r:iso-8859-1") do |f| while line = f.gets next if line.nil? word = line.chomp.downcase word.gsub!(/\/.*/,"") next unless word =~ /^[a-z]+$/ sword = word.split(//).sort.join # world --> dlorw if list[sword] && list[sword] & [word] == [] then list[sword] << word else list[sword] = [word] end end end max = 0 list.each do |key,val| max = val.size > max ? val.size : max if val.size >= 2 then print val, "\n" end end print "words that have the max number of anagrams\n" list.each do |key,val| if val.size == max then print val, "\n" end end
結果は、
["alpert", "plater"] ["alpine", "nepali"] ["alp", "lap", "pal"] ["alps", "laps", "slap"] ["alric", "caril", "clair", "clari"] ["alston", "salton"] ["altai", "latia", "talia"] ["altair", "atrial", "lariat"] ["altitude", "latitude"] ["alton", "talon", "tonal"] ["altruism", "muralist"] : :
という感じ。a、e、mあたりががからむと比較的アナグラムになりやすいかしら。
["amass", "assam"] ["amber", "bream"] ["amble", "blame", "mabel", "mable", "melba"] ["ambler", "blamer", "marble", "ramble"] ["ambur", "burma", "rumba", "umbra"] ["amelie", "emelia"] ["amelina", "laminae", "malanie", "melania"]
アナグラムの最大数を調べたら8個。
["arin", "arni", "iran", "nair", "nari", "rain", "rani", "rina"] ["earth", "ertha", "harte", "hater", "heart", "herta", "retha", "rheta"]
しかし、かなり大きな英和辞典で引いても、rhetaとかerthaとか出てないし。rhetaはファーストネーム、erthaも名前で、ナチュラル系商品販売のブランド名とかだったりもするらしい。