refactoring: represent binary as a string of vlsm length
This commit is contained in:
+56
-43
@@ -9,77 +9,90 @@ def get_data(input_file):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def cidr4_to_binary(cidr4: str) -> Tuple[str, int]:
|
def cidr4_to_binary(cidr4: str) -> str:
|
||||||
ip_str, vlsm = cidr4.strip().split("/")
|
ip_str, vlsm = cidr4.strip().split("/")
|
||||||
vlsm = int(vlsm)
|
vlsm = int(vlsm)
|
||||||
ipv4 = IPv4Address(ip_str)
|
ipv4 = IPv4Address(ip_str)
|
||||||
binary_ip = bin(int(ipv4))[2:]
|
binary_ip = bin(int(ipv4))[2:]
|
||||||
binary_ip = binary_ip.zfill(32)
|
binary_ip = binary_ip.zfill(32)
|
||||||
return binary_ip, vlsm
|
binary = binary_ip[:vlsm]
|
||||||
|
return binary
|
||||||
|
|
||||||
|
|
||||||
def binary_to_cidr4(binary_ip: str, vlsm: int) -> str:
|
def binary_to_cidr4(binary: str) -> str:
|
||||||
|
vlsm = len(binary)
|
||||||
|
binary_ip = binary + "0" * (32 - vlsm)
|
||||||
int_ip = int(binary_ip, 2)
|
int_ip = int(binary_ip, 2)
|
||||||
ip_str = str(IPv4Address(int_ip))
|
ip = IPv4Address(int_ip)
|
||||||
return f"{ip_str}/{vlsm}"
|
return f"{ip}/{vlsm}"
|
||||||
|
|
||||||
|
|
||||||
def reduce_bin_ip(bin_ip: str, vlsm: int) -> Tuple[str, int]:
|
def reduce_binary(binary: str) -> str:
|
||||||
if vlsm == 0:
|
if len(binary) == 0:
|
||||||
return "0" * 32, vlsm
|
return ""
|
||||||
new_vlsm = vlsm - 1
|
new_binary = binary[:-1]
|
||||||
new_bin_ip = bin_ip[:new_vlsm] + "0" * (32 - new_vlsm)
|
if "1" not in new_binary:
|
||||||
if new_bin_ip == "0" * 32:
|
return ""
|
||||||
return "0" * 32, 0
|
return new_binary
|
||||||
return new_bin_ip, new_vlsm
|
|
||||||
|
|
||||||
|
|
||||||
def rough_merge_ips(
|
def rough_merge_binaries(binaries: List[str], req_len: int) -> List[str]:
|
||||||
bin_ips: List[Tuple[str, int]], req_len: int
|
ips = set(deepcopy(binaries))
|
||||||
) -> List[Tuple[str, int]]:
|
non_reducible_ips = set()
|
||||||
ips = deepcopy(bin_ips)
|
|
||||||
reduction_limit_reached = False
|
reduction_limit_reached = False
|
||||||
while len(ips) > req_len and not reduction_limit_reached:
|
while (
|
||||||
max_vlsm = max(ips, key=lambda x: x[1])[1]
|
len(ips) > 0
|
||||||
ips_to_reduce = []
|
and len(ips) + len(non_reducible_ips) > req_len
|
||||||
merged_ips = []
|
and not reduction_limit_reached
|
||||||
for ip_vlsm in ips:
|
):
|
||||||
if ip_vlsm[1] == max_vlsm:
|
max_vlsm = len(max(ips, key=lambda x: len(x)))
|
||||||
ips_to_reduce.append(ip_vlsm)
|
reduced_ips = set()
|
||||||
|
merged_ips = set()
|
||||||
|
for ip in ips:
|
||||||
|
if len(ip) == max_vlsm:
|
||||||
|
reduced_ip = reduce_binary(ip)
|
||||||
|
if len(reduced_ip) > 0:
|
||||||
|
reduced_ips.add(reduced_ip)
|
||||||
else:
|
else:
|
||||||
merged_ips.append(ip_vlsm)
|
non_reducible_ips.add(ip)
|
||||||
reduced_ips = map(lambda x: reduce_bin_ip(*x), ips_to_reduce)
|
else:
|
||||||
reduced_ips = set(reduced_ips)
|
merged_ips.add(ip)
|
||||||
reduced_ips = filter(lambda x: "1" in x[0], reduced_ips)
|
merged_ips.update(reduced_ips)
|
||||||
merged_ips.extend(list(reduced_ips))
|
if len(merged_ips) + len(non_reducible_ips) > req_len:
|
||||||
if len(merged_ips) > req_len:
|
|
||||||
ips = merged_ips
|
ips = merged_ips
|
||||||
else:
|
else:
|
||||||
reduction_limit_reached = True
|
reduction_limit_reached = True
|
||||||
return ips
|
|
||||||
|
ips.update(non_reducible_ips)
|
||||||
|
return sorted(ips)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
file = "cidr4.txt"
|
file = "cidr4.txt"
|
||||||
|
required_len = 20
|
||||||
|
|
||||||
data = get_data(file)
|
data = get_data(file)
|
||||||
bin_ips = list(map(cidr4_to_binary, data))
|
bin_ips = list(map(cidr4_to_binary, data))
|
||||||
rough_merged_bin_ips = rough_merge_ips(bin_ips, 20)
|
rough_merged_bin_ips = rough_merge_binaries(bin_ips, required_len)
|
||||||
print(f"{len(rough_merged_bin_ips)=}")
|
print(f"{len(rough_merged_bin_ips)=}")
|
||||||
sorted_ips = sorted(rough_merged_bin_ips)
|
for ip in rough_merged_bin_ips:
|
||||||
for ip in sorted_ips:
|
|
||||||
print(ip)
|
print(ip)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
assert cidr4_to_binary("4.78.139.0/24") == ("00000100010011101000101100000000", 24)
|
assert cidr4_to_binary("4.78.139.0/24") == "000001000100111010001011"
|
||||||
assert binary_to_cidr4("00000100010011101000101100000000", 24) == "4.78.139.0/24"
|
assert cidr4_to_binary("128.0.0.0/1") == "1"
|
||||||
|
assert cidr4_to_binary("0.0.0.0/0") == ""
|
||||||
|
|
||||||
assert reduce_bin_ip("00000100010011101000101100000000", 24) == (
|
assert binary_to_cidr4("000001000100111010001011") == "4.78.139.0/24"
|
||||||
"00000100010011101000101000000000",
|
assert binary_to_cidr4("1") == "128.0.0.0/1"
|
||||||
23,
|
assert binary_to_cidr4("") == "0.0.0.0/0"
|
||||||
)
|
|
||||||
assert reduce_bin_ip("10000000000000000000000000000000", 1) == ("0" * 32, 0)
|
assert reduce_binary("000001000100111010001011") == "00000100010011101000101"
|
||||||
assert reduce_bin_ip("10000000000000000000000000000000", 0) == ("0" * 32, 0)
|
assert reduce_binary("1") == ""
|
||||||
assert reduce_bin_ip("0" * 32, 0) == ("0" * 32, 0)
|
assert reduce_binary("0") == ""
|
||||||
|
assert reduce_binary("") == ""
|
||||||
|
assert reduce_binary("0001") == ""
|
||||||
|
assert reduce_binary("0000") == ""
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user