Cidr4 merge algorithm #5

Merged
PavelPatsey merged 91 commits from CIDR4_merge_algorithm into main 2025-01-27 22:05:39 +03:00
Showing only changes of commit 7d89eee92f - Show all commits
+37 -20
View File
6
@@ -37,37 +37,41 @@ def reduce_binary(binary: str) -> str:
return binary[:vlsm] + "0" + binary[vlsm + 1 :] return binary[:vlsm] + "0" + binary[vlsm + 1 :]
def get_mask(binary: str) -> str:
i = binary.rfind("1")
return binary[: i + 1]
def rough_merge_binaries(binaries: List[str], req_len: int) -> List[str]: def rough_merge_binaries(binaries: List[str], req_len: int) -> List[str]:
ips = set(deepcopy(binaries)) ips = set(deepcopy(binaries))
non_reducible_ips = set()
reduction_limit_reached = False reduction_limit_reached = False
max_vlsm = float("inf") max_vlsm = float("inf")
while ( while len(ips) > req_len and not reduction_limit_reached and max_vlsm != -1:
len(ips) > 0
and len(ips) + len(non_reducible_ips) > req_len
and not reduction_limit_reached
and max_vlsm != -1
):
ip_with_max_vlsm = max(ips, key=lambda x: x.rfind("1")) ip_with_max_vlsm = max(ips, key=lambda x: x.rfind("1"))
max_vlsm = ip_with_max_vlsm.rfind("1") max_vlsm = ip_with_max_vlsm.rfind("1")
reduced_ips = set() reduced_ips = set()
merged_ips = set() merged_ips = set()
for ip in ips: for ip in ips:
if ip.rfind("1") == max_vlsm: if ip.rfind("1") == max_vlsm:
reduced_ip = reduce_binary(ip) reduced_ips.add(reduce_binary(ip))
if "1" in reduced_ip:
reduced_ips.add(reduced_ip)
else:
non_reducible_ips.add(ip)
else: else:
merged_ips.add(ip) merged_ips.add(ip)
filtered_set = set()
for r_ip in reduced_ips:
mask = get_mask(r_ip)
for ip in merged_ips:
if ip.startswith(mask):
filtered_set.add(r_ip)
reduced_ips -= filtered_set
merged_ips.update(reduced_ips) merged_ips.update(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
ips.update(non_reducible_ips)
return sorted(ips) return sorted(ips)
@@ -81,7 +85,7 @@ def smooth_merge_binaries(binaries: List[str], req_len: int) -> List[str]:
ips.add(ip) ips.add(ip)
while len(ips) > 0 and len(ips) + len(non_reducible_ips) > req_len: while len(ips) > 0 and len(ips) + len(non_reducible_ips) > req_len:
print(f"{req_len=} {len(ips) + len(non_reducible_ips)=}") # print(f"{req_len=} {len(ips) + len(non_reducible_ips)=}")
group_dict = defaultdict(list) group_dict = defaultdict(list)
for ip in ips: for ip in ips:
@@ -120,18 +124,26 @@ def main():
data = get_data(file) data = get_data(file)
bin_ips = list(map(cidr4_to_binary, data)) bin_ips = list(map(cidr4_to_binary, data))
# for ip in bin_ips:
# print(ip)
# print("#" * 128)
rough_merged_bin_ips = rough_merge_binaries(bin_ips, required_len) 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)=}")
for ip in rough_merged_bin_ips: for ip in rough_merged_bin_ips:
print(ip) print(ip)
print("#" * 128) # print("#" * 128)
#
# smooth_merged_bin_ips = smooth_merge_binaries(rough_merged_bin_ips, required_len)
# print(f"{len(smooth_merged_bin_ips)=}")
# for ip in smooth_merged_bin_ips:
# print(ip)
smooth_merged_bin_ips = smooth_merge_binaries(rough_merged_bin_ips, required_len) # smooth_merged_bin_ips = smooth_merge_binaries(bin_ips, required_len)
print(f"{len(smooth_merged_bin_ips)=}") # print(f"{len(smooth_merged_bin_ips)=}")
for ip in smooth_merged_bin_ips: # for ip in smooth_merged_bin_ips:
print(ip) # print(ip)
if __name__ == "__main__": if __name__ == "__main__":
@@ -153,5 +165,10 @@ if __name__ == "__main__":
assert reduce_binary("0" * 32) == "0" * 32 assert reduce_binary("0" * 32) == "0" * 32
assert reduce_binary("00000000000010000000000000000000") == "0" * 32 assert reduce_binary("00000000000010000000000000000000") == "0" * 32
assert get_mask("00000100010011101000101100000000") == "000001000100111010001011"
assert get_mask("10000000000000000000000000000000") == "1"
assert get_mask("00000000000000000000000000000000") == ""
assert get_mask("00000000000010000000000000000000") == "0000000000001"
main() main()
# cProfile.run("main()") # cProfile.run("main()")