From: Eugene Kalenkovich Date: 2007-09-17T03:05:17+09:00 Subject: Re: [QUIZ] IP to Country (#139) My solution suffers from over-generality (is supposed to work for any sorted string file by any sorting criteria), and from over-limiting memory usage - I like Simon's approach, reading in chunks makes everything easier and faster. BTW, all solutions already submitted will lie for subnets 1,2 and 5 :) Most (but not all) will break on out of bounds submissions (256.256.256.256 or 0.0.0.-1, latter if comments are stripped out) (yes, I know, just trying to find an excuse for not very elegant solution - edge cases kill elegancy :) >----------------------------------------------------------------------------- def bin_find(file,search) if block_given? compare = lambda { |a, b| yield(a, b) } else compare = lambda { |a, b| a <=> b } end open(file) do |f| return bin_search(f,search,f.lstat.size,&compare) end end def bin_search(f,search,size) start,finish=0,size while start0 break when 0 return l1 else case (l2=f.readline.chomp rescue false) ? yield(search,l2) : -1 when -1 return l1 when 0 return l2 else start+=dist; next end end end nil end nums=[] out=true if ARGV[0]=='test' n=ARGV[1].to_i n.times{nums << rand(4294967296)} out=false else ARGV.each do |argv| nums << ((($1.to_i*256)+$2.to_i)*256+$3.to_i)*256+$4.to_i if argv=~/(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})/ end end if nums.empty? puts "Please enter valid ip(s) (or use '#{$0} test NNN' for testing)" exit end nums.each do |num| ctry='Unknown' res=bin_find('IpToCountry.csv',num) { |search, str| str.empty? || str[0,1]!='"' ? 1 : search <=> str.gsub('"','').split(',')[0].to_i }.gsub('"','').split(',') ctry=res[4] if (res[0].to_i..res[1].to_i)===num puts ctry if out end