Skip to main content

Python Nested Logic Patterns Practice Problems & Exercises

Practice: Nested Logic Patterns

10 problems3 Easy4 Medium3 Hard35–50 min
← Back to lesson

Easy

#1Identify Nesting DepthEasy
nested-ifcode-analysisnesting-depth

Analyze code snippets and report the maximum nesting depth of conditional logic. Depth 1 means a single if with no inner conditionals.

Python
# We represent code snippets as lists of (indent_level, keyword) pairs.
# indent_level counts how many conditional blocks deep the line is.

snippet_a = [
    (1, "if user.is_active:"),
    (2, "if user.role == 'admin':"),
    (3, "if user.has_permission('delete'):"),
    (3, "print('can delete')"),
]

snippet_b = [
    (1, "if not user:"),
    (1, "return None"),
    (1, "if not user.is_active:"),
    (1, "return 'inactive'"),
    (1, "return process(user)"),
]

snippet_c = [
    (1, "if request.method == 'POST':"),
    (2, "if request.body:"),
    (3, "if validate(request.body):"),
    (4, "if save(request.body):"),
    (4, "return 'saved'"),
]

for name, snippet in [("snippet_a", snippet_a), ("snippet_b", snippet_b), ("snippet_c", snippet_c)]:
    max_depth = max(level for level, _ in snippet)
    print(f"{name} max depth: {max_depth}")
Solution
snippet_a max depth: 3
snippet_b max depth: 1
snippet_c max depth: 4

Key insights:

  • snippet_a (depth 3): Classic nested pattern — check user, then role, then permission. Each check is inside the previous one, creating a pyramid.
  • snippet_b (depth 1): Guard clause pattern — every check is at the top level with an early return. Despite having multiple conditions, the maximum depth never exceeds 1.
  • snippet_c (depth 4): Deeply nested request handling. Four levels of checking (method, body, validation, save) creates hard-to-read code that should be refactored.

Rule of thumb: If your nesting depth exceeds 2, consider flattening with guard clauses, extraction, or lookup tables. Deep nesting makes code harder to read, test, and maintain.

Expected Output
snippet_a max depth: 3
snippet_b max depth: 1
snippet_c max depth: 4
Hints

Hint 1: Count indentation levels that start with `if`, `elif`, or `else`. Each new conditional block inside another adds one level of nesting.

Hint 2: Flat guard clauses (early returns) keep depth at 1 even if there are many checks.

#2Flatten Three-Level Nested IfEasy
flattenguard-clauserefactoring

Refactor the nested function into a flat version using guard clauses. Both versions must produce identical output.

Python
# --- NESTED version (depth 3 — hard to read) ---
def check_access_nested(user, role, permission):
    if user is not None:
        if role in ("admin", "editor"):
            if permission == "write":
                return "full"
            else:
                return "denied"
        else:
            return "denied"
    else:
        return "denied"

# --- FLAT version (guard clauses — depth 1) ---
def check_access_flat(user, role, permission):
    if user is None:
        return "denied"
    if role not in ("admin", "editor"):
        return "denied"
    if permission != "write":
        return "denied"
    return "full"

# --- Verify both produce the same results ---
test_cases = [
    ({"name": "Alice"}, "admin", "write"),
    (None, "admin", "write"),
    ({"name": "Bob"}, "viewer", "write"),
    ({"name": "Carol"}, "editor", "read"),
]

print("--- NESTED version ---")
for user, role, perm in test_cases:
    print(f"access: {check_access_nested(user, role, perm)}")

print("--- FLAT version ---")
for user, role, perm in test_cases:
    print(f"access: {check_access_flat(user, role, perm)}")
Solution
--- NESTED version ---
access: full
access: denied
access: denied
access: denied
--- FLAT version ---
access: full
access: denied
access: denied
access: denied

The flattening technique:

  1. Identify the innermost "happy path" — in the nested version, return "full" is buried 3 levels deep.
  2. Invert each condition and return the failure case immediately:
    • if user is not None: becomes if user is None: return "denied"
    • if role in (...): becomes if role not in (...): return "denied"
    • if permission == "write": becomes if permission != "write": return "denied"
  3. The happy path falls through all guards and sits at depth 0.

Why flat is better:

  • Each guard clause is independently testable.
  • Adding a new check means adding one line, not restructuring the entire pyramid.
  • The reader can scan top-to-bottom: every early return is a rejection, and the final return is the success.
Expected Output
--- NESTED version ---
access: full
access: denied
access: denied
access: denied
--- FLAT version ---
access: full
access: denied
access: denied
access: denied
Hints

Hint 1: Invert each condition and return early. `if user:` with code inside becomes `if not user: return "denied"` at the top.

Hint 2: After all guard clauses pass, the remaining code (the happy path) sits at the top indentation level — no nesting needed.

#3Replace Nested If with Dict LookupEasy
dict-lookupnested-ifrefactoring

Replace the nested if/elif chain with a single dictionary lookup. Both must produce identical output.

Python
# --- NESTED version (if/elif chain) ---
def status_message_nested(code):
    if code == 200:
        return "OK"
    elif code == 201:
        return "Created"
    elif code == 301:
        return "Moved Permanently"
    elif code == 400:
        return "Bad Request"
    elif code == 401:
        return "Unauthorized"
    elif code == 403:
        return "Forbidden"
    elif code == 404:
        return "Not Found"
    elif code == 500:
        return "Internal Server Error"
    elif code == 502:
        return "Bad Gateway"
    elif code == 503:
        return "Service Unavailable"
    else:
        return "Unknown Status"

# --- DICT version (zero nesting) ---
STATUS_MAP = {
    200: "OK",
    201: "Created",
    301: "Moved Permanently",
    400: "Bad Request",
    401: "Unauthorized",
    403: "Forbidden",
    404: "Not Found",
    500: "Internal Server Error",
    502: "Bad Gateway",
    503: "Service Unavailable",
}

def status_message_dict(code):
    return STATUS_MAP.get(code, "Unknown Status")

# --- Verify both versions match ---
test_codes = [200, 301, 404, 500, 999]

print("--- NESTED version ---")
for code in test_codes:
    print(f"http {code} -> {status_message_nested(code)}")

print("--- DICT version ---")
for code in test_codes:
    print(f"http {code} -> {status_message_dict(code)}")
Solution
--- NESTED version ---
http 200 -> OK
http 301 -> Moved Permanently
http 404 -> Not Found
http 500 -> Internal Server Error
http 999 -> Unknown Status
--- DICT version ---
http 200 -> OK
http 301 -> Moved Permanently
http 404 -> Not Found
http 500 -> Internal Server Error
http 999 -> Unknown Status

Why dictionaries beat long if/elif chains:

  • O(1) lookup vs O(n) sequential checking — dictionaries use hash tables internally.
  • Data-driven — the mapping is declared as pure data, separate from logic. You can load it from a config file, database, or API.
  • Single line of logicSTATUS_MAP.get(code, "Unknown Status") replaces 20+ lines of branching.
  • Easy to extend — adding a new status code means one new dictionary entry, not inserting into the middle of an if/elif chain.
  • Testable — you can assert on the dictionary contents directly without calling the function.

When NOT to use a dict: When each branch has complex logic beyond returning a value (side effects, multiple statements, different argument handling). In those cases, consider a dict of functions instead.

Expected Output
--- NESTED version ---
http 200 -> OK
http 301 -> Moved Permanently
http 404 -> Not Found
http 500 -> Internal Server Error
http 999 -> Unknown Status
--- DICT version ---
http 200 -> OK
http 301 -> Moved Permanently
http 404 -> Not Found
http 500 -> Internal Server Error
http 999 -> Unknown Status
Hints

Hint 1: A dictionary maps each status code to its message. Use `dict.get(key, default)` to handle unknown codes without any if-statements.

Hint 2: This pattern eliminates all branching — the dictionary IS the decision logic. Adding new codes means adding one key-value pair.


Medium

#4Refactor Complex Order ProcessingMedium
refactoringorder-processingflatten-logic

Refactor the deeply nested order processing function into a clean, flat structure. Both versions must produce identical output.

Python
# --- NESTED version (depth 4) ---
def process_order_nested(customer, cart, coupon=None):
    if customer is not None:
        if customer.get("verified"):
            if len(cart) > 0:
                total = 0
                for item in cart:
                    if item.get("in_stock", False):
                        total += item["price"] * item["qty"]
                if coupon is not None:
                    if coupon.get("active"):
                        total *= (1 - coupon["discount"])
                return {"total": round(total, 2), "status": "approved"}
            else:
                return {"total": 0, "status": "rejected: empty cart"}
        else:
            return {"total": 0, "status": "rejected: not verified"}
    else:
        return {"total": 0, "status": "rejected: no customer"}

# --- REFACTORED version (flat, extracted helpers) ---
def validate_order(customer, cart):
    """Return error message or None if valid."""
    if customer is None:
        return "no customer"
    if not customer.get("verified"):
        return "not verified"
    if len(cart) == 0:
        return "empty cart"
    return None

def calculate_total(cart):
    """Sum prices for in-stock items only."""
    return sum(
        item["price"] * item["qty"]
        for item in cart
        if item.get("in_stock", False)
    )

def apply_coupon(total, coupon):
    """Apply discount if coupon is active."""
    if coupon and coupon.get("active"):
        return total * (1 - coupon["discount"])
    return total

def process_order_flat(customer, cart, coupon=None):
    error = validate_order(customer, cart)
    if error:
        return {"total": 0, "status": f"rejected: {error}"}

    total = calculate_total(cart)
    total = apply_coupon(total, coupon)
    return {"total": round(total, 2), "status": "approved"}

# --- Test data ---
orders = [
    ({"name": "Alice", "verified": True},
     [{"name": "Widget", "price": 25.00, "qty": 2, "in_stock": True},
      {"name": "Gadget", "price": 30.00, "qty": 1, "in_stock": True}],
     None),
    ({"name": "Bob", "verified": False},
     [{"name": "Widget", "price": 25.00, "qty": 1, "in_stock": True}],
     None),
    ({"name": "Carol", "verified": True}, [], None),
    ({"name": "Dave", "verified": True},
     [{"name": "Pro", "price": 150.00, "qty": 1, "in_stock": True}],
     {"active": True, "discount": 0.05}),
    (None, [{"name": "X", "price": 10, "qty": 1, "in_stock": True}], None),
]

print("--- NESTED version ---")
for i, (cust, cart, coupon) in enumerate(orders, 1):
    result = process_order_nested(cust, cart, coupon)
    print(f"Order {i}: total={result['total']}, status={result['status']}")

