PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates implementing rule-evaluation logic, data modeling for expense records and rule representations, operator semantics, and designing for extensibility to support grouped rules and logical composition.

  • easy
  • Rippling
  • Coding & Algorithms
  • Software Engineer

Build an Expense Policy Rule Engine

Company: Rippling

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: easy

Interview Round: Technical Screen

Implement a simplified expense-policy rule engine. An expense record contains: - `amount`: number - `category`: string - `merchant`: string - `country`: string A basic rule contains: - `id`: string - `field`: one of the expense fields above - `operator`: one of `==`, `!=`, `>`, `>=`, `<`, `<=`, `in` - `value`: the value to compare against Write a component that can: 1. register a collection of rules; 2. evaluate a single expense record; 3. return the ids of all rules that match the expense. After that, explain how you would extend the model to support grouped rules, where a group can contain rules or other groups and combines them using logical `AND` or `OR`. You only need to implement the basic rule engine in code. The grouped-rule extension can be discussed at a design level.

Quick Answer: This question evaluates implementing rule-evaluation logic, data modeling for expense records and rule representations, operator semantics, and designing for extensibility to support grouped rules and logical composition.

Implement a simplified expense-policy rule engine. An expense record has these fields: - amount: number - category: string - merchant: string - country: string Each basic rule is a dictionary with: - id: string - field: one of amount, category, merchant, country - operator: one of ==, !=, >, >=, <, <=, in - value: the value to compare against Write a function that receives a collection of rules and a single expense record, evaluates every rule, and returns the ids of all rules that match the expense. For the in operator, the rule matches when expense[field] is contained in rule["value"]. You may assume rule["value"] is a valid collection for membership checks when operator is in. Return matching rule ids in the same order the rules were registered. Follow-up discussion only: after coding, explain how you would extend this model so that a group can contain rules or other groups and combine them with logical AND or OR. You do not need to implement grouped rules in code.

Constraints

  • 0 <= len(rules) <= 100000
  • Each rule has a valid field and operator
  • All comparisons are type-compatible
  • For operator 'in', rule['value'] is a collection that supports membership testing

Examples

Input: ([{'id': 'r1', 'field': 'amount', 'operator': '>=', 'value': 100}, {'id': 'r2', 'field': 'category', 'operator': '==', 'value': 'travel'}, {'id': 'r3', 'field': 'country', 'operator': 'in', 'value': ['US', 'CA']}, {'id': 'r4', 'field': 'merchant', 'operator': '!=', 'value': 'Uber'}], {'amount': 120, 'category': 'travel', 'merchant': 'Hilton', 'country': 'US'})

Expected Output: ['r1', 'r2', 'r3', 'r4']

Explanation: All four rules match the expense, so all ids are returned in the original order.

Input: ([], {'amount': 50, 'category': 'meal', 'merchant': 'Cafe', 'country': 'FR'})

Expected Output: []

Explanation: With no registered rules, nothing can match.

Input: ([{'id': 'a', 'field': 'amount', 'operator': '<', 'value': 0}, {'id': 'b', 'field': 'amount', 'operator': '<=', 'value': -20}, {'id': 'c', 'field': 'country', 'operator': 'in', 'value': ['DE', 'FR']}, {'id': 'd', 'field': 'merchant', 'operator': '==', 'value': 'RefundCo'}], {'amount': -20, 'category': 'refund', 'merchant': 'RefundCo', 'country': 'DE'})

Expected Output: ['a', 'b', 'c', 'd']

Explanation: This checks negative amounts, a boundary comparison, membership, and string equality. Every rule matches.

Input: ([{'id': 'r1', 'field': 'amount', 'operator': '>', 'value': 500}, {'id': 'r2', 'field': 'category', 'operator': '==', 'value': 'lodging'}, {'id': 'r3', 'field': 'country', 'operator': '!=', 'value': 'JP'}], {'amount': 300, 'category': 'meal', 'merchant': 'Sushi Bar', 'country': 'JP'})

Expected Output: []

Explanation: The amount is not greater than 500, the category is not lodging, and the country is equal to JP, so no rules match.

Input: ([{'id': 'x1', 'field': 'category', 'operator': 'in', 'value': ['meal', 'travel']}, {'id': 'x2', 'field': 'amount', 'operator': '<', 'value': 50}, {'id': 'x3', 'field': 'country', 'operator': '==', 'value': 'US'}, {'id': 'x4', 'field': 'merchant', 'operator': '!=', 'value': 'Starbucks'}], {'amount': 49.99, 'category': 'meal', 'merchant': 'Starbucks', 'country': 'US'})

Expected Output: ['x1', 'x2', 'x3']

Explanation: The first three rules match. The last rule fails because the merchant is exactly Starbucks.

Hints

  1. Write a small helper or mapping from operator strings to the corresponding comparison logic.
  2. Scan the rules once, and append a rule's id whenever its condition is true.
Last updated: May 16, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Implement a Searchable Logger Pipeline - Rippling (hard)
  • Implement an In-Memory File System - Rippling
  • Compare Complete and Partial Poker Hands - Rippling (medium)
  • Implement Courier Delivery Cost Tracking - Rippling (medium)
  • Implement Article Vote Tracking - Rippling (medium)