Determine allow/deny for an IP via CIDR rules
Company: Databricks
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: hard
Interview Round: Technical Screen
Quick Answer: This question evaluates understanding of IPv4 addressing, CIDR range matching, rule ordering and precedence, and algorithmic correctness in determining allow/deny outcomes.
Constraints
- 0 <= len(rules) <= 10^5
- Each rule is of the form (action, cidr), where action is "ALLOW" or "DENY"
- CIDR prefix length p is in the range [0, 32]
- IPv4 only; all input strings are well-formed
- Rules are evaluated in order, and the first matching rule decides the result
Examples
Input: ([('DENY', '10.0.0.0/8'), ('ALLOW', '10.1.0.0/16')], '10.1.2.3')
Expected Output: 'DENY'
Explanation: 10.1.2.3 matches both CIDR blocks, but the first matching rule is DENY.
Input: ([('ALLOW', '192.168.1.10/32'), ('DENY', '192.168.1.0/24')], '192.168.1.10')
Expected Output: 'ALLOW'
Explanation: The exact /32 rule matches first, so it takes priority over the broader /24 deny rule.
Input: ([('DENY', '0.0.0.0/0')], '8.8.8.8')
Expected Output: 'DENY'
Explanation: A /0 CIDR matches every IPv4 address.
Input: ([], '8.8.4.4')
Expected Output: 'ALLOW'
Explanation: There are no rules, so the default action ALLOW is returned.
Input: ([('ALLOW', '10.0.0.0/8')], '192.0.2.1', 'DENY')
Expected Output: 'DENY'
Explanation: The IP does not match the only rule, so the custom default action is returned.
Hints
- Convert each IPv4 address into a 32-bit integer so you can compare ranges using bit masks.
- For a CIDR block a.b.c.d/p, build a mask with the top p bits set. Remember that /0 matches every IPv4 address.