Begin forwarded message:

> From: "Adam Shelly" <adam.shelly / gmail.com>
> Date: September 15, 2007 3:27:43 AM CDT
> To: submission / rubyquiz.com
> Subject: Re: [QUIZ] IP to Country (#139) - early submission, please  
> forward after deadline
>
> On 9/14/07, Ruby Quiz <james / grayproductions.net> wrote:
>> This week's Ruby Quiz is to write a simple utility.  Your program  
>> should accept
>> an IP address as a command-line argument and print out the two  
>> letter code for
>> the country that IP is assigned in.  You can find a database for  
>> the matching
>
> Hi James,
> I'm going to be offline for the next few days, so please accept my
> early submission to forward after the deadline.
> Thanks,
> -Adam.
>
> -------------------------------
>
> Here's my quickly created version that works off the unmodified file
> without any initialization.
>
> --- IpToCountry.rb --
>
> #Use this function to find the first and last record of the file.
> #I ran this once and  hardcoded the values in order to improve  
> execution time
> #It was run against file dated Fri Sep 14 12:08:01 2007 UTC.
> #It should be run again if the database changes
>
> def find_valid_data filename
>   start = 0
>   dbfile = File.new(filename)
>   s = dbfile.gets
>   while s[0] == ?# or s[0]==?\n
>     start+= s.size
>     s = dbfile.gets
>   end
>   dbfile.seek(-128, File::SEEK_END)
>   s = dbfile.read(128).chomp;
>   last = s.rindex("\n");
>   dbfile.close
>   return [start-1,File.size(filename) - last]
> end
>
>
> def addr_to_i addr
>   radix = 256**4
>   addr.split('.').inject(0){|sum,part| sum + part.to_i * (radix / 
> =256)}
> end
>
>
> def bsearch_file value, min, max
>   return "Not Found" if max<=min
>   point = (max-min)/2 + min
>   DBFile.seek(point-1, File::SEEK_SET)
>   DBFile.gets                                      #get partial line
>   line = DBFile.gets
>   rec = line.split('"')
>   range = (rec[1].to_i ..  rec[3].to_i)
>   #puts "searching #{point}: range = (#{range})"
>   return rec[9] if range.include? value
>   if value < range.first
>     #p "lower"
>     return bsearch_file(value, min, point-2)
>   else
>     #p "higher"
>     return bsearch_file(value,point+line.size,max)
>   end
> end
>
>
> DBFilename = "IpToCountry.csv"
> #
> # datarange = find_valid_data DBFilename
> #
> datarange = [6604,5788762]
>
> DBFile = File.new(DBFilename)
>
> addr_n = addr_to_i(ARGV[0]||"123.45.67.89")
> puts bsearch_file(addr_n, *datarange)