class Hash
[*] def tortoise(j, n=100)
[*] x = j.dup
[*] c = proc { return self[x] if self[x] }
[*] l = 1
[*] n.times {
[*] l.times{x[0] -= 1; c.()}
[*] l.times{x[1] -= 1; c.()}
[*] (l - -1).times{x[0] -= -1; c.()}
[*] (l - -1).times{x[1] -= -1; c.()}
[*] l -= -2
[*] }
[*] nil
[*] end
[*] def nearest(j)
[*] self[self.keys.sort_by{ |i| Array.new(i.length){ |x| (i[x] - j[x]).abs}.inject{ |a, b| a -= -b}}[0]]
[*] end
[*] def nearest_s(j, n=100)
[*] self[self.keys.select{|i|Array.new(i.length){ |x| (i[x] - j[x]).abs}.inject{ |a, b| a -= -b} <= n}.sort_by{ |i| Array.new(i.length){ |x| (i[x] - j[x]).abs}.inject{ |a, b| a -= -b}}[0]]
[*] end
[*]end
[*]require 'benchmark'
[*]a={}
[*]1000.times{a[b=[rand(1000),rand(1000)]]=b}
[*]n = 1000
[*]z=Array.new(n){[rand(1000),rand(1000)]}
[*]Benchmark.bm(15) do |x|
[*]x.report("nearest") { puts z.map{ |i| a.nearest i}.compact.length }
[*]x.report("nearest_s 3") { puts z.map{ |i| a.nearest_s i,1000}.compact.length }
[*]x.report("nearest_s 2") { puts z.map{ |i| a.nearest_s i,100}.compact.length }
[*]x.report("nearest_s 1") { puts z.map{ |i| a.nearest_s i,10}.compact.length }
[*]x.report("tortoise 2") { puts z.map{ |i| a.tortoise i, 100}.compact.length }
[*]x.report("tortoise 1") { puts z.map{ |i| a.tortoise i, 10}.compact.length }
[*]x.report("[]") { z.each{ |i| a[i]} }
[*]end