Skip to content

Instantly share code, notes, and snippets.

@shibukawa
Created April 21, 2012 05:51
Show Gist options
  • Save shibukawa/2434507 to your computer and use it in GitHub Desktop.
Save shibukawa/2434507 to your computer and use it in GitHub Desktop.
Fuzzy method calling
module HAL
module_function
def calc_weight(index, length)
distance = (length - 1.0 - index) / (length - 1.0)
distance * distance * 0.5 + 1.0
end
def strings_distance(source, target, distance_limit)
if source == target
return 0
end
m = source.size
n = target.size
if (m - n).abs > distance_limit
return 100
end
inf = m + n
h = Array.new(m + 2) { |i|
a = Array.new(n + 2, 0)
a[0] = inf
a[1] = i
a
}
h1 = h[1]
h0 = h[0]
(0..n).each do |i|
h1[i + 1] = i
h0[i + 1] = inf
end
sd = {}
(1..m).each do |i|
db = 0
hi = h[i]
hi1 = h[i + 1]
weight = calc_weight(i - 1, m)
c1 = source[i - 1].downcase
(1..n).each do |j|
i1 = sd[target[j - 1]] || 0
j1 = db
c2 = target[j - 1]
if c1 == c2.downcase
hi1[j + 1] = hi[j]
db = j
else
hi1[j + 1] = [hi[j], hi1[j], hi[j + 1]].min + 1 * weight
end
hi1[j + 1] = [hi1[j + 1], h[i1][j1] + ((i - i1 - 1) + 1 + (j - j1 - 1)) * weight].min
end
sd[source[i - 1]] = i
end
h[m + 1][n + 1]
end
end
class Object
def method_missing(name, *args)
matched_method = []
name = name.to_s
public_methods.each { |method|
score = HAL.strings_distance(name, method.to_s, 2)
matched_method.push([score, method]) if score <= 2
}
matched_method.sort! { |a, b|
a[0] <=> b[0]
}
if matched_method.size > 0
public_send(matched_method[0][1], *args)
else
raise NoMethodError, "undefined method `#{name}'"
end
end
end
require "./HAL"
class Test
def say_hello
puts "hello"
end
end
test = Test.new
test.say_helo
# > "hello"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment