Here's a solution that not only addresses all the fixes, but uses a much better algorithm. (It's speed is bound by sort instead of O(N2).)

#!/usr/bin/perl # # The name of the file containing the data is specified as an argument +. # Alternatively, the data may passed via STDIN. # The data consist of mulitple records, one per line. # Each record has two columns: a network address and its mask. # The columns are seperated by whitespace. # Lines containing only whitespace are ignored. # Comments (anything after a "#") are ignored. # # # Example # ------- # # This is a sample data file. # # 10.0.0.0 255.255.255.0 # Overlaps with 4, 5 & 6 # 10.0.0.0 255.255.255.128 # Overlaps with 5 & 6 # 10.0.0.0 255.255.255.192 # 10.0.0.64 255.255.255.192 # # 11.0.0.0 255.255.255.0 # 11.0.1.0 255.255.255.0 # 11.0.2.0 255.255.254.0 # Overlaps with 11 # 11.0.3.0 255.255.255.0 # 11.0.4.0 255.255.255.0 # # 12.0.0.0 255.255.255.0 # Overlaps with 15 # 12.0.0.1 255.255.255.0 # use strict; use warnings; sub packip4 { return unpack('N', (pack 'C4', split(/\./, shift))); } sub unpackip4 { return join('.', unpack('C4', pack('N', shift))); } sub format_rec { my $rec = @_ ? $_[0] : $_; return sprintf('%s/%s (line %d)', unpackip4($rec->[0]), unpackip4($rec->[1]), $rec->[2], ); } sub overlap { my ($overlaps, $r1, $r2) = @_; if ($r1->[2] > $r2->[2]) { ($r1, $r2) = ($r2, $r1) } push @$overlaps, [ $r1, $r2 ]; } { my @recs; { while (<>) { s/#.*//; s/\s+\z//; next if !length; my ($net, $mask) = split /\s+/; $net = packip4($net); $mask = packip4($mask); my $first = $net & $mask; my $last = $net | ~$mask; push @recs, [ $first, $last, $. ]; } } my @overlaps; if (@recs) { @recs = sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1] } @rec +s; my $crushed = shift @recs; my @components = ( $crushed ); while (@recs) { my $rec = shift @recs; if ($rec->[0] gt $crushed->[1]) { $crushed = $rec; @components = ( $rec ); next; } foreach my $component (@components) { next if $component->[0] gt $rec->[1] || $component->[1] lt $rec->[0]; overlap(\@overlaps, $rec, $component); } $crushed = [ $crushed->[0], ( $crushed->[1] gt $rec->[1] ? $crushed->[1] : $rec->[1] ) ]; push @components, $rec; } } print map { sprintf("%s overlaps %s\n", map format_rec, @$_) } sort { $a->[0][2] <=> $b->[0][2] || $a->[1][2] <=> $b->[1][2] + } @overlaps; }

In reply to Re: Subnet Overlap (fixes) by ikegami
in thread Subnet Overlap by bfarley

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.