Implement IP Address Arithmetic
Company: OpenAI
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: hard
Interview Round: Onsite
Quick Answer: This question evaluates proficiency in IP addressing, parsing and validation, binary/address-space arithmetic, CIDR subnet calculation, and formatting for both IPv4 and IPv6, testing bit-level manipulation and string-processing skills in the Networking and Coding & Algorithms domain.
Part 1: Validate and Parse an IPv4 Address
Constraints
- 1 <= len(ip_address) <= 100
- The address must contain exactly 4 parts separated by '.'
- Each part must contain only decimal digits and represent a value in [0, 255]
- Do not use external networking libraries
Examples
Input: "192.168.0.1"
Expected Output: [192, 168, 0, 1]
Explanation: A standard valid IPv4 address.
Input: "0.0.0.0"
Expected Output: [0, 0, 0, 0]
Explanation: Lower boundary address.
Input: "255.255.255.255"
Expected Output: [255, 255, 255, 255]
Explanation: Upper boundary address.
Input: "10.01.2.003"
Expected Output: [10, 1, 2, 3]
Explanation: Leading zeros are allowed and parsed as decimal values.
Input: "256.1.2.3"
Expected Output: []
Explanation: 256 is outside the valid octet range.
Hints
- Split the string on '.' and first check whether you got exactly four pieces.
- Validate each piece before converting it: it should be non-empty, all digits, and within the range 0 to 255.
Part 2: Find the Adjacent IPv4 Address
Constraints
- 1 <= len(ip_address) <= 100
- direction is expected to be 'up' or 'down'
- Use only manual parsing and arithmetic; do not use networking libraries
Examples
Input: ("192.168.0.1", "up")
Expected Output: "192.168.0.2"
Explanation: Simple increment within the same last octet.
Input: ("192.168.0.255", "up")
Expected Output: "192.168.1.0"
Explanation: Increment carries into the next octet.
Input: ("10.0.0.0", "down")
Expected Output: "9.255.255.255"
Explanation: Decrement borrows across octet boundaries.
Input: ("0.0.0.0", "down")
Expected Output: ""
Explanation: This would underflow below the smallest IPv4 address.
Input: ("255.255.255.255", "up")
Expected Output: ""
Explanation: This would overflow above the largest IPv4 address.
Hints
- Convert the 4 octets into one 32-bit integer, then the adjacent address is just plus or minus 1.
- Check the boundary values before changing the number: 0 for underflow and 2^32 - 1 for overflow.
Part 3: Compute the First and Last IPv4 Addresses in a CIDR Block
Constraints
- 1 <= len(cidr) <= 100
- The prefix length P must be an integer in [0, 32]
- The IPv4 portion must be a valid dotted-decimal IPv4 address
- Do not use external networking libraries
Examples
Input: "192.168.0.0/24"
Expected Output: ["192.168.0.0", "192.168.0.255"]
Explanation: A standard /24 block.
Input: "192.168.5.123/24"
Expected Output: ["192.168.5.0", "192.168.5.255"]
Explanation: Host bits in the given base address are ignored when computing the block range.
Input: "10.0.0.1/32"
Expected Output: ["10.0.0.1", "10.0.0.1"]
Explanation: A /32 block contains exactly one address.
Input: "0.0.0.0/0"
Expected Output: ["0.0.0.0", "255.255.255.255"]
Explanation: A /0 block covers the entire IPv4 address space.
Input: "1.2.3.4/33"
Expected Output: []
Explanation: 33 is not a valid IPv4 prefix length.
Hints
- Build the subnet mask from the prefix length: the top P bits are 1 and the remaining bits are 0.
- The first address is ip & mask, and the last address is first | (~mask within 32 bits).
Part 4: Check Whether an IPv4 Address Belongs to a CIDR Block
Constraints
- 1 <= len(ip_address), len(cidr) <= 100
- The CIDR prefix length must be in [0, 32]
- Use only manual parsing and arithmetic; do not use networking libraries
Examples
Input: ("192.168.0.10", "192.168.0.0/24")
Expected Output: 1
Explanation: The address falls inside the /24 range.
Input: ("192.168.0.200", "192.168.0.99/24")
Expected Output: 1
Explanation: The block is still 192.168.0.0/24 after masking the base address.
Input: ("192.168.1.10", "192.168.0.0/24")
Expected Output: 0
Explanation: The third octet differs from the target /24 block.
Input: ("10.0.0.0", "10.0.0.0/32")
Expected Output: 1
Explanation: A /32 block contains exactly one address, and this is it.
Input: ("1.2.3.4", "1.2.3.4/33")
Expected Output: -1
Explanation: The CIDR block is invalid because the prefix is out of range.
Hints
- Two addresses are in the same block if their network portions are equal after applying the same subnet mask.
- A /0 mask is valid and matches every valid IPv4 address.
Part 5: Find the Adjacent IPv6 Address
Constraints
- 1 <= len(ipv6_address) <= 200
- The IPv6 address must contain exactly 8 groups separated by '.'
- Each group must contain 1 to 4 hexadecimal characters
- Compressed notation such as '::' is not allowed
- Do not use external networking libraries
Examples
Input: ("ffff.ffff.ffff.ffff.ffff.ffff.ffff.fffa", "up")
Expected Output: "ffff.ffff.ffff.ffff.ffff.ffff.ffff.fffb"
Explanation: A simple increment in the last group.
Input: ("0000.0000.0000.0000.0000.0000.0000.ffff", "up")
Expected Output: "0000.0000.0000.0000.0000.0000.0001.0000"
Explanation: Increment causes a carry into the previous 16-bit group.
Input: ("ABCD.0.0.0.0.0.0.1", "down")
Expected Output: "abcd.0000.0000.0000.0000.0000.0000.0000"
Explanation: Input is case-insensitive and output is normalized to lowercase four-digit groups.
Input: ("0000.0000.0000.0000.0000.0000.0000.0000", "down")
Expected Output: ""
Explanation: This would underflow below the smallest IPv6 address.
Input: ("ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff", "up")
Expected Output: ""
Explanation: This would overflow above the largest IPv6 address.
Hints
- Treat each group as a 16-bit chunk and build one 128-bit integer by shifting left 16 bits at a time.
- When formatting the answer, always print each group with exactly 4 lowercase hexadecimal digits.