豊福@パパイヤです。
 
  ruby サイン本プレゼント係御中

  エントリ作品
  「英単語曖昧スペル検索」 spell.rb

    ruby spell.rb word [dictionary]

で word にスペルや音が似た英単語ベスト10を表示します。
  dictonary が指定されていないときは
/usr/local/lib/edict を検索します。

  辞書のフォーマットは edict のように一行につき
一キーワードが行の始めに書いてある形式です。

  文字列の類似度は私が適当に作った点数化法とアルゴリズム
を使っています。
  まだ実際に edict 辞書で試してないですが多分かなり時間
がかかると思います。

  曖昧検索でよい点数化法とアルゴリズムがあったら教えて下さい。
---
			豊福@パパイヤ
			unbound / papaya.juice.or.jp
			toyofuku / juice.or.jp

#!/usr/local/bin/ruby
# usage: spell.rb word [dictionary]

if (ARGV.size <= 0)
  puts("usage: #$0 word [dictionary]")
  exit 1
end

# 文字列 a と b の違いを点数化して返す
def diff(a, b)
  xlen = a.length
  ylen = b.length
  demerit = {}
  demerit[[0,0]] = 0

  for d in 1..(xlen + ylen)
    x = -1
    y = d + 1
    for i in 0..d
      x = x + 1
      y = y - 1

      if (y > ylen)
        next
      end
      if (x > xlen)
        break
      end

      x1 = x - 1
      y1 = y - 1

      if (x == 0)
        v = demerit[[0,y1]] + 2
      elsif (y == 0)
        v = demerit[[x1,0]] + 2
      else
        a1 = a[x1,1]
        b1 = b[y1,1]

        if (a1 == b1)
          # 一致したら減点 0
          ev = 0
        elsif (a1+b1 =~ /[aeiou]{2}|[lr]{2}|[fh]{2}|[bv]{2}|[ck]{2}|[cs]{2}|[mn]{2}/)
          # "l" と "r" ぐらいの違いのときは減点 1
          ev = 1
        else
          # 似ていないときは減点 3
          ev = 3
        end
        v = demerit[[x1,y1]] + ev

        v2 = 10000
        if (x >= 2 && b1 =~ /[fsxyz]/)
          # "ph" と "f" ぐらいの違いのときは減点 1
          if (b1 + ":" + a[x-2, 2] =~ /f:ph|[sz]:th|x:cs|y:[ei]e/)
            v2 = demerit[[x-2, y1]] + 1
          end
        elsif (y >= 2 && a1 =~ /[fsxyz]/)
          # "f" と "ph" ぐらいの違いのときは減点 1
          if (a1 + ":" + b[y-2, 2] =~ /f:ph|[sz]:th|x:cs|y:[ei]e/)
            v2 = demerit[[x1, y-2]] + 1
          end
        end

        # 片側読み飛ばしのときは減点 2
        v3 = demerit[[x1,y]] + 2

        # 片側読み飛ばしのときは減点 2
        v4 = demerit[[x,y1]] + 2

        # 最も減点の少ないコースを選ぶ
        v = v2 if (v2 < v)
        v = v3 if (v3 < v)
        v = v4 if (v4 < v)
      end

      return v if (x >= xlen && y >= ylen)

      demerit[[x,y]] = v
    end
  end

  raise("bug")
end

### main

default_dic = "/usr/local/lib/edict"
cand = []
sizemax = 10
dmax = 10000

word = ARGV.shift

if (ARGV.size == 0)
  ARGV.push(default_dic)
end

while (gets)
  ~/^\s*(\S*)\s*(.*)/
  d = diff(word, $1)
  if (d < dmax)
    cand <<= [d, $1, $2]
    cand.sort! {|a,b| a[0] - b[0] }
    if (cand.size > sizemax)
      cand.pop
      dmax = cand[sizemax-1][0]
    end
  end
end

for elem in cand
  print elem[1]
  print ("\t", elem[2]) if (elem[2] != "")
  print "\n"
end