Skip to content

Commit 84bb461

Browse files
committed
751 IP to CIDR
1 parent 230c5ff commit 84bb461

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

751 IP to CIDR.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/python3
2+
"""
3+
Given a start IP address ip and a number of ips we need to cover n, return a
4+
representation of the range as a list (of smallest possible length) of CIDR
5+
blocks.
6+
7+
A CIDR block is a string consisting of an IP, followed by a slash, and then the
8+
prefix length. For example: "123.45.67.89/20". That prefix length "20"
9+
represents the number of common prefix bits in the specified range.
10+
11+
Example 1:
12+
Input: ip = "255.0.0.7", n = 10
13+
Output: ["255.0.0.7/32","255.0.0.8/29","255.0.0.16/32"]
14+
Explanation:
15+
The initial ip address, when converted to binary, looks like this (spaces added
16+
for clarity):
17+
255.0.0.7 -> 11111111 00000000 00000000 00000111
18+
The address "255.0.0.7/32" specifies all addresses with a common prefix of 32
19+
bits to the given address,
20+
ie. just this one address.
21+
22+
The address "255.0.0.8/29" specifies all addresses with a common prefix of 29
23+
bits to the given address:
24+
255.0.0.8 -> 11111111 00000000 00000000 00001000
25+
Addresses with common prefix of 29 bits are:
26+
11111111 00000000 00000000 00001000
27+
11111111 00000000 00000000 00001001
28+
11111111 00000000 00000000 00001010
29+
11111111 00000000 00000000 00001011
30+
11111111 00000000 00000000 00001100
31+
11111111 00000000 00000000 00001101
32+
11111111 00000000 00000000 00001110
33+
11111111 00000000 00000000 00001111
34+
35+
The address "255.0.0.16/32" specifies all addresses with a common prefix of 32
36+
bits to the given address,
37+
ie. just 11111111 00000000 00000000 00010000.
38+
39+
In total, the answer specifies the range of 10 ips starting with the address
40+
255.0.0.7 .
41+
42+
There were other representations, such as:
43+
["255.0.0.7/32","255.0.0.8/30", "255.0.0.12/30", "255.0.0.16/32"],
44+
but our answer was the shortest possible.
45+
46+
Also note that a representation beginning with say, "255.0.0.7/30" would be
47+
incorrect,
48+
because it includes addresses like 255.0.0.4 = 11111111 00000000 00000000
49+
00000100
50+
that are outside the specified range.
51+
Note:
52+
ip will be a valid IPv4 address.
53+
Every implied address ip + x (for x < n) will be a valid IPv4 address.
54+
n will be an integer in the range [1, 1000].
55+
"""
56+
from typing import List
57+
58+
59+
# the weights of ip when converting to binary
60+
weights = [
61+
24,
62+
16,
63+
8,
64+
0,
65+
]
66+
67+
68+
class Solution:
69+
def ipToCIDR(self, ip: str, n: int) -> List[str]:
70+
"""
71+
bit manipulation
72+
111, then 32 to cover only one, depends on LSB
73+
Greedy
74+
To cover n, can have representation covers > n
75+
76+
need helper functions, write the main function first
77+
78+
Iterate LSB to the next LSB skipping 1's
79+
num += lsb
80+
"""
81+
num_ip = self.to_bin(ip)
82+
ret = []
83+
while n > 0:
84+
lsb = self.get_lsb(num_ip)
85+
while (1 << lsb) > n:
86+
lsb -= 1
87+
88+
cur_cover = 1 << lsb
89+
n -= cur_cover
90+
ret.append(
91+
self.to_ip(num_ip) + f"/{32-lsb}"
92+
)
93+
num_ip += cur_cover
94+
95+
return ret
96+
97+
def to_bin(self, ip):
98+
ret = 0
99+
for n, w in zip(map(int, ip.split(".")), weights):
100+
ret += n << w
101+
102+
return ret
103+
104+
def to_ip(self, bin):
105+
ret = []
106+
for w in weights:
107+
ret.append(
108+
(bin >> w) & 255
109+
)
110+
return ".".join(map(str, ret))
111+
112+
def get_lsb(self, n):
113+
lsb = 0
114+
while (n >> lsb) & 1 == 0:
115+
lsb += 1
116+
# n >>= lsb # error
117+
return lsb
118+
119+
120+
if __name__ == "__main__":
121+
assert Solution().ipToCIDR("60.166.253.147", 12) == ["60.166.253.147/32","60.166.253.148/30","60.166.253.152/30","60.166.253.156/31","60.166.253.158/32"]
122+
assert Solution().ipToCIDR("255.0.0.7", 10) == ["255.0.0.7/32","255.0.0.8/29","255.0.0.16/32"]

0 commit comments

Comments
 (0)