Evaluate IP Access Rules
Company: Amazon
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: hard
Interview Round: Technical Screen
You are given a list of IPv4 access-control rules. Each rule consists of:
- an action: `allow` or `deny`
- a CIDR block such as `192.168.0.0/16`
You are also given a target IPv4 address such as `192.168.1.25`.
Determine whether the target IP should be **allowed** or **denied**.
Use the following rule semantics so the problem is fully specified:
1. A rule matches if the target IP belongs to that CIDR block.
2. If multiple rules match, the rule with the **longest prefix length** takes precedence.
3. If multiple matching rules have the same prefix length, the **later** rule in the input overrides the earlier one.
4. If no rule matches, return `deny`.
Implement a function that takes a list of rules and one IPv4 address and returns the final decision.
You may assume all inputs are valid IPv4 addresses and valid CIDR blocks, with prefix lengths from 0 to 32.
Quick Answer: This question evaluates knowledge of IPv4 addressing, CIDR subnet matching, and access-control rule resolution, assessing competency in bitwise address reasoning, prefix-length precedence, and rule tie-breaking.
You are given a list of IPv4 access-control rules and a target IPv4 address. Each rule is a pair `[action, cidr]` where `action` is `"allow"` or `"deny"` and `cidr` is a CIDR block such as `"192.168.0.0/16"`. The target is a dotted-quad string such as `"192.168.1.25"`.
Return the final decision (`"allow"` or `"deny"`) using these semantics:
1. A rule matches if the target IP belongs to that rule's CIDR block.
2. Among matching rules, the one with the **longest prefix length** takes precedence.
3. If multiple matching rules share the same (longest) prefix length, the one that appears **later** in the input wins.
4. If no rule matches, return `"deny"`.
All inputs are valid IPv4 addresses and valid CIDR blocks with prefix lengths from 0 to 32.
The function signature is `evaluateAccess(rules, ip)`.
Constraints
- 0 <= number of rules <= 10^5
- Each CIDR prefix length is in the range 0 to 32
- All IPs and CIDR blocks are valid IPv4 (no IPv6)
- action is exactly "allow" or "deny"
Examples
Input: ([['allow', '192.168.0.0/16'], ['deny', '192.168.1.0/24']], '192.168.1.25')
Expected Output: 'deny'
Explanation: Both rules match. /24 is a longer prefix than /16, so the deny rule wins.
Input: ([['deny', '0.0.0.0/0'], ['allow', '10.0.0.0/8']], '10.1.2.3')
Expected Output: 'allow'
Explanation: The /0 default deny and the /8 allow both match; the longer /8 prefix wins -> allow.
Hints
- Convert each dotted-quad IPv4 address to a 32-bit integer so containment becomes a bitmask test.
- For a prefix length p, build the mask ((1 << p) - 1) << (32 - p); a rule matches when (target & mask) == (network & mask). Handle p == 0 specially (mask = 0, matches everything).
- Track the longest prefix length seen so far. Use '>=' (not '>') when comparing so that a rule with an equal prefix length that appears later overrides the earlier one.