print("--- REFACTORED version ---")
for i, (cust, cart, coupon) in enumerate(orders, 1):
    result = process_order_flat(cust, cart, coupon)
    print(f"Order {i}: total={result['total']}, status={result['status']}")
Solution
--- NESTED version ---
Order 1: total=80.00, status=approved
Order 2: total=0, status=rejected: not verified
Order 3: total=0, status=rejected: empty cart
Order 4: total=142.50, status=approved
Order 5: total=0, status=rejected: no customer
--- REFACTORED version ---
Order 1: total=80.00, status=approved
Order 2: total=0, status=rejected: not verified
Order 3: total=0, status=rejected: empty cart
Order 4: total=142.50, status=approved
Order 5: total=0, status=rejected: no customer

Three refactoring strategies used here:

  1. Extract validationvalidate_order() returns an error message or None. The main function checks once and returns early. This eliminates the nested "check customer, then check verified, then check cart" pyramid.

  2. Extract computationcalculate_total() uses a generator expression with a conditional (if item.get("in_stock")). No nesting — the filter is built into the comprehension.

  3. Extract transformationapply_coupon() handles the coupon logic in isolation. The if coupon and coupon.get("active") check is a single flat conditional.

The main function (process_order_flat) reads like a recipe:

  1. Validate the order. If invalid, reject.
  2. Calculate the total.
  3. Apply the coupon.
  4. Return the result.

Each step is independently testable, and adding new steps (e.g., tax calculation, shipping) means adding one function call — not nesting another level.

Expected Output
--- NESTED version ---
Order 1: total=80.00, status=approved
Order 2: total=0, status=rejected: not verified
Order 3: total=0, status=rejected: empty cart
Order 4: total=142.50, status=approved
Order 5: total=0, status=rejected: no customer
--- REFACTORED version ---
Order 1: total=80.00, status=approved
Order 2: total=0, status=rejected: not verified
Order 3: total=0, status=rejected: empty cart
Order 4: total=142.50, status=approved
Order 5: total=0, status=rejected: no customer
Hints

Hint 1: Extract validation into a separate function that returns an error message or None. The main function calls validate first and returns early on failure.

Hint 2: Separate the concerns: validation logic, price calculation, and discount application should each be their own function or block.

#5State-Based Processor Without NestingMedium
state-machinedict-dispatchno-nesting

Implement a document workflow processor using a state-transition table instead of nested if/elif. The processor should track state history and handle invalid transitions gracefully.

Python
class DocumentProcessor:
    TRANSITIONS = {
        ("idle", "start_review"):     ("reviewing", "Started review"),
        ("reviewing", "approve"):     ("editing", "Review approved, editing"),
        ("reviewing", "publish"):     ("published", "Review approved, publishing"),
        ("reviewing", "reject"):      ("idle", "Review rejected, back to idle"),
        ("editing", "submit"):        ("reviewing", "Edit complete, re-reviewing"),
        ("editing", "cancel"):        ("idle", "Edit cancelled"),
        ("published", "archive"):     ("archived", "Document archived"),
    }

    FINAL_STATES = {"published", "archived"}

    def __init__(self):
        self.state = "idle"
        self.history = ["idle"]

    def process(self, action):
        if self.state in self.FINAL_STATES:
            return f"[{self.state}] Final state reached"

        key = (self.state, action)
        if key not in self.TRANSITIONS:
            return f"[{self.state}] Invalid action: {action}"

        old_state = self.state
        self.state, message = self.TRANSITIONS[key]
        self.history.append(self.state)
        return f"[{old_state} -> {self.state}] {message}"

# --- Run the pipeline ---
doc = DocumentProcessor()
actions = ["start_review", "approve", "submit", "publish", "archive"]

print("Processing document through pipeline...")
for action in actions:
    result = doc.process(action)
    print(result)

print(f"\nFinal state: {doc.state}")
print(f"History: {' -> '.join(doc.history)}")
Solution
Processing document through pipeline...
[idle -> reviewing] Started review
[reviewing -> editing] Review approved, editing
[editing -> reviewing] Edit complete, re-reviewing
[reviewing -> published] Review approved, publishing
[published] Final state reached

Final state: published
History: idle -> reviewing -> editing -> reviewing -> published

Why a transition table beats nested conditionals:

The naive approach would look like this (do not write code this way):

if state == "idle":
if action == "start_review":
state = "reviewing"
elif action == "approve":
print("Invalid")
elif state == "reviewing":
if action == "approve":
state = "editing"
elif action == "publish":
...

That creates an N x M grid of nesting (N states times M actions). The transition table flattens this into a simple dictionary lookup:

  • Adding a new state means adding entries to the dictionary — no restructuring.
  • Invalid transitions are handled by a single if key not in check — no nested else clauses.
  • Final states are a set membership check — no repeated conditionals.
  • History tracking happens in one place, not scattered across branches.

This is a core pattern in production systems: workflow engines, order status tracking, game state machines, and protocol handlers all use transition tables.

Expected Output
Processing document through pipeline...
[idle -> reviewing] Started review
[reviewing -> editing] Review approved, editing
[editing -> reviewing] Edit complete, re-reviewing
[reviewing -> published] Review approved, publishing
[published] Final state reached

Final state: published
History: idle -> reviewing -> editing -> reviewing -> published
Hints

Hint 1: Model transitions as a dictionary mapping (current_state, action) pairs to (next_state, message) tuples. The processor just looks up the transition.

Hint 2: The state machine eliminates nesting entirely — instead of `if state == X: if action == Y:`, you do `transitions[(state, action)]`.

#6Config Validator Without Deep NestingMedium
validationguard-clauseerror-collection

Build a config validator that reports ALL errors at once instead of stopping at the first one. Use flat, independent validation checks — no nested conditionals.

Python
REQUIRED_KEYS = ["host", "port"]
VALID_PROTOCOLS = {"http", "https", "tcp"}

def validate_config(config):
    errors = []

    # Check required keys first
    for key in REQUIRED_KEYS:
        if key not in config:
            errors.append(f"missing required key: {key}")

    # If required keys are missing, skip field-level validation
    if errors:
        return errors

    # Each field validated independently — no nesting between fields
    host = config.get("host", "")
    if not isinstance(host, str) or not host.strip():
        errors.append("host must be a non-empty string")

    port = config.get("port", 0)
    if not isinstance(port, int) or not (1 <= port <= 65535):
        errors.append("port must be between 1 and 65535")

    protocol = config.get("protocol", "http")
    if protocol not in VALID_PROTOCOLS:
        errors.append(f"protocol must be one of: {', '.join(sorted(VALID_PROTOCOLS))}")

    timeout = config.get("timeout", 30)
    if not isinstance(timeout, (int, float)) or timeout <= 0:
        errors.append("timeout must be a positive number")

    return errors

def print_validation(label, config):
    print(f"--- {label} ---")
    errors = validate_config(config)
    if not errors:
        print("Valid: True")
        print("Errors: none")
    else:
        print("Valid: False")
        print("Errors:")
        for err in errors:
            print(f"  - {err}")

# --- Test cases ---
print_validation("Config 1 (valid)", {
    "host": "localhost",
    "port": 8080,
    "protocol": "https",
    "timeout": 60,
})

print_validation("Config 2 (multiple errors)", {
    "host": "",
    "port": 99999,
    "protocol": "ftp",
    "timeout": 10,
})

print_validation("Config 3 (missing keys)", {
    "protocol": "http",
})
Solution
--- Config 1 (valid) ---
Valid: True
Errors: none
--- Config 2 (multiple errors) ---
Valid: False
Errors:
- host must be a non-empty string
- port must be between 1 and 65535
- protocol must be one of: http, https, tcp
--- Config 3 (missing keys) ---
Valid: False
Errors:
- missing required key: host
- missing required key: port

The error-collection pattern vs. nested early-return:

A nested approach would check each field inside the previous check's success branch:

if "host" in config:
if isinstance(config["host"], str):
if config["host"].strip():
# now check port...

The error-collection pattern is superior here because:

  • All errors reported at once — the user sees every problem in one pass, not one at a time.
  • Independent checks — each field is validated in its own block with no dependency on previous checks (except the required-keys guard at the top).
  • Easy to extend — adding a new field validation means adding one block, not nesting deeper.
  • Two-phase validation — check structural requirements first (required keys), then field-level constraints. This avoids KeyError exceptions without nesting.

When to use early-return vs. error-collection:

  • Early-return: When the first error makes further checking impossible or meaningless (e.g., null user — nothing else to check).
  • Error-collection: When multiple independent things can be wrong simultaneously (e.g., form validation, config files, API request bodies).
Expected Output
--- Config 1 (valid) ---
Valid: True
Errors: none
--- Config 2 (multiple errors) ---
Valid: False
Errors:
  - host must be a non-empty string
  - port must be between 1 and 65535
  - protocol must be one of: http, https, tcp
--- Config 3 (missing keys) ---
Valid: False
Errors:
  - missing required key: host
  - missing required key: port
Hints

Hint 1: Instead of nesting checks inside each other (if host exists, then if host is a string, then if host is non-empty...), collect ALL errors in a list and return them at the end.

Hint 2: Define each validation rule as a separate function or inline check. Append errors to the list independently — no nesting between rules.

#7Extract Helper Functions to Flatten LogicMedium
extract-functionrefactoringseparation-of-concerns

Extract the nested eligibility logic into named helper functions. The refactored version should read like plain English.

Python
# --- NESTED version (depth 4) ---
def check_eligibility_nested(account):
    if account is not None:
        if account.get("status") == "active":
            if account.get("tier") in ("premium", "enterprise"):
                if account.get("loyalty_years", 0) >= 2:
                    return "eligible (premium + loyalty)"
                elif account.get("total_spend", 0) >= 1000:
                    return "eligible (premium + high spend)"
                else:
                    return "not eligible (premium but low engagement)"
            else:
                return "not eligible (basic tier)"
        else:
            return "not eligible (suspended)"
    else:
        return "not eligible (no account)"

# --- EXTRACTED version (named helpers, flat logic) ---
def has_active_account(account):
    return account is not None and account.get("status") == "active"

def is_premium_tier(account):
    return account.get("tier") in ("premium", "enterprise")

def meets_loyalty_threshold(account, min_years=2):
    return account.get("loyalty_years", 0) >= min_years

def is_high_spender(account, min_spend=1000):
    return account.get("total_spend", 0) >= min_spend

def check_eligibility_extracted(account):
    if not has_active_account(account):
        if account is None:
            return "not eligible (no account)"
        return "not eligible (suspended)"

    if not is_premium_tier(account):
        return "not eligible (basic tier)"

    if meets_loyalty_threshold(account):
        return "eligible (premium + loyalty)"

    if is_high_spender(account):
        return "eligible (premium + high spend)"

    return "not eligible (premium but low engagement)"

# --- Test data ---
accounts = [
    ("Alice", {"status": "active", "tier": "premium", "loyalty_years": 5, "total_spend": 500}),
    ("Bob", {"status": "active", "tier": "basic", "loyalty_years": 3, "total_spend": 2000}),
    ("Carol", {"status": "active", "tier": "enterprise", "loyalty_years": 1, "total_spend": 5000}),
    ("Dave", {"status": "suspended", "tier": "premium", "loyalty_years": 4, "total_spend": 3000}),
    ("Eve", None),
]

print("--- NESTED version ---")
for name, acct in accounts:
    print(f"{name}: {check_eligibility_nested(acct)}")

print("--- EXTRACTED version ---")
for name, acct in accounts:
    print(f"{name}: {check_eligibility_extracted(acct)}")
Solution
--- NESTED version ---
Alice: eligible (premium + loyalty)
Bob: not eligible (basic tier)
Carol: eligible (premium + high spend)
Dave: not eligible (suspended)
Eve: not eligible (no account)
--- EXTRACTED version ---
Alice: eligible (premium + loyalty)
Bob: not eligible (basic tier)
Carol: eligible (premium + high spend)
Dave: not eligible (suspended)
Eve: not eligible (no account)

The extraction technique step by step:

  1. Name each conditionaccount.get("tier") in ("premium", "enterprise") becomes is_premium_tier(account). The name documents the intent.
  2. Make helpers pure — each helper takes the account and returns a boolean. No side effects, no state.
  3. Flatten the main function with guard clauses — reject invalid states first (no account, suspended, wrong tier), then check positive conditions.
  4. Read it like English: "If not active, reject. If not premium, reject. If loyal, eligible. If high spender, eligible. Otherwise, not enough engagement."

Benefits:

  • Testable in isolationis_premium_tier({"tier": "basic"}) returns False without setting up the entire account flow.
  • Reusableis_high_spender can be used in other business logic (marketing emails, upgrade prompts).
  • Self-documenting — the function names eliminate the need for comments explaining what each if checks.
  • Configurable — thresholds are parameters with defaults (min_years=2, min_spend=1000), not magic numbers buried in conditionals.
Expected Output
--- NESTED version ---
Alice: eligible (premium + loyalty)
Bob: not eligible (basic tier)
Carol: eligible (premium + high spend)
Dave: not eligible (suspended)
Eve: not eligible (no account)
--- EXTRACTED version ---
Alice: eligible (premium + loyalty)
Bob: not eligible (basic tier)
Carol: eligible (premium + high spend)
Dave: not eligible (suspended)
Eve: not eligible (no account)
Hints

Hint 1: Identify each "decision" in the nested structure and give it a name: `is_account_active()`, `is_premium_tier()`, `meets_loyalty_threshold()`. Each becomes a one-liner.

Hint 2: The main function becomes a flat sequence of named boolean checks — readable as English: "if account active and (premium with loyalty or high spender)..."


Hard

#8Composable Rule EngineHard
rule-enginecomposablehigher-order-functions

Build a rule engine where individual rules are composable functions. Rules can be combined with all_of (AND) and any_of (OR) combinators — no nested conditionals anywhere.

Python
def make_rule(field, op, value, description=None):
    """Factory that creates a rule function for a single field check."""
    desc = description or f"{field} {op} {value}"

    def rule(data):
        actual = data.get(field)
        if op == ">=":
            passed = actual >= value
        elif op == "<=":
            passed = actual <= value
        elif op == "==":
            passed = actual == value
        elif op == "!=":
            passed = actual != value
        elif op == "in":
            passed = actual in value
        elif op == "is":
            passed = actual is value
        else:
            passed = False
        return (True, None) if passed else (False, f"Failed: {desc}")

    rule.__doc__ = desc
    return rule

def all_of(*rules):
    """AND combinator — all rules must pass. Returns first failure."""
    def combined(data):
        for rule in rules:
            passed, reason = rule(data)
            if not passed:
                return (False, reason)
        return (True, None)
    return combined

def any_of(*rules):
    """OR combinator — at least one rule must pass."""
    def combined(data):
        reasons = []
        for rule in rules:
            passed, reason = rule(data)
            if passed:
                return (True, None)
            reasons.append(reason)
        return (False, " AND ".join(reasons))
    return combined

# --- Define rule sets by composing atomic rules ---
credit_approval = all_of(
    make_rule("age", ">=", 21, "age >= 21"),
    make_rule("score", ">=", 650, "score >= 650"),
    make_rule("employed", "==", True, "employed is True"),
)

premium_offer = all_of(
    make_rule("age", ">=", 21, "age >= 21"),
    make_rule("score", ">=", 700, "score >= 700"),
    make_rule("income", ">=", 70000, "income >= 70000"),
    make_rule("employed", "==", True, "employed is True"),
)

# --- Test applicants ---
applicants = [
    {"name": "Alice", "age": 28, "score": 720, "income": 85000, "employed": True},
    {"name": "Bob", "age": 19, "score": 580, "income": 30000, "employed": True},
    {"name": "Carol", "age": 35, "score": 750, "income": 120000, "employed": False},
    {"name": "Dave", "age": 45, "score": 690, "income": 55000, "employed": True},
]

rule_sets = {"credit_approval": credit_approval, "premium_offer": premium_offer}

print("--- Evaluating applicants ---")
for person in applicants:
    name = person["name"]
    print(f"{name} (age={person['age']}, score={person['score']}, "
          f"income={person['income']}, employed={person['employed']})")
    for rule_name, rule_fn in rule_sets.items():
        passed, reason = rule_fn(person)
        if passed:
            print(f"  {rule_name}: PASS")
        else:
            print(f"  {rule_name}: FAIL -> {reason}")
    print()
Solution
--- Evaluating applicants ---
Alice (age=28, score=720, income=85000, employed=True)
credit_approval: PASS
premium_offer: PASS

Bob (age=19, score=580, income=30000, employed=True)
credit_approval: FAIL -> Failed: score >= 650
premium_offer: FAIL -> Failed: score >= 700

Carol (age=35, score=750, income=120000, employed=False)
credit_approval: FAIL -> Failed: employed is True
premium_offer: FAIL -> Failed: employed is True

Dave (age=45, score=690, income=55000, employed=True)
credit_approval: PASS
premium_offer: FAIL -> Failed: income >= 70000

Architecture of the rule engine:

  1. Atomic rulesmake_rule("score", ">=", 650) creates a function that checks one field against one value. Each rule returns (True, None) on success or (False, reason) on failure.

  2. Combinatorsall_of() (AND) and any_of() (OR) take multiple rules and return a new rule with the same signature. This is function composition.

  3. Rule setscredit_approval = all_of(rule1, rule2, rule3) defines a complete policy as a single callable. No nesting anywhere.

Why this eliminates nesting entirely:

The naive nested approach would be:

if age >= 21:
if score >= 650:
if employed:
return "approved"

The rule engine replaces this with a flat list of checks. Adding a new rule is one line. Removing a rule is deleting one line. Changing AND to OR is swapping all_of for any_of.

Production uses of this pattern:

  • Authorization engines — combine permission rules dynamically
  • Form validation — compose field validators for different forms
  • Feature flagsany_of(is_beta_user, is_internal, has_flag("new_ui"))
  • Business rules — insurance underwriting, loan approval, pricing tiers
Expected Output
--- Evaluating applicants ---
Alice (age=28, score=720, income=85000, employed=True)
  credit_approval: PASS
  premium_offer: PASS

Bob (age=19, score=580, income=30000, employed=True)
  credit_approval: FAIL -> Failed: score >= 650
  premium_offer: FAIL -> Failed: score >= 700

Carol (age=35, score=750, income=120000, employed=False)
  credit_approval: FAIL -> Failed: employed is True
  premium_offer: FAIL -> Failed: employed is True

Dave (age=45, score=690, income=55000, employed=True)
  credit_approval: PASS
  premium_offer: FAIL -> Failed: income >= 70000
Hints

Hint 1: Define atomic rule functions that each check ONE thing and return (True, None) or (False, reason). Then compose them with `all_of()` which runs every rule and returns the first failure.

Hint 2: The key insight: instead of nesting `if age >= 21: if score >= 650: if income >= ...`, you build a list of rules and iterate. Adding/removing rules never changes the structure.

#9Decision Matrix ProcessorHard
decision-matrixdata-drivenpattern-matching

Build a decision matrix that replaces deeply nested conditional logic for shipping method selection. The matrix maps combinations of (region, speed, size) to (method, cost).

Python
class DecisionMatrix:
    """Data-driven decision engine — no nested conditionals."""

    WILDCARD = "*"

    def __init__(self, dimensions, rules, default_result):
        self.dimensions = dimensions
        self.rules = rules  # List of (conditions_dict, result_dict)
        self.default_result = default_result

    def _matches(self, conditions, inputs):
        """Check if all conditions match the inputs."""
        for dim in self.dimensions:
            expected = conditions.get(dim, self.WILDCARD)
            if expected == self.WILDCARD:
                continue
            if isinstance(expected, (list, tuple, set)):
                if inputs.get(dim) not in expected:
                    return False
            elif inputs.get(dim) != expected:
                return False
        return True

    def evaluate(self, **inputs):
        """Find the first matching rule and return its result."""
        for conditions, result in self.rules:
            if self._matches(conditions, inputs):
                return result
        return self.default_result

# --- Define the shipping decision matrix ---
shipping_matrix = DecisionMatrix(
    dimensions=["region", "speed", "size"],
    rules=[
        # Domestic rules
        ({"region": "domestic", "speed": "standard", "size": ("small", "medium")},
         {"method": "ground", "cost": 5.99}),
        ({"region": "domestic", "speed": "express", "size": ("small", "medium")},
         {"method": "air_priority", "cost": 15.99}),
        ({"region": "domestic", "speed": "overnight", "size": ("small", "medium")},
         {"method": "next_day_air", "cost": 25.99}),
        ({"region": "domestic", "speed": "*", "size": "large"},
         {"method": "freight_truck", "cost": 55.00}),
        ({"region": "domestic", "speed": "*", "size": "oversized"},
         {"method": "freight_truck", "cost": 75.00}),

        # International rules
        ({"region": "international", "speed": "standard", "size": "*"},
         {"method": "ocean_freight", "cost": 45.00}),
        ({"region": "international", "speed": "express", "size": ("small", "medium")},
         {"method": "air_international", "cost": 29.99}),
        ({"region": "international", "speed": "express", "size": ("large", "oversized")},
         {"method": "cargo_air", "cost": 65.00}),
        ({"region": "international", "speed": "overnight", "size": ("small", "medium")},
         {"method": "premium_international", "cost": 59.99}),
        ({"region": "international", "speed": "overnight", "size": ("large", "oversized")},
         {"method": "charter_freight", "cost": 89.99}),
    ],
    default_result={"method": "default", "cost": 9.99},
)

# --- Test orders ---
orders = [
    {"region": "domestic", "speed": "standard", "size": "small"},
    {"region": "domestic", "speed": "express", "size": "medium"},
    {"region": "international", "speed": "standard", "size": "large"},
    {"region": "international", "speed": "express", "size": "small"},
    {"region": "domestic", "speed": "overnight", "size": "medium"},
    {"region": "international", "speed": "overnight", "size": "large"},
    {"region": "domestic", "speed": "standard", "size": "oversized"},
    {"region": "unknown", "speed": "express", "size": "small"},
]

print("--- Shipping decisions ---")
for order in orders:
    result = shipping_matrix.evaluate(**order)
    dims = "/".join(order[d] for d in ["region", "speed", "size"])
    print(f"Order: {dims} -> {result['method']}, cost=\${result['cost']}")
Solution
--- Shipping decisions ---
Order: domestic/standard/small -> ground, cost=$5.99
Order: domestic/express/medium -> air_priority, cost=$15.99
Order: international/standard/large -> ocean_freight, cost=$45.00
Order: international/express/small -> air_international, cost=$29.99
Order: domestic/overnight/medium -> next_day_air, cost=$25.99
Order: international/overnight/large -> charter_freight, cost=$89.99
Order: domestic/standard/oversized -> freight_truck, cost=$75.00
Order: unknown/express/small -> default, cost=$9.99

How the decision matrix eliminates nesting:

The naive approach for 3 dimensions with 3-5 values each would create a deeply nested structure:

if region == "domestic":
if speed == "standard":
if size == "small":
...
elif size == "medium":
...
elif size == "large":
...
elif speed == "express":
if size == "small":
...

That is 3+ levels deep and grows multiplicatively. The decision matrix flattens this into a linear list of rules.

Key features of the matrix:

  • Wildcards (*) — a rule can match any value for a dimension, avoiding duplicate rules.
  • Collection matching("small", "medium") matches either value, reducing the number of rules.
  • First-match wins — rules are evaluated in order, so more specific rules go before general ones.
  • Default fallback — if no rule matches, the default result is returned. No else chains needed.
  • Data-driven — the entire decision table can be loaded from a JSON file, database, or admin UI. No code changes needed to add shipping methods.

Real-world applications: pricing engines, tax calculation, insurance rate tables, feature flag targeting, A/B test assignment.

Expected Output
--- Shipping decisions ---
Order: domestic/standard/small -> ground, cost=$5.99
Order: domestic/express/medium -> air_priority, cost=$15.99
Order: international/standard/large -> ocean_freight, cost=$45.00
Order: international/express/small -> air_international, cost=$29.99
Order: domestic/overnight/medium -> next_day_air, cost=$25.99
Order: international/overnight/large -> charter_freight, cost=$89.99
Order: domestic/standard/oversized -> freight_truck, cost=$75.00
Order: unknown/express/small -> default, cost=$9.99
Hints

Hint 1: Build a list of (conditions_dict, result) pairs. To find a match, iterate through the matrix and check if ALL conditions in a row match the input. Use a default/fallback row at the end.

Hint 2: The conditions dict can use special values like "*" for wildcard matching (match any value for that dimension).

#10Command Pattern DispatcherHard
command-patterndispatchnested-switch-replacement

Build a command dispatcher that replaces nested switch/if-elif structures. Each command is registered as a handler function, and the dispatcher routes by name lookup.

