Canonicalize CIDR: Difference between revisions
Content added Content deleted
m (→{{header|Lua}}) |
(Python alternative) |
||
Line 1,384: | Line 1,384: | ||
<pre>$ canonicalize_cidr.py 87.70.141.1/22 |
<pre>$ canonicalize_cidr.py 87.70.141.1/22 |
||
87.70.140.0/22</pre> |
87.70.140.0/22</pre> |
||
===Bit mask and shift=== |
|||
<lang python>"""Canonicalize CIDR""" |
|||
DIGITS = (24, 16, 8, 0) |
|||
def dotted_to_int(dotted: str) -> int: |
|||
digits = [int(digit) for digit in dotted.split(".")] |
|||
return sum(a << b for a, b in zip(digits, DIGITS)) |
|||
def int_to_dotted(ip: int) -> str: |
|||
digits = [(ip & (255 << d)) >> d for d in DIGITS] |
|||
return ".".join(str(d) for d in digits) |
|||
def network_mask(number_of_bits: int) -> int: |
|||
return ((1 << number_of_bits) - 1) << (32 - number_of_bits) |
|||
def canonicalize(ip: str) -> str: |
|||
dotted, network_bits = ip.split("/") |
|||
i = dotted_to_int(dotted) |
|||
mask = network_mask(int(network_bits)) |
|||
return int_to_dotted(i & mask) + "/" + network_bits |
|||
TEST_CASES = [ |
|||
("36.18.154.103/12", "36.16.0.0/12"), |
|||
("62.62.197.11/29", "62.62.197.8/29"), |
|||
("67.137.119.181/4", "64.0.0.0/4"), |
|||
("161.214.74.21/24", "161.214.74.0/24"), |
|||
("184.232.176.184/18", "184.232.128.0/18"), |
|||
] |
|||
if __name__ == "__main__": |
|||
for ip, expect in TEST_CASES: |
|||
rv = canonicalize(ip) |
|||
print(f"{ip:<18} -> {rv}") |
|||
assert rv == expect |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
36.18.154.103/12 -> 36.16.0.0/12 |
|||
62.62.197.11/29 -> 62.62.197.8/29 |
|||
67.137.119.181/4 -> 64.0.0.0/4 |
|||
161.214.74.21/24 -> 161.214.74.0/24 |
|||
184.232.176.184/18 -> 184.232.128.0/18 |
|||
</pre> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |