Evaluate Ordered Accept/Block Transaction Rules with AND, OR and Parentheses
Company: Stripe
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Onsite
In this round you write Python in a coding environment that has a built-in AI assistant, and you are expected to use it. Implement a transaction risk-rule evaluator: given one transaction as a dictionary of field values and an ordered list of rules, decide whether the transaction is accepted or blocked.
- Rules are applied in list order, and the first rule whose condition matches decides the result.
- If no rule matches, the result is `"accept"`.
- Inputs are guaranteed to be well-formed.
The exact rule syntax of the original prompt was not preserved. For practice, assume that each rule is a pair `(condition, outcome)`, where `outcome` is `"accept"` or `"block"` and `condition` is a string in which string constants are written in double quotes and equality is written `==`:
```python
transaction = {"merchant": "Corner Store", "country": "US"}
rules = [
('country == "FR"', "block"),
('"Corner Store" == merchant', "accept"),
]
evaluate(transaction, rules) # "accept": the second rule is the first one that matches
```
Implement `evaluate(transaction: dict, rules: list[tuple[str, str]]) -> str`. The task has three parts, and each part must keep the behavior of the earlier ones.
### Clarifying Questions
- What should a condition do when it refers to a field the transaction does not have?
- Are AND and OR written in upper case only, or in any case?
- Can a string constant contain a double quote, and if so, how is it escaped?
### Part 1 — String equality and rule order
Support conditions that compare one field with one string constant for equality, the two outcomes accept and block, first-match order, and the default accept. The examples allow the field and the string constant to appear on either side of the equals sign.
```hint Field or constant
Decide how your code tells a field name from a string constant without relying on which side of the operator it appears on.
```
#### What This Part Should Cover
- Recognizing a constant versus a field regardless of operand order
- First-match semantics and the default outcome
- A few runnable examples, including the swapped form
### Part 2 — Boolean fields with AND and OR
Keep the Part 1 behavior. Add conditions on Boolean fields, and allow conditions to be combined with AND and OR. The interviewer then asks for a boundary test: what does your program do if a merchant name itself contains the word "and" or "or"?
```hint Where a keyword is recognized
Ask at which step your code decides that a piece of text is the operator AND rather than part of a quoted value, and whether that step knows where quotes begin and end.
```
#### Clarifying Questions for this Part
- Is a Boolean condition written as a bare field name, as a comparison with `true` or `false`, or both?
- Can AND and OR be mixed in one condition without parentheses, and if so, which binds tighter?
#### What This Part Should Cover
- How Boolean values are represented and compared, without confusing them with strings
- Splitting a condition into operators and operands without breaking quoted values
- The precedence rule, and a test with "and" or "or" inside a merchant name
### Part 3 — Parentheses and nested combinations
Extend conditions to arbitrary combinations of parentheses, equality tests and AND / OR, for example `(country == "US" OR country == "CA") AND merchant == "Corner Store"`.
```hint Grammar first
Write down the grammar of a condition, including how parentheses and the two operators nest, before you change the code.
```
#### What This Part Should Cover
- A parser that handles nesting to any depth and respects precedence
- Evaluation over the parsed structure, with short-circuiting
- Tests that tell correct precedence apart from plain left-to-right evaluation
### What a Strong Answer Covers
- A tokenizer that understands quoted strings, kept separate from parsing and evaluation
- Behavior from Parts 1 and 2 preserved as the grammar grows, with the tests rerun each time
- Explicit decisions on missing fields, Boolean representation and precedence
- Critical use of the AI assistant: a precise specification going in, careful review and real tests coming out
- Robustness that does not depend on how merchant names or field names happen to be spelled
### Follow-up Questions
- How would you report which rule decided each transaction, for audits and for explaining a block to support staff?
- If rules are evaluated against a high volume of transactions, what would you precompute?
- How would you add NOT, inequality, or a numeric comparison such as an amount above a limit?
- If inputs are no longer guaranteed to be valid, how and when would you reject a malformed rule?
Overview: A three-part Python exercise, solved with an in-editor AI assistant, that evaluates an ordered list of accept or block rules against a transaction. Conditions grow from string equality to Boolean fields, AND and OR, and parentheses, testing tokenizing quoted values, operator precedence, first-match semantics and careful review of AI-written code.
Read the full Stripe Software Engineer interview experience this question came from