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 d514d4f5e0 - Show all commits
+52
View File
6
@@ -3,6 +3,7 @@ from ipaddress import IPv4Address
from typing import List, Tuple from typing import List, Tuple
from itertools import groupby from itertools import groupby
from collections import defaultdict from collections import defaultdict
import cProfile
def get_data(input_file): def get_data(input_file):
@@ -70,6 +71,49 @@ def rough_merge_binaries(binaries: List[str], req_len: int) -> List[str]:
return sorted(ips) return sorted(ips)
def smooth_merge_binaries(binaries: List[str], req_len: int) -> List[str]:
non_reducible_ips = set()
ips = set()
for ip in binaries:
if "1" not in reduce_binary(ip):
non_reducible_ips.add(ip)
else:
ips.add(ip)
while len(ips) > 0 and len(ips) + len(non_reducible_ips) > req_len:
print(f"{req_len=} {len(ips) + len(non_reducible_ips)=}")
group_dict = defaultdict(list)
for ip in ips:
group_dict[ip.rfind("1")].append(ip)
max_len = max(group_dict)
lst = group_dict[max_len]
for x, y in zip(lst, lst[1:]):
i = x.rfind("1")
if y.startswith(x[:i]):
ips.remove(x)
ips.remove(y)
ips.add(reduce_binary(x))
break
else:
x = lst[0]
ips.remove(x)
ips.add(reduce_binary(x))
_ips = ips | non_reducible_ips
non_reducible_ips = set()
ips = set()
for ip in _ips:
if "1" not in reduce_binary(ip):
non_reducible_ips.add(ip)
else:
ips.add(ip)
ips.update(non_reducible_ips)
return sorted(ips)
def main(): def main():
file = "cidr4.txt" file = "cidr4.txt"
required_len = 20 required_len = 20
@@ -82,6 +126,13 @@ def main():
for ip in rough_merged_bin_ips: for ip in rough_merged_bin_ips:
print(ip) print(ip)
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)
if __name__ == "__main__": if __name__ == "__main__":
assert cidr4_to_binary("4.78.139.0/24") == "00000100010011101000101100000000" assert cidr4_to_binary("4.78.139.0/24") == "00000100010011101000101100000000"
@@ -103,3 +154,4 @@ if __name__ == "__main__":
assert reduce_binary("00000000000010000000000000000000") == "0" * 32 assert reduce_binary("00000000000010000000000000000000") == "0" * 32
main() main()
# cProfile.run("main()")