Last active
May 14, 2020 18:28
-
-
Save sorrat/90fe88b7f42db53267dde2497c302bcd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Поиск минимальной подсети, содержащей заданный набор IP-адресов. | |
""" | |
import unittest | |
import struct | |
import socket | |
def ip_to_bin(ip) -> str: | |
ip_packed = socket.inet_aton(ip) | |
ip_int = struct.unpack('!I', ip_packed)[0] | |
return bin(ip_int)[2:].rjust(32, '0') | |
def bin_to_ip(ip_bin) -> str: | |
ip_int = int(ip_bin, 2) | |
ip_packed = struct.pack('!I', ip_int) | |
ip = socket.inet_ntoa(ip_packed) | |
return ip | |
def get_common_prefix(iterables) -> list: | |
prefix = [] | |
for elems in zip(*iterables): | |
if len(set(elems)) == 1: | |
prefix.append(elems[0]) | |
else: | |
break | |
return prefix | |
def get_min_subnet(ips) -> str: | |
"""Минимальная подсеть, содержащая адреса ips""" | |
subnet_bin_prefix = get_common_prefix(map(ip_to_bin, ips)) | |
subnet_bin_ip = ''.join(subnet_bin_prefix).ljust(32, '0') | |
subnet_id = '%s/%s' % (bin_to_ip(subnet_bin_ip), len(subnet_bin_prefix)) | |
return subnet_id | |
class TestMinSubnet(unittest.TestCase): | |
def test_get_min_subnet(self): | |
test_cases = [ | |
('10.10.0.1/32', [ | |
'10.10.0.1', | |
]), | |
('10.10.0.2/31', [ | |
'10.10.0.2', | |
'10.10.0.3', | |
]), | |
('10.10.0.4/30', [ | |
'10.10.0.5', | |
'10.10.0.6', | |
]), | |
('10.10.0.0/29', [ | |
'10.10.0.3', | |
'10.10.0.4', | |
]), | |
('10.10.0.16/28', [ | |
'10.10.0.17', | |
'10.10.0.24', | |
]), | |
('10.10.0.128/25', [ | |
'10.10.0.130', | |
'10.10.0.200', | |
]), | |
('10.10.0.0/24', [ | |
'10.10.0.5', | |
'10.10.0.128', | |
]), | |
('10.10.0.0/16', [ | |
'10.10.10.0', | |
'10.10.128.2', | |
]), | |
('10.0.0.0/8', [ | |
'10.0.1.1', | |
'10.240.1.2', | |
]), | |
('0.0.0.0/0', [ | |
'0.1.0.0', | |
'240.10.1.2', | |
]), | |
] | |
for i, (expected, inp) in enumerate(test_cases): | |
with self.subTest(i=i, expected=expected, input=inp): | |
subnet_id = get_min_subnet(inp) | |
self.assertEqual(subnet_id, expected) | |
if __name__ == '__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment