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.
Overview: 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.
Read the full Affirm Software Engineer interview experience this question came from
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.
Community answers
Answer by akshayjagz
Simple Python:
def count_distinct_underwriting_pii(events):
pii = set()
pii_fields = ['address', 'phone', 'email', 'ssn']
for event in events:
if event.get('event_type') == 'underwriting':
cust_details = event.get('customer_details')
if cust_details and cust_details != {}:
for field in pii_fields:
val = cust_details.get(field)
if val and isinstance(val, str) and val != '':
pii.add(val)
return len(pii)