Python
class FileSystem:
    """In-memory filesystem with command-pattern dispatch."""

    def __init__(self):
        self.files = {}
        self._commands = {
            "create": self._cmd_create,
            "read": self._cmd_read,
            "update": self._cmd_update,
            "delete": self._cmd_delete,
            "copy": self._cmd_copy,
            "rename": self._cmd_rename,
            "list": self._cmd_list,
        }

    def dispatch(self, command_str):
        """Parse and dispatch a command string. Zero nesting."""
        parts = []
        current = ""
        in_quotes = False
        for ch in command_str:
            if ch == '"' and not in_quotes:
                in_quotes = True
            elif ch == '"' and in_quotes:
                in_quotes = False
            elif ch == ' ' and not in_quotes:
                if current:
                    parts.append(current)
                    current = ""
            else:
                current += ch
        if current:
            parts.append(current)

        cmd_name = parts[0] if parts else ""
        args = parts[1:]

        handler = self._commands.get(cmd_name)
        if handler is None:
            return (False, f"Unknown command: {cmd_name}")
        return handler(args)

    def _cmd_create(self, args):
        if len(args) < 1:
            return (False, "Usage: create <filename> [content]")
        name = args[0]
        content = args[1] if len(args) > 1 else ""
        if name in self.files:
            return (False, f"File already exists: {name}")
        self.files[name] = content
        return (True, f"Created {name} (content: '{content}', size: {len(content)})")

    def _cmd_read(self, args):
        if len(args) < 1:
            return (False, "Usage: read <filename>")
        name = args[0]
        if name not in self.files:
            return (False, f"File not found: {name}")
        return (True, f"Content of {name} -> '{self.files[name]}'")

    def _cmd_update(self, args):
        if len(args) < 2:
            return (False, "Usage: update <filename> <content>")
        name, content = args[0], args[1]
        if name not in self.files:
            return (False, f"File not found: {name}")
        self.files[name] = content
        return (True, f"Updated {name} (new content: '{content}', size: {len(content)})")

    def _cmd_delete(self, args):
        if len(args) < 1:
            return (False, "Usage: delete <filename>")
        name = args[0]
        if name not in self.files:
            return (False, f"File not found: {name}")
        del self.files[name]
        return (True, f"Deleted {name}")

    def _cmd_copy(self, args):
        if len(args) < 2:
            return (False, "Usage: copy <source> <dest>")
        src, dest = args[0], args[1]
        if src not in self.files:
            return (False, f"File not found: {src}")
        if dest in self.files:
            return (False, f"Destination already exists: {dest}")
        self.files[dest] = self.files[src]
        return (True, f"Copied {src} -> {dest}")

    def _cmd_rename(self, args):
        if len(args) < 2:
            return (False, "Usage: rename <old> <new>")
        old, new = args[0], args[1]
        if old not in self.files:
            return (False, f"File not found: {old}")
        if new in self.files:
            return (False, f"Destination already exists: {new}")
        self.files[new] = self.files.pop(old)
        return (True, f"Renamed {old} -> {new}")

    def _cmd_list(self, args):
        if not self.files:
            return (True, "No files")
        names = ", ".join(sorted(self.files.keys()))
        return (True, f"Files: {names}")


# --- Run a sequence of commands ---
fs = FileSystem()
commands = [
    'create report.txt "Q4 Results"',
    'read report.txt',
    'update report.txt "Q4 Results - Final"',
    'copy report.txt backup.txt',
    'list',
    'delete report.txt',
    'read report.txt',
    'rename backup.txt final.txt',
    'unknown_cmd foo',
]

print("--- Running file operations ---")
for cmd in commands:
    success, message = fs.dispatch(cmd)
    status = "OK" if success else "ERROR"
    print(f"> {cmd}")
    print(f"  {status}: {message}")
    print()
Solution
--- Running file operations ---
> create report.txt "Q4 Results"
OK: Created report.txt (content: 'Q4 Results', size: 10)

> read report.txt
OK: Content of report.txt -> 'Q4 Results'

> update report.txt "Q4 Results - Final"
OK: Updated report.txt (new content: 'Q4 Results - Final', size: 18)

> copy report.txt backup.txt
OK: Copied report.txt -> backup.txt

> list
OK: Files: backup.txt, report.txt

> delete report.txt
OK: Deleted report.txt

> read report.txt
ERROR: File not found: report.txt

> rename backup.txt final.txt
OK: Renamed backup.txt -> final.txt

> unknown_cmd foo
ERROR: Unknown command: unknown_cmd

The Command Pattern eliminates nested switch statements entirely:

A naive approach would nest two levels — command type, then argument validation:

if cmd == "create":
if len(args) >= 1:
if name not in files:
...
elif cmd == "read":
if len(args) >= 1:
if name in files:
...
elif cmd == "update":
...

The command pattern replaces this with:

  1. Registration — each command maps to a handler function in self._commands.
  2. Dispatchself._commands.get(cmd_name) does the routing in O(1). No if/elif chain.
  3. Uniform interface — every handler takes args and returns (success, message). The dispatcher does not care what the command does internally.
  4. Self-contained validation — each handler validates its own arguments independently. No shared nesting.

Adding a new command takes exactly 3 steps:

  1. Write the handler method (_cmd_whatever).
  2. Add one entry to self._commands.
  3. Done. No other code changes.

Production uses:

  • CLI toolsargparse subcommands use this exact pattern internally.
  • Chat bots — map /slash commands to handler functions.
  • API routers — Flask and FastAPI map URL patterns to handler functions.
  • Game engines — player actions dispatched to handler functions by name.
  • Undo/redo systems — each command is an object with execute() and undo() methods.
Expected Output
--- Running file operations ---
> create report.txt "Q4 Results"
  OK: Created report.txt (content: 'Q4 Results', size: 10)

> read report.txt
  OK: Content of report.txt -> 'Q4 Results'

> update report.txt "Q4 Results - Final"
  OK: Updated report.txt (new content: 'Q4 Results - Final', size: 18)

> copy report.txt backup.txt
  OK: Copied report.txt -> backup.txt

> list
  OK: Files: backup.txt, report.txt

> delete report.txt
  OK: Deleted report.txt

> read report.txt
  ERROR: File not found: report.txt

> rename backup.txt final.txt
  OK: Renamed backup.txt -> final.txt

> unknown_cmd foo
  ERROR: Unknown command: unknown_cmd
Hints

Hint 1: Register each command as a method and map command names to handler functions in a dictionary. The dispatcher looks up the command name and calls the handler with the arguments.

Hint 2: Each handler has the same signature: takes a list of args and returns (success, message). This uniform interface means the dispatcher has zero conditionals about which command is running.

© 2026 EngineersOfAI. All rights reserved.