Skip to content

Instantly share code, notes, and snippets.

@upsuper
Created April 10, 2013 03:22
Show Gist options
  • Save upsuper/5351509 to your computer and use it in GitHub Desktop.
Save upsuper/5351509 to your computer and use it in GitHub Desktop.
Simplify IP segments by removing redundant segments and merging adjacent segments.
# coding: UTF-8
import socket
import struct
def aton(addr):
return struct.unpack('!l', socket.inet_aton(addr))
def ntoa(addr):
return socket.inet_ntoa(struct.pack('!l', addr))
def mask_bits(mask):
return ((1 << mask) - 1) << (32 - mask)
def simplify(ips):
addrs = []
# parse ip segments
for ip in ips:
if ip.find('/') == -1:
addr, mask = ip, '32'
else:
addr, mask = ip.split('/')
addr, = struct.unpack('!l', socket.inet_aton(addr))
mask = int(mask)
addr &= mask_bits(mask)
addrs.append((addr, mask))
if len(addrs) == 0:
return []
# remove redundant segments
addrs.sort()
result = [addrs[0]]
for addr, mask in addrs[1:]:
pre_addr, pre_mask = result[-1]
if addr & mask_bits(pre_mask) != pre_addr:
result.append((addr, mask))
addrs = result
# merge adjacent segments
changed = True
while changed:
changed = False
result = [addrs[0]]
for addr, mask in addrs[1:]:
pre_addr, pre_mask = result[-1]
if mask != pre_mask or \
addr - pre_addr != 1 << (32 - mask):
result.append((addr, mask))
else:
new_mask = mask - 1
new_addr = addr & mask_bits(new_mask)
result[-1] = (new_addr, new_mask)
changed = True
addrs = result
# format ip segments again
result = []
for addr, mask in addrs:
addr = ntoa(addr)
if mask == 32:
result.append(addr)
else:
result.append('%s/%d' % (addr, mask))
return result
if __name__ == '__main__':
import sys
ips = []
for line in sys.stdin:
line = line.strip()
if line:
ips.append(line)
print
print '\n'.join(simplify(ips))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment