Input files:
Call the script as:
./whois.p6 ips10k.txt query10k.txt
PS: It's for this programming challange.
Input files:
Call the script as:
./whois.p6 ips10k.txt query10k.txt
PS: It's for this programming challange.
sub ip-to-number ($ip) { | |
do given $ip.split('.') { | |
.[0] +< 24 + | |
.[1] +< 16 + | |
.[2] +< 8 + | |
.[3] +< 0 | |
} | |
} | |
class IntervalTree { | |
has $.min; | |
has $.max; | |
has $!center = ($!min + $!max) div 2; | |
has @!intervals; | |
has IntervalTree $!left; | |
has IntervalTree $!right; | |
method new ($min, $max) { self.bless(:$min, :$max) } | |
method insert (|c ($start, $end, $name)) { | |
if $end < $!center and $!min < $!center - 1 { | |
($!left //= self.new($!min, $!center)).insert(|c) | |
} | |
elsif $start > $!center and $!max > $!center { | |
($!right //= self.new($!center, $!max)).insert(|c) | |
} | |
else { | |
@!intervals.push: [$start, $end, $name, $end-$start] | |
} | |
} | |
method prepare { | |
@!intervals.=sort(*[3]); | |
$!left .prepare if $!left; | |
$!right.prepare if $!right; | |
} | |
method lookup ($n) { | |
my $best = ($n < $!center ?? ($!left .lookup($n) if $!left) | |
!! ($!right.lookup($n) if $!right)); | |
$best ?? @!intervals.first({ return $best if .[3] > $best[3]; | |
.[0] <= $n <= .[1] }) // $best | |
!! @!intervals.first({ .[0] <= $n <= .[1] }) | |
} | |
} | |
sub MAIN ($ip-file, $query-file) { | |
my $index = IntervalTree.new(0, ip-to-number '255.255.255.255'); | |
for $ip-file.IO.lines { | |
my ($start, $end, $name) = .split(' ', 3); | |
$index.insert(ip-to-number($start), ip-to-number($end), $name); | |
} | |
$index.prepare; | |
for $query-file.IO.lines -> $ip { | |
my $name = $index.lookup(ip-to-number $ip)[2]; | |
say "$ip {$name // '<unknown>'}"; | |
} | |
} |