Cidr4 merge algorithm #5
@@ -4,7 +4,7 @@ from vpn_manager.cidr4_merge.cidr4_merger import (
|
|||||||
find_neighbors,
|
find_neighbors,
|
||||||
find_parent,
|
find_parent,
|
||||||
make_cidr4,
|
make_cidr4,
|
||||||
merge_two_nodes,
|
merge_nodes,
|
||||||
solution,
|
solution,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -62,13 +62,13 @@ def test_calc_dip():
|
|||||||
assert calc_dip(3, 3, 1) == 2**30
|
assert calc_dip(3, 3, 1) == 2**30
|
||||||
|
|
||||||
|
|
||||||
def test_merge_two_nodes():
|
def test_merge_nodes():
|
||||||
assert merge_two_nodes((0, 32), (1, 32)) == ((0, 31), 0)
|
assert merge_nodes((0, 32), (1, 32)) == ((0, 31), 0)
|
||||||
assert merge_two_nodes((0, 32), (2, 32)) == ((0, 30), 2)
|
assert merge_nodes((0, 32), (2, 32)) == ((0, 30), 2)
|
||||||
assert merge_two_nodes((0, 32), (5, 32)) == ((0, 29), 6)
|
assert merge_nodes((0, 32), (5, 32)) == ((0, 29), 6)
|
||||||
assert merge_two_nodes((3, 32), (4, 32)) == ((0, 29), 6)
|
assert merge_nodes((3, 32), (4, 32)) == ((0, 29), 6)
|
||||||
assert merge_two_nodes((0, 32), (4, 30)) == ((0, 29), 3)
|
assert merge_nodes((0, 32), (4, 30)) == ((0, 29), 3)
|
||||||
assert merge_two_nodes((0, 32), (6, 31)) == ((0, 29), 5)
|
assert merge_nodes((0, 32), (6, 31)) == ((0, 29), 5)
|
||||||
|
|
||||||
|
|
||||||
def test_find_neighbors():
|
def test_find_neighbors():
|
||||||
@@ -96,7 +96,7 @@ def test_find_neighbors():
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_merge_nodes():
|
def test_solution():
|
||||||
assert solution(
|
assert solution(
|
||||||
[
|
[
|
||||||
(0, 32),
|
(0, 32),
|
||||||
|
|||||||
@@ -9,6 +9,34 @@ class Cidr4MergerError(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def find_subnets(nodes: list[Node]) -> list[tuple[Node, Node]]:
|
||||||
|
subnets = []
|
||||||
|
for i, (a, b) in enumerate(zip(nodes, nodes[1:])):
|
||||||
|
parent_node, dip = merge_nodes(a, b)
|
||||||
|
if parent_node == a or parent_node == b:
|
||||||
|
subnets.append((a, b))
|
||||||
|
return subnets
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_no_subnets(nodes: list[Node]):
|
||||||
|
if subnets := find_subnets(nodes):
|
||||||
|
raise Cidr4MergerError(f"There are subnets! {subnets=}")
|
||||||
|
|
||||||
|
|
||||||
|
def find_neighbors(nodes: list[Node]) -> list[tuple[int, Node, Node]]:
|
||||||
|
neighbors = []
|
||||||
|
for i, (a, b) in enumerate(zip(nodes, nodes[1:])):
|
||||||
|
parent_node, dip = merge_nodes(a, b)
|
||||||
|
if parent_node[1] + 1 == a[1] == b[1]:
|
||||||
|
neighbors.append((i, a, b))
|
||||||
|
return neighbors
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_no_neighbors(nodes: list[Node]):
|
||||||
|
if neighbors := find_neighbors(nodes):
|
||||||
|
raise Cidr4MergerError(f"There are neighbors! {neighbors=}")
|
||||||
|
|
||||||
|
|
||||||
def find_parent(a: Node, b: Node) -> Node:
|
def find_parent(a: Node, b: Node) -> Node:
|
||||||
ia, la = a
|
ia, la = a
|
||||||
ib, lb = b
|
ib, lb = b
|
||||||
@@ -31,7 +59,7 @@ def calc_dip(la: int, lb: int, lp: int) -> int:
|
|||||||
return dip(la, lp) + dip(lb, lp)
|
return dip(la, lp) + dip(lb, lp)
|
||||||
|
|
||||||
|
|
||||||
def merge_two_nodes(a: Node, b: Node) -> tuple[Node, int]:
|
def merge_nodes(a: Node, b: Node) -> tuple[Node, int]:
|
||||||
p = find_parent(a, b)
|
p = find_parent(a, b)
|
||||||
dip = calc_dip(a[1], b[1], p[1])
|
dip = calc_dip(a[1], b[1], p[1])
|
||||||
return p, dip
|
return p, dip
|
||||||
@@ -42,7 +70,7 @@ def solution(nodes: list[Node], req_len: int) -> tuple[list[Node], int]:
|
|||||||
while len(nodes) > req_len:
|
while len(nodes) > req_len:
|
||||||
min_t = None, None, float("inf")
|
min_t = None, None, float("inf")
|
||||||
for i, (a, b) in enumerate(zip(nodes, nodes[1:])):
|
for i, (a, b) in enumerate(zip(nodes, nodes[1:])):
|
||||||
p, dip = merge_two_nodes(a, b)
|
p, dip = merge_nodes(a, b)
|
||||||
if dip < min_t[2]:
|
if dip < min_t[2]:
|
||||||
min_t = i, p, dip
|
min_t = i, p, dip
|
||||||
i, p, dip = min_t
|
i, p, dip = min_t
|
||||||
@@ -51,41 +79,13 @@ def solution(nodes: list[Node], req_len: int) -> tuple[list[Node], int]:
|
|||||||
|
|
||||||
while nbs := find_neighbors(nodes):
|
while nbs := find_neighbors(nodes):
|
||||||
i, a, b = nbs[0]
|
i, a, b = nbs[0]
|
||||||
p, dip = merge_two_nodes(a, b)
|
p, dip = merge_nodes(a, b)
|
||||||
nodes = nodes[:i] + [p] + nodes[i + 2 :]
|
nodes = nodes[:i] + [p] + nodes[i + 2 :]
|
||||||
sum_dip += dip
|
sum_dip += dip
|
||||||
|
|
||||||
return nodes, sum_dip
|
return nodes, sum_dip
|
||||||
|
|
||||||
|
|
||||||
def find_subnets(nodes: list[Node]) -> list[tuple[Node, Node]]:
|
|
||||||
subnets = []
|
|
||||||
for i, (a, b) in enumerate(zip(nodes, nodes[1:])):
|
|
||||||
parent_node, dip = merge_two_nodes(a, b)
|
|
||||||
if parent_node == a or parent_node == b:
|
|
||||||
subnets.append((a, b))
|
|
||||||
return subnets
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_no_subnets(nodes: list[Node]):
|
|
||||||
if subnets := find_subnets(nodes):
|
|
||||||
raise Cidr4MergerError(f"There are subnets! {subnets=}")
|
|
||||||
|
|
||||||
|
|
||||||
def find_neighbors(nodes: list[Node]) -> list[tuple[int, Node, Node]]:
|
|
||||||
neighbors = []
|
|
||||||
for i, (a, b) in enumerate(zip(nodes, nodes[1:])):
|
|
||||||
parent_node, dip = merge_two_nodes(a, b)
|
|
||||||
if parent_node[1] + 1 == a[1] == b[1]:
|
|
||||||
neighbors.append((i, a, b))
|
|
||||||
return neighbors
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_no_neighbors(nodes: list[Node]):
|
|
||||||
if neighbors := find_neighbors(nodes):
|
|
||||||
raise Cidr4MergerError(f"There are neighbors! {neighbors=}")
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
required_len = 20
|
required_len = 20
|
||||||
data = get_data()
|
data = get_data()
|
||||||
|
|||||||
Reference in New Issue
Block a user