update generate files and problem examples to be consistent

This commit is contained in:
Harivansh Rathi 2025-12-14 16:03:56 -05:00
parent 186bb75289
commit 933b466c25
2 changed files with 342 additions and 255 deletions

View file

@ -1,83 +1,54 @@
--- ---
description: Generate a new practice problem with tests description: Generate a new practice problem with tests
argument-hint: [difficulty] [topic] argument-hint: [difficulty] [topic]
allowed-tools: Write, Bash(mkdir:*) allowed-tools: Write, Bash(mkdir:*), Bash(cd:*), Bash(python:*), Bash(rm:*)
--- ---
# Generate a New Practice Problem # Generate a New Practice Problem
**Reference**: @.claude/problem-examples.md for consistent formatting and quality examples. **Reference**: @.claude/problem-examples.md for consistent formatting and quality examples.
You are generating a practical implementation problem for veetcode - a terminal-based coding practice tool. You are generating a practical implementation problem for veetcode.
## Arguments Provided ## Arguments Provided
- Difficulty: $1 (if empty, ask user to choose: easy, medium, or hard) - Difficulty: $1 (if empty, ask user to choose: easy, medium, or hard)
- Topic: $2 (if empty, ask user what concept/topic they want to practice) - Topic: $2 (if empty, ask user what concept/topic they want to practice)
## Problem Style Guide ## Generation Workflow
Generate **practical implementation** problems, NOT abstract LeetCode puzzles: ### Step 1: Gather Requirements
If arguments not provided, ask user:
1. Difficulty: easy, medium, or hard
2. Topic/concept they want to practice
3. Confirm with a one-line problem summary before proceeding
### DO: ### Step 2: Design the Problem (in your head)
- Use real-world business context (e.g., "You are building a payment system...") Before writing any files, mentally design:
- Provide clear function signatures with type hints - The problem scenario (real-world context)
- Include 2-3 concrete examples with explanations - Function signature with types
- List explicit constraints - The ACTUAL SOLUTION (keep this secret - never write to files)
- Focus on practical skills: data transformation, validation, API-like operations - Test cases that verify the solution
- Edge cases
### DON'T: ### Step 3: Create Directory
- Create pure algorithmic puzzles without context
- Use abstract mathematical framing
- Make problems that feel like textbook exercises
## Difficulty Calibration
**Easy** (15-25 min):
- Single data structure (list, dict, set)
- 1-2 core concepts
- 3-4 test cases
- ~20-30 lines solution
**Medium** (30-40 min):
- Multiple data structures
- 3-4 concepts (sorting, hash maps, two pointers)
- 5-6 test cases including edge cases
- ~40-60 lines solution
**Hard** (45-60 min):
- Custom classes or complex data structures
- 5+ concepts (DP, graphs, sliding window + state)
- 7-10 test cases with tricky edge cases
- ~80+ lines solution
## Output Format
### 1. First, confirm with the user:
- The difficulty level
- The topic/concept
- A one-line problem summary
### 2. Generate the problem name
Create a kebab-case name (e.g., `validate-transactions`, `rate-limiter`, `word-frequency`)
### 3. Create the directory
```bash ```bash
mkdir -p problems/{difficulty}/{problem-name} mkdir -p problems/{difficulty}/{problem-name}
``` ```
### 4. Create solution.py ### Step 4: Write solution.py (SKELETON ONLY)
Write ONLY the skeleton - never include the solution!
Structure:
```python ```python
""" """
{Problem Title} {Problem Title}
{Story-based description in 2-3 sentences with real-world context} {Story-based description in 2-3 sentences with real-world context.
Frame it as a real task: "You're building...", "Your team needs...", etc.}
Example 1: Example 1:
Input: {param1} = {value1}, {param2} = {value2} Input: {param1} = {value1}, {param2} = {value2}
Output: {expected} Output: {expected}
Explanation: {why this is the answer} Explanation: {brief explanation}
Example 2: Example 2:
Input: {param1} = {value1}, {param2} = {value2} Input: {param1} = {value1}, {param2} = {value2}
@ -90,59 +61,148 @@ Constraints:
""" """
def {function_name}({params_with_types}) -> {return_type}: def {function_name}({params}: {types}) -> {return_type}:
"""{One-line docstring describing what to return}.""" """{One-line description of what to return}."""
pass # Your implementation here pass # Your implementation here
``` ```
### 5. Create tests.py ### Step 5: Write tests.py (CONSISTENT FORMAT)
Follow this EXACT format for all tests:
Structure:
```python ```python
"""Tests for {problem_name}."""
import pytest import pytest
from solution import {function_name} from solution import {function_name}
def test_basic_case(): class TestBasicCases:
"""Test the example from the problem description.""" """Test basic functionality with typical inputs."""
assert {function_name}(...) == ...
def test_example_one(self):
"""Test first example from problem description."""
assert {function_name}(...) == ...
def test_example_two(self):
"""Test second example from problem description."""
assert {function_name}(...) == ...
def test_typical_case(self):
"""Test another common case."""
assert {function_name}(...) == ...
def test_another_case(): class TestEdgeCases:
"""Test another typical case.""" """Test edge cases and boundary conditions."""
assert {function_name}(...) == ...
def test_empty_input(self):
"""Test with empty or minimal input."""
assert {function_name}(...) == ...
def test_single_element(self):
"""Test with single element input."""
assert {function_name}(...) == ...
def test_boundary_values(self):
"""Test boundary conditions."""
assert {function_name}(...) == ...
def test_edge_case_empty(): # Test count by difficulty:
"""Test empty or minimal input.""" # Easy: 4-5 tests (2 basic, 2-3 edge)
assert {function_name}(...) == ... # Medium: 6-8 tests (3 basic, 3-5 edge)
# Hard: 8-12 tests (4 basic, 4-8 edge)
def test_edge_case_boundary():
"""Test boundary conditions."""
assert {function_name}(...) == ...
# Add more tests based on difficulty:
# Easy: 3-4 tests
# Medium: 5-6 tests
# Hard: 7-10 tests
``` ```
## Example Problems by Topic ### Step 6: VERIFY TESTS WORK (CRITICAL)
**Arrays/Lists**: frequency counting, deduplication, sliding window, two pointers You MUST verify the tests are solvable before telling the user. Run this verification using inline Python - DO NOT write the solution to any file:
**Strings**: parsing, validation, transformation, pattern matching
**Hash Maps**: grouping, caching, lookup optimization
**Trees/Graphs**: traversal, path finding, hierarchy operations
**OOP Design**: class design, state management, encapsulation
**Data Processing**: ETL operations, aggregation, filtering pipelines
## After Generation ```bash
cd problems/{difficulty}/{problem-name} && python -c "
import sys
from types import ModuleType
Tell the user: # Define the actual solution INLINE (user cannot see this)
1. The path to their new problem: `problems/{difficulty}/{problem-name}/` def {function_name}({params}):
2. How to start practicing: `uv run veetcode` then select the problem # YOUR SOLUTION HERE - implement it fully
3. The file to edit: `solution.py` ...
Now, let's generate a problem! If difficulty or topic weren't provided, ask the user to choose. # Create a fake 'solution' module
solution_module = ModuleType('solution')
solution_module.{function_name} = {function_name}
sys.modules['solution'] = solution_module
# Run pytest
import pytest
exit_code = pytest.main(['tests.py', '-v'])
sys.exit(exit_code)
"
```
If tests FAIL:
- Fix the tests (not the solution approach)
- Re-run verification
- Do NOT proceed until all tests pass
If tests PASS:
- Proceed to tell user the problem is ready
### Step 7: Confirm to User
Only after verification passes, tell the user:
```
✅ Problem created and verified!
📁 Location: problems/{difficulty}/{problem-name}/
📝 Edit: solution.py
🚀 Run: uv run veetcode → select "{problem-name}"
Good luck!
```
## Problem Style Guide
### DO:
- Real-world business context ("You're building a payment API...")
- Clear function signatures with type hints
- 2-3 concrete examples with explanations
- Explicit constraints
- Practical skills: data transformation, validation, business logic
### DON'T:
- Abstract algorithmic puzzles without context
- Mathematical framing ("Given an array of integers...")
- Textbook exercise style
- Overly complex for the difficulty level
## Difficulty Calibration
**Easy** (15-25 min):
- Single data structure (list, dict, set)
- 1-2 concepts
- 4-5 test cases
- ~20-30 line solution
**Medium** (30-40 min):
- Multiple data structures
- 3-4 concepts
- 6-8 test cases
- ~40-60 line solution
**Hard** (45-60 min):
- Custom classes or complex structures
- 5+ concepts
- 8-12 test cases
- ~80+ line solution
## Topic Ideas
- **Arrays**: frequency counting, deduplication, sliding window, two pointers
- **Strings**: parsing, validation, transformation, pattern matching
- **Hash Maps**: grouping, caching, lookup optimization, counting
- **Classes**: state management, encapsulation, business entities
- **Data Processing**: filtering, aggregation, transformation pipelines
Now, let's generate a problem! Ask for difficulty and topic if not provided.

View file

@ -2,6 +2,8 @@
Reference examples for generating consistent, high-quality practice problems. Reference examples for generating consistent, high-quality practice problems.
---
## Easy Example: Email Validator ## Easy Example: Email Validator
**solution.py**: **solution.py**:
@ -9,15 +11,14 @@ Reference examples for generating consistent, high-quality practice problems.
""" """
Email Validator Email Validator
You're building a user registration system. Before storing emails in your You're building a user registration system for an e-commerce platform.
database, you need to validate that they follow the correct format. Before storing customer emails in your database, you need to validate
that they follow the correct format to prevent data quality issues.
Write a function that checks if an email address is valid.
Example 1: Example 1:
Input: email = "user@example.com" Input: email = "user@example.com"
Output: True Output: True
Explanation: Has username, @, domain with dot Explanation: Has username, single @, domain with dot
Example 2: Example 2:
Input: email = "invalid-email" Input: email = "invalid-email"
@ -31,8 +32,8 @@ Example 3:
Constraints: Constraints:
- Input is always a string - Input is always a string
- Valid emails have: non-empty username, exactly one @, domain with at least one dot - Valid: non-empty username, exactly one @, domain with at least one dot
- No spaces allowed anywhere in the email - No spaces allowed anywhere
""" """
@ -43,32 +44,45 @@ def is_valid_email(email: str) -> bool:
**tests.py**: **tests.py**:
```python ```python
"""Tests for email-validator."""
import pytest import pytest
from solution import is_valid_email from solution import is_valid_email
def test_valid_simple(): class TestBasicCases:
assert is_valid_email("user@example.com") == True """Test basic functionality with typical inputs."""
def test_valid_simple_email(self):
"""Test standard email format."""
assert is_valid_email("user@example.com") == True
def test_valid_with_subdomain(self):
"""Test email with subdomain."""
assert is_valid_email("user.name@mail.example.co.uk") == True
def test_invalid_missing_at(self):
"""Test email without @ symbol."""
assert is_valid_email("userexample.com") == False
def test_valid_with_dots(): class TestEdgeCases:
assert is_valid_email("user.name@example.co.uk") == True """Test edge cases and boundary conditions."""
def test_empty_string(self):
"""Test with empty input."""
assert is_valid_email("") == False
def test_invalid_no_at(): def test_empty_username(self):
assert is_valid_email("userexample.com") == False """Test with nothing before @."""
assert is_valid_email("@example.com") == False
def test_no_domain_dot(self):
"""Test domain without dot."""
assert is_valid_email("user@examplecom") == False
def test_invalid_no_domain_dot(): def test_spaces_in_email(self):
assert is_valid_email("user@examplecom") == False """Test email containing spaces."""
assert is_valid_email("user @example.com") == False
def test_invalid_empty_username():
assert is_valid_email("@example.com") == False
def test_invalid_spaces():
assert is_valid_email("user @example.com") == False
``` ```
--- ---
@ -80,11 +94,9 @@ def test_invalid_spaces():
""" """
Transaction Grouper Transaction Grouper
You're building a financial dashboard. Users want to see their transactions You're building a financial dashboard for a budgeting app. Users want
grouped by category, with totals calculated for each group. to see their spending grouped by category with totals, so they can
understand where their money is going each month.
Given a list of transactions (each with amount, category, and date),
return a dictionary grouping transactions by category with their total.
Example 1: Example 1:
Input: transactions = [ Input: transactions = [
@ -101,67 +113,85 @@ Example 2:
Explanation: No transactions means empty result Explanation: No transactions means empty result
Constraints: Constraints:
- Each transaction has "amount" (positive int), "category" (string), "date" (string) - Each transaction has "amount" (positive int), "category" (str), "date" (str)
- Categories are case-sensitive - Categories are case-sensitive
- Return categories in any order - Return categories in any order
- Amount is always positive
""" """
def group_transactions(transactions: list[dict]) -> dict[str, int]: def group_transactions(transactions: list[dict]) -> dict[str, int]:
"""Return dictionary mapping category to total amount.""" """Return dictionary mapping each category to its total amount."""
pass # Your implementation here pass # Your implementation here
``` ```
**tests.py**: **tests.py**:
```python ```python
"""Tests for group-transactions."""
import pytest import pytest
from solution import group_transactions from solution import group_transactions
def test_multiple_categories(): class TestBasicCases:
txns = [ """Test basic functionality with typical inputs."""
{"amount": 50, "category": "food", "date": "2024-01-01"},
{"amount": 30, "category": "food", "date": "2024-01-02"}, def test_multiple_categories(self):
{"amount": 100, "category": "transport", "date": "2024-01-01"} """Test grouping across different categories."""
] txns = [
assert group_transactions(txns) == {"food": 80, "transport": 100} {"amount": 50, "category": "food", "date": "2024-01-01"},
{"amount": 30, "category": "food", "date": "2024-01-02"},
{"amount": 100, "category": "transport", "date": "2024-01-01"}
]
assert group_transactions(txns) == {"food": 80, "transport": 100}
def test_single_category(self):
"""Test all transactions in one category."""
txns = [
{"amount": 10, "category": "food", "date": "2024-01-01"},
{"amount": 20, "category": "food", "date": "2024-01-02"},
{"amount": 30, "category": "food", "date": "2024-01-03"}
]
assert group_transactions(txns) == {"food": 60}
def test_single_transaction(self):
"""Test with just one transaction."""
txns = [{"amount": 25, "category": "entertainment", "date": "2024-01-01"}]
assert group_transactions(txns) == {"entertainment": 25}
def test_empty_list(): class TestEdgeCases:
assert group_transactions([]) == {} """Test edge cases and boundary conditions."""
def test_empty_list(self):
"""Test with no transactions."""
assert group_transactions([]) == {}
def test_single_transaction(): def test_case_sensitive_categories(self):
txns = [{"amount": 25, "category": "entertainment", "date": "2024-01-01"}] """Test that categories are case-sensitive."""
assert group_transactions(txns) == {"entertainment": 25} txns = [
{"amount": 10, "category": "Food", "date": "2024-01-01"},
{"amount": 20, "category": "food", "date": "2024-01-02"}
]
result = group_transactions(txns)
assert result == {"Food": 10, "food": 20}
def test_many_categories(self):
"""Test with many different categories."""
txns = [
{"amount": 1, "category": "a", "date": "2024-01-01"},
{"amount": 2, "category": "b", "date": "2024-01-01"},
{"amount": 3, "category": "c", "date": "2024-01-01"},
{"amount": 4, "category": "d", "date": "2024-01-01"}
]
assert group_transactions(txns) == {"a": 1, "b": 2, "c": 3, "d": 4}
def test_single_category_multiple_transactions(): def test_large_amounts(self):
txns = [ """Test with large transaction amounts."""
{"amount": 10, "category": "food", "date": "2024-01-01"}, txns = [
{"amount": 20, "category": "food", "date": "2024-01-02"}, {"amount": 1000000, "category": "salary", "date": "2024-01-01"},
{"amount": 30, "category": "food", "date": "2024-01-03"} {"amount": 500000, "category": "salary", "date": "2024-02-01"}
] ]
assert group_transactions(txns) == {"food": 60} assert group_transactions(txns) == {"salary": 1500000}
def test_case_sensitive_categories():
txns = [
{"amount": 10, "category": "Food", "date": "2024-01-01"},
{"amount": 20, "category": "food", "date": "2024-01-02"}
]
result = group_transactions(txns)
assert result == {"Food": 10, "food": 20}
def test_many_categories():
txns = [
{"amount": 1, "category": "a", "date": "2024-01-01"},
{"amount": 2, "category": "b", "date": "2024-01-01"},
{"amount": 3, "category": "c", "date": "2024-01-01"},
{"amount": 4, "category": "d", "date": "2024-01-01"}
]
assert group_transactions(txns) == {"a": 1, "b": 2, "c": 3, "d": 4}
``` ```
--- ---
@ -173,164 +203,161 @@ def test_many_categories():
""" """
Rate Limiter Rate Limiter
You're building an API gateway that needs to prevent abuse. Implement a You're building an API gateway for a SaaS platform. To prevent abuse
rate limiter that tracks requests per user and enforces limits using and ensure fair usage, you need to implement a rate limiter that tracks
a sliding window algorithm. requests per user using a sliding window algorithm.
The rate limiter should allow at most `max_requests` per user within The limiter should allow at most `max_requests` per user within any
any `window_seconds` time period. `window_seconds` time period.
Example 1: Example 1:
limiter = RateLimiter(max_requests=3, window_seconds=60) limiter = RateLimiter(max_requests=3, window_seconds=60)
limiter.allow_request("user1", timestamp=0) # True (1st request) limiter.allow_request("user1", timestamp=0) # True (1st request)
limiter.allow_request("user1", timestamp=30) # True (2nd request) limiter.allow_request("user1", timestamp=30) # True (2nd request)
limiter.allow_request("user1", timestamp=45) # True (3rd request) limiter.allow_request("user1", timestamp=45) # True (3rd request)
limiter.allow_request("user1", timestamp=50) # False (4th in 60s window) limiter.allow_request("user1", timestamp=50) # False (limit reached)
limiter.allow_request("user1", timestamp=61) # True (1st request expired) limiter.allow_request("user1", timestamp=61) # True (1st expired)
Example 2: Example 2:
limiter = RateLimiter(max_requests=2, window_seconds=10) limiter = RateLimiter(max_requests=2, window_seconds=10)
limiter.allow_request("user1", timestamp=0) # True limiter.allow_request("user1", timestamp=0) # True
limiter.allow_request("user2", timestamp=0) # True (different user) limiter.allow_request("user2", timestamp=0) # True (different user)
limiter.allow_request("user1", timestamp=5) # True limiter.allow_request("user1", timestamp=5) # True
limiter.allow_request("user1", timestamp=8) # False (limit reached) limiter.allow_request("user1", timestamp=8) # False
Constraints: Constraints:
- max_requests >= 1 - max_requests >= 1
- window_seconds >= 1 - window_seconds >= 1
- timestamps are non-negative integers (seconds) - Timestamps are non-negative integers (seconds)
- timestamps are always non-decreasing for a given user - Timestamps are non-decreasing per user
- user_id is a non-empty string - user_id is a non-empty string
""" """
class RateLimiter: class RateLimiter:
"""Sliding window rate limiter.""" """Sliding window rate limiter for API request throttling."""
def __init__(self, max_requests: int, window_seconds: int): def __init__(self, max_requests: int, window_seconds: int):
"""Initialize rate limiter with request limit and time window.""" """Initialize with request limit and time window."""
pass # Your implementation here pass # Your implementation here
def allow_request(self, user_id: str, timestamp: int) -> bool: def allow_request(self, user_id: str, timestamp: int) -> bool:
"""Return True if request is allowed, False if rate limited.""" """Return True if request allowed, False if rate limited."""
pass # Your implementation here pass # Your implementation here
def get_remaining(self, user_id: str, timestamp: int) -> int: def get_remaining(self, user_id: str, timestamp: int) -> int:
"""Return number of remaining requests allowed for user.""" """Return remaining requests allowed for user at timestamp."""
pass # Your implementation here pass # Your implementation here
``` ```
**tests.py**: **tests.py**:
```python ```python
"""Tests for rate-limiter."""
import pytest import pytest
from solution import RateLimiter from solution import RateLimiter
def test_basic_allow(): class TestBasicCases:
limiter = RateLimiter(max_requests=3, window_seconds=60) """Test basic functionality with typical inputs."""
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 30) == True def test_allow_within_limit(self):
assert limiter.allow_request("user1", 45) == True """Test requests within the limit are allowed."""
limiter = RateLimiter(max_requests=3, window_seconds=60)
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 30) == True
assert limiter.allow_request("user1", 45) == True
def test_block_over_limit(self):
"""Test requests over limit are blocked."""
limiter = RateLimiter(max_requests=2, window_seconds=60)
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 30) == True
assert limiter.allow_request("user1", 45) == False
def test_multiple_users_independent(self):
"""Test each user has independent limits."""
limiter = RateLimiter(max_requests=1, window_seconds=60)
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user2", 0) == True
assert limiter.allow_request("user1", 30) == False
assert limiter.allow_request("user2", 30) == False
def test_get_remaining_basic(self):
"""Test remaining count decreases with requests."""
limiter = RateLimiter(max_requests=3, window_seconds=60)
assert limiter.get_remaining("user1", 0) == 3
limiter.allow_request("user1", 0)
assert limiter.get_remaining("user1", 0) == 2
def test_rate_limit_exceeded(): class TestEdgeCases:
limiter = RateLimiter(max_requests=2, window_seconds=60) """Test edge cases and boundary conditions."""
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 30) == True
assert limiter.allow_request("user1", 45) == False
def test_window_expiration(self):
"""Test old requests expire from window."""
limiter = RateLimiter(max_requests=2, window_seconds=60)
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 30) == True
assert limiter.allow_request("user1", 45) == False
assert limiter.allow_request("user1", 61) == True
def test_window_expiration(): def test_single_request_limit(self):
limiter = RateLimiter(max_requests=2, window_seconds=60) """Test with limit of 1 request."""
assert limiter.allow_request("user1", 0) == True limiter = RateLimiter(max_requests=1, window_seconds=10)
assert limiter.allow_request("user1", 30) == True assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 45) == False assert limiter.allow_request("user1", 5) == False
assert limiter.allow_request("user1", 61) == True # First request expired assert limiter.allow_request("user1", 11) == True
def test_new_user_full_allowance(self):
"""Test new users start with full allowance."""
limiter = RateLimiter(max_requests=5, window_seconds=60)
limiter.allow_request("user1", 0)
assert limiter.get_remaining("new_user", 20) == 5
def test_multiple_users_independent(): def test_remaining_after_expiration(self):
limiter = RateLimiter(max_requests=1, window_seconds=60) """Test remaining increases as requests expire."""
assert limiter.allow_request("user1", 0) == True limiter = RateLimiter(max_requests=2, window_seconds=60)
assert limiter.allow_request("user2", 0) == True limiter.allow_request("user1", 0)
assert limiter.allow_request("user1", 30) == False limiter.allow_request("user1", 30)
assert limiter.allow_request("user2", 30) == False assert limiter.get_remaining("user1", 30) == 0
assert limiter.get_remaining("user1", 61) == 1
def test_rapid_same_timestamp(self):
"""Test multiple requests at same timestamp."""
limiter = RateLimiter(max_requests=3, window_seconds=1)
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 0) == False
def test_get_remaining(): def test_exact_window_boundary(self):
limiter = RateLimiter(max_requests=3, window_seconds=60) """Test behavior at exact window boundary."""
assert limiter.get_remaining("user1", 0) == 3 limiter = RateLimiter(max_requests=1, window_seconds=10)
limiter.allow_request("user1", 0) assert limiter.allow_request("user1", 0) == True
assert limiter.get_remaining("user1", 0) == 2 assert limiter.allow_request("user1", 10) == False
limiter.allow_request("user1", 30) assert limiter.allow_request("user1", 11) == True
assert limiter.get_remaining("user1", 30) == 1
def test_get_remaining_after_expiration():
limiter = RateLimiter(max_requests=2, window_seconds=60)
limiter.allow_request("user1", 0)
limiter.allow_request("user1", 30)
assert limiter.get_remaining("user1", 30) == 0
assert limiter.get_remaining("user1", 61) == 1 # First expired
def test_single_request_limit():
limiter = RateLimiter(max_requests=1, window_seconds=10)
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 5) == False
assert limiter.allow_request("user1", 10) == False
assert limiter.allow_request("user1", 11) == True
def test_new_user_has_full_allowance():
limiter = RateLimiter(max_requests=5, window_seconds=60)
limiter.allow_request("user1", 0)
limiter.allow_request("user1", 10)
assert limiter.get_remaining("new_user", 20) == 5
def test_rapid_requests():
limiter = RateLimiter(max_requests=3, window_seconds=1)
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 0) == True
assert limiter.allow_request("user1", 0) == False
``` ```
--- ---
## Topic Ideas by Concept ## Topic Quick Reference
### Arrays/Lists ### Arrays/Lists
- Remove duplicates preserving order - Frequency counting, deduplication, sliding window
- Find pairs that sum to target - Two pointers, rotation, merging sorted arrays
- Merge sorted arrays
- Rotate array by k positions
- Find missing number in sequence
### Strings ### Strings
- Validate email/URL/phone format - Validation (email, URL, phone), parsing CSV/JSON
- Count word frequency - Pattern matching, compression, transformation
- Find longest palindromic substring
- Parse CSV line with quotes
- Compress string (aaabbc -> a3b2c1)
### Hash Maps ### Hash Maps
- Group items by property - Grouping by property, counting occurrences
- Find first non-repeating character - Two sum variants, caching, anagram detection
- Two sum / three sum variations
- LRU Cache implementation
- Anagram grouping
### Classes/OOP ### Classes/OOP
- Shopping cart with discounts - Shopping cart, bank account, task scheduler
- Bank account with transaction history - State machines, event systems, entity modeling
- Task scheduler with priorities
- Event emitter / pub-sub
- State machine implementation
### Data Processing ### Data Processing
- Filter and transform records - Filter/map/reduce pipelines, aggregation
- Aggregate statistics - Interval merging, pagination, deduplication
- Merge overlapping intervals
- Topological sort of dependencies
- Pagination with cursor