Count Distinct PII in Underwriting Events
Company: Affirm
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
# Count Distinct PII in Underwriting Events
An event stream contains `underwriting` and `fraud_flag` events. Count the distinct nonempty personally identifiable information values present across all `underwriting` events. Ignore every `fraud_flag` event.
The recognized PII fields are `address`, `phone`, `email`, and `ssn` inside `customer_details`.
### Function Signature
```python
def count_distinct_underwriting_pii(events: list[dict]) -> int:
...
```
### Example
```text
Input: [
{"event_type": "underwriting",
"customer_details": {
"address": "123 Main St", "phone": "182-920-4124",
"email": "johndoe@gmail.com", "ssn": "4568698929"
},
"loan_amount": 3000},
{"event_type": "fraud_flag",
"customer_details": {
"address": "ignored", "phone": "ignored"
}},
{"event_type": "underwriting",
"customer_details": {
"address": "123 Main St", "phone": "947-213-9402",
"email": "janedoe@yahoo.com", "ssn": "4568698929"
},
"loan_amount": 3000}
]
Output: 6
```
### Constraints
- `0 <= len(events) <= 200_000`
- Every event is a JSON-compatible dictionary with a valid `event_type`.
- `customer_details` may be absent or `null`.
- Recognized PII values, when present, are strings.
### Clarifications
- Count distinct values globally, not distinct `(field, value)` pairs. The same string in two recognized fields counts once.
- Ignore a recognized field when it is absent, `null`, or the empty string.
- Ignore unrecognized fields such as `credit_score` and all top-level fields other than `event_type`.
- Do not mutate the events.
- Target expected `O(n)` time in the total number of events and `O(u)` space for `u` distinct PII values.
### Hints
- Filter by event type before inspecting customer details.
- Avoid inserting a default empty value for missing fields.
Quick Answer: Count globally distinct nonempty PII values found in address, phone, email, and SSN fields across underwriting events only. Ignore fraud flags, missing customer details, nulls, empty strings, and unrecognized fields while using a set for expected linear processing.
Across underwriting events only, count globally distinct nonempty string values found in address, phone, email, and ssn fields inside customer_details. Ignore fraud_flag events, absent or null details, empty values, and unrecognized fields.
Constraints
- Only events whose event_type is underwriting are inspected.
- Recognized fields are address, phone, email, and ssn.
- The same string in different recognized fields counts once.
- Missing, null, and empty-string values are ignored.
- Do not mutate the input events.
Examples
Input: ([],)
Expected Output: 0
Explanation: An empty stream contains no PII.
Input: ([{"event_type": "underwriting", "customer_details": {"address": "123 Main St", "phone": "182-920-4124", "email": "johndoe@gmail.com", "ssn": "4568698929"}, "loan_amount": 3000}, {"event_type": "fraud_flag", "customer_details": {"address": "ignored", "phone": "ignored"}}, {"event_type": "underwriting", "customer_details": {"address": "123 Main St", "phone": "947-213-9402", "email": "janedoe@yahoo.com", "ssn": "4568698929"}, "loan_amount": 3000}],)
Expected Output: 6
Explanation: The prompt has six globally distinct recognized values.
Hints
- Filter event type before reading customer_details.
- Use one set for values across all recognized fields.
- Do not add a default empty value for missing fields.