Skip to content

Instantly share code, notes, and snippets.

@edk0
Last active March 31, 2019 04:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edk0/b22431299f34609c7f46d2839d803d41 to your computer and use it in GitHub Desktop.
Save edk0/b22431299f34609c7f46d2839d803d41 to your computer and use it in GitHub Desktop.
from ipaddress import ip_address, ip_network, summarize_address_range, collapse_addresses
from itertools import chain
import sys
def parse_net_or_range(s):
if '-' in s:
start, end = s.split('-', 1)
start = ip_address(start)
end = ip_address(end)
return summarize_address_range(start, end)
return [ip_network(s)]
def smallest_containing_net(a, b):
while not a.supernet_of(b):
a = a.supernet()
return a
def merge_cost(a, b):
return smallest_containing_net(a, b).num_addresses - a.num_addresses - b.num_addresses
def main(args):
_, *args = args
addrs = list(collapse_addresses(chain.from_iterable(map(parse_net_or_range, args))))
ads = set(addrs)
gaps = sorted((merge_cost(a, b), a, b) for a, b in zip(addrs, addrs[1:]))
merged = []
n = len(ads)
while gaps:
_, a, b = gaps.pop(0)
merged.append(smallest_containing_net(a, b))
ads.discard(a)
ads.discard(b)
l = list(collapse_addresses(chain(merged, ads)))
if len(l) < n:
print('%d:' % len(l))
print('\t' + ' '.join(str(n) for n in l))
n = len(l)
if __name__ == '__main__':
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment