William James wrote: > Short: > > D=IO.read('dict').split($/).grep(/^.{#{$*[0].size}}$/) > def rate(new,old,goal,l) > t=0; v=0; new.size.times{|i|t+=1 if new[i]!=old[i] > v+=1 if new[i]==goal[i] } > [ 1==t && nil==l.index(new), v ] > end > def m(a,b,l) > l << a.dup > if a==b then p l; exit; end > D.inject([]){|w,x| y,v = rate(x,a,b,l) > w << [v,x] if y ; w > }.sort.reverse_each{|v,x| m(x,b,l) } > end > m($*[0], $*[1], []) Using Dominik's nice idea i boiled it down to: (the dictionary is the optional third parameter, no -d) ----------------------------------------------------------- dict, len = Hash.new{|h,k|h[k] = []}, ARGV[0].size IO.foreach(ARGV[2] || 'words.txt') do |w| w.chomp! if w.size != len then next else s = w.dup end (0...w.size).each{|i|s[i]=?.; dict[s] << w; s[i]=w[i]} end t, known = {ARGV[1] => 0}, {} while !known.merge!(t).include?(ARGV[0]) t = t.keys.inject({}){|h, w|(0...w.size).each{|i| s=w.dup; s[i]=?.; dict[s].each{|l|h[l] = w if !known[l]}};h} warn 'no way!' or exit if t.empty? end puts w = ARGV[0]; puts w while (w = known[w]) != 0 ----------------------------------------------------------- It's still quite fast. BTW: Is there a nice way to construct a hash, like #map does? like: array = (1..10).map{|i| i} hash = (1..10).map_to_hash{|i| i => i*2} (i always use inject in a 'not so nice' way) cheers Simon