Build an Expense Policy Rule Engine
RipplingSoftware Engineer · Technical ScreenLast updated
This question tests your ability to design a rule evaluation engine that processes structured expense data against a set of logical conditions, including support for basic operators.
Problem Statement
You are tasked with building a lightweight rule engine for an expense management system. The system evaluates whether an Expense object complies with a set of Rules.
Definitions
- An
Expenseis represented as a dictionary with keys:amount(float),category(string), andis_international(boolean). - A
Ruleis represented as a dictionary with:field(the expense key to check),operator(one of '>', '<', '==', 'in'), andvalue(the threshold or set to compare against).
Task
Implement a function is_compliant(expense, rules) that returns True if the expense satisfies all rules in the provided list, and False otherwise.
Examples
# Example 1: Basic validation
expense = {"amount": 150.0, "category": "travel", "is_international": False}
rules = [
{"field": "amount", "operator": "<", "value": 500},
{"field": "category", "operator": "in", "value": ["travel", "office"]}
]
# Result: True (150 < 500 AND travel is in [travel, office])
# Example 2: Failing validation
expense = {"amount": 1200.0, "category": "software", "is_international": True}
rules = [
{"field": "amount", "operator": "<", "value": 1000}
]
# Result: False (1200 is not < 1000)
Constraints
ruleswill contain between 0 and 50 rule objects.- The
valuefor the 'in' operator will be a list of primitives. - Ensure the code handles missing fields gracefully (treat as
Falseif a rule references a non-existent key).
Edge Cases
- Empty rules list: The function should return
True(no rules violated). operatornot recognized: The function should raise aValueError.- Mismatched types (e.g., comparing string to int).
Hints
Hint 1
Use a dictionary mapping operator strings to lambda functions to avoid long if-else chains.
Hint 2
Access the expense value dynamically using `expense.get(rule['field'])` to safely handle missing keys.
Hint 3
Iterate through the rule list and use the `all()` function or a simple loop with an early return.
Follow-up questions
- How would you modify the engine to support nested logic, such as an 'OR' operator between groups of rules?
- If this engine were used in a high-traffic environment, how would you optimize the evaluation of thousands of rules per second?
- How would you redesign the system if the rules were stored in a database and needed to be fetched and compiled into executable code at runtime?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.