Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 97 additions & 20 deletions .amazonq/rules/problem-creation.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,108 @@
# Problem Creation Guide

## Quick Steps
## Assistant Workflow

1. Create JSON: `.templates/leetcode/json/{problem_name}.json`
2. Update Makefile: `PROBLEM ?= your_new_problem`
3. Generate: `make p-gen`
4. Verify: `make lint`
5. **If you edit generated files**: Update JSON template, then `make p-gen FORCE=1` to ensure reproducibility
When user requests a problem by **number** or **name/slug**, the assistant will:

## JSON Template Rules
1. **Scrape** problem data using `.templates/leetcode/scrape.py`
2. **Transform** data into proper JSON template format
3. **Create** JSON file in `.templates/leetcode/json/{problem_name}.json`
4. **Update** Makefile with `PROBLEM ?= {problem_name}`
5. **Generate** problem structure using `make p-gen`
6. **Verify** with `make lint` - fix template issues in JSON if possible, or manually fix generated files if template limitations
7. **Iterate** if JSON fixes: re-run `make p-gen PROBLEM={problem_name} FORCE=1` and `make lint` until passes to ensure reproducibility

- **Copy from reference examples** - don't create from scratch
- **Tree problems**: Use `.templates/leetcode/examples/tree.json5`
- **Basic problems**: Use `.templates/leetcode/examples/basic.json5`
- **Don't add extra fields** - templates are complete
- **Python naming convention**: Use snake_case for all parameter names (e.g., `new_interval` not `newInterval`)
- **If lint fails**: Fix JSON and regenerate, don't edit generated files
- **After any manual edits**: Always update JSON template and verify with `make p-gen FORCE=1`
## Scraping Commands

## Tags (Optional)
```bash
# Fetch by number
poetry run python .templates/leetcode/scrape.py -n 1

# Fetch by slug
poetry run python .templates/leetcode/scrape.py -s "two-sum"
```

## JSON Template Format

Required fields for `.templates/leetcode/json/{problem_name}.json`:

**Reference examples in `.templates/leetcode/examples/` for complete templates:**

- `basic.json5` - Array, string, number problems
- `tree.json5` - Binary tree problems
- `linked_list.json5` - Linked list problems
- `string.json5` - String manipulation problems
- `matrix.json5` - 2D array/matrix problems

```json
"tags": ["grind-75", "blind-75", "neetcode-150", "top-interview"]
{
"problem_name": "two_sum",
"class_name": "TwoSum",
"method_name": "two_sum",
"problem_number": "1",
"problem_title": "Two Sum",
"difficulty": "Easy",
"topics": "Array, Hash Table",
"tags": ["grind-75"],
"problem_description": "Given an array...",
"examples": [{ "input": "nums = [2,7,11,15], target = 9", "output": "[0,1]" }],
"constraints": "- 2 <= nums.length <= 10^4",
"parameters": "nums: list[int], target: int",
"return_type": "list[int]",
"dummy_return": "[]",
"imports": "",
"test_cases": [{ "args": [[2, 7, 11, 15], 9], "expected": [0, 1] }],
"param_names": "nums, target, expected",
"param_names_with_types": "nums: list[int], target: int, expected: list[int]",
"input_description": "nums={nums}, target={target}",
"input_params": "nums, target",
"expected_param": "expected",
"method_args": "nums, target",
"test_setup": "",
"test_logging": "",
"assertion_code": "assert result == expected",
"test_input_setup": "nums = [2, 7, 11, 15]\ntarget = 9",
"expected_output_setup": "expected = [0, 1]"
}
```

## Helper Classes
## Naming Conventions

- **problem_name**: snake_case (e.g., "two_sum", "valid_palindrome")
- **class_name**: PascalCase (e.g., "TwoSum", "ValidPalindrome")
- **method_name**: snake_case (e.g., "two_sum", "is_palindrome")
- **parameters**: Use snake_case for all parameter names

## Special Problem Types

### Tree Problems

- Add `"imports": "from leetcode_py.tree_node import TreeNode"`
- Use `TreeNode | None` for nullable tree parameters
- Test setup: `root = TreeNode.from_list(root_list)`

### Linked List Problems

- Add `"imports": "from leetcode_py.list_node import ListNode"`
- Use `ListNode | None` for nullable list parameters
- Test setup: `head = ListNode.from_list(head_list)`

## Generation Commands

```bash
# Generate problem
make p-gen PROBLEM={problem_name}

# Force regenerate (if files exist)
make p-gen PROBLEM={problem_name} FORCE=1

# Test specific problem
make p-test PROBLEM={problem_name}

# Lint check
make lint
```

## Tags (Optional)

- TreeNode: `from leetcode_py.tree_node import TreeNode`
- ListNode: `from leetcode_py.list_node import ListNode`
- New helpers: Add to `leetcode_py/`
Common tags: `["grind-75", "blind-75", "neetcode-150", "top-interview"]`
2 changes: 1 addition & 1 deletion .templates/leetcode/examples/basic.json5
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"method_name": "two_sum",

// REQUIRED: Problem metadata
"problem_number": "1",
"problem_number": "1", // OPTIONAL: omit if no LeetCode number
"problem_title": "Two Sum",
"difficulty": "Easy",
"topics": "Array, Hash Table",
Expand Down
120 changes: 60 additions & 60 deletions .templates/leetcode/examples/linked_list.json5
Original file line number Diff line number Diff line change
@@ -1,62 +1,62 @@
{
// Linked list problem template
// Use this for problems involving ListNode structures

// REQUIRED: Core identifiers
"problem_name": "reverse_linked_list_ii",
"class_name": "ReverseLinkedListII",
"method_name": "reverse_between",

// REQUIRED: Problem metadata
"problem_number": "92",
"problem_title": "Reverse Linked List II",
"difficulty": "Medium",
"topics": "Linked List",

// OPTIONAL: Problem categorization
"tags": [],

// REQUIRED: Problem description
"problem_description": "Given the head of a singly linked list and two integers left and right where left <= right, reverse the nodes of the list from position left to position right, and return the reversed list.",

// REQUIRED: Examples
"examples": [
{ "input": "head = [1,2,3,4,5], left = 2, right = 4", "output": "[1,4,3,2,5]" },
{ "input": "head = [5], left = 1, right = 1", "output": "[5]" }
],

// REQUIRED: Constraints
"constraints": "- The number of nodes in the list is n.\n- 1 <= n <= 500\n- -500 <= Node.val <= 500\n- 1 <= left <= right <= n",

// REQUIRED: Method signature
"parameters": "head: ListNode | None, left: int, right: int",
"return_type": "ListNode | None",
"dummy_return": "None",

// REQUIRED: ListNode import for linked list problems
"imports": "from leetcode_py.list_node import ListNode",

// REQUIRED: Test cases
"test_cases": [
{ "args": [[1, 2, 3, 4, 5], 2, 4], "expected": [1, 4, 3, 2, 5] },
{ "args": [[5], 1, 1], "expected": [5] },
{ "args": [[1, 2, 3], 1, 3], "expected": [3, 2, 1] }
],

// REQUIRED: Test parameters (use expected_list for linked list problems)
"param_names": "head_list, left, right, expected_list",
"param_names_with_types": "head_list: list[int], left: int, right: int, expected_list: list[int]",
"input_description": "head_list={head_list}, left={left}, right={right}",
"input_params": "head, left, right",
"expected_param": "expected",
"method_args": "head, left, right",

// REQUIRED: Linked list-specific test setup
"test_setup": "head = ListNode.from_list(head_list)\nexpected = ListNode.from_list(expected_list)",
"test_logging": "logger.success(f\"Got result: {result.to_list() if result else []}\")",
"assertion_code": "assert result == expected",

// REQUIRED: Notebook setup for linked list problems
"test_input_setup": "# Example test case\nhead = ListNode.from_list([1, 2, 3, 4, 5])\nleft = 2\nright = 4",
"expected_output_setup": "expected = ListNode.from_list([1, 4, 3, 2, 5])"
// Linked list problem template
// Use this for problems involving ListNode structures

// REQUIRED: Core identifiers
problem_name: "reverse_linked_list_ii",
class_name: "ReverseLinkedListII",
method_name: "reverse_between",

// REQUIRED: Problem metadata
problem_number: "92", // OPTIONAL: omit if no LeetCode number
problem_title: "Reverse Linked List II",
difficulty: "Medium",
topics: "Linked List",

// OPTIONAL: Problem categorization
tags: [],

// REQUIRED: Problem description
problem_description: "Given the head of a singly linked list and two integers left and right where left <= right, reverse the nodes of the list from position left to position right, and return the reversed list.",

// REQUIRED: Examples
examples: [
{ input: "head = [1,2,3,4,5], left = 2, right = 4", output: "[1,4,3,2,5]" },
{ input: "head = [5], left = 1, right = 1", output: "[5]" },
],

// REQUIRED: Constraints
constraints: "- The number of nodes in the list is n.\n- 1 <= n <= 500\n- -500 <= Node.val <= 500\n- 1 <= left <= right <= n",

// REQUIRED: Method signature
parameters: "head: ListNode | None, left: int, right: int",
return_type: "ListNode | None",
dummy_return: "None",

// REQUIRED: ListNode import for linked list problems
imports: "from leetcode_py import ListNode",

// REQUIRED: Test cases
test_cases: [
{ args: [[1, 2, 3, 4, 5], 2, 4], expected: [1, 4, 3, 2, 5] },
{ args: [[5], 1, 1], expected: [5] },
{ args: [[1, 2, 3], 1, 3], expected: [3, 2, 1] },
],

// REQUIRED: Test parameters (use expected_list for linked list problems)
param_names: "head_list, left, right, expected_list",
param_names_with_types: "head_list: list[int], left: int, right: int, expected_list: list[int]",
input_description: "head_list={head_list}, left={left}, right={right}",
input_params: "head, left, right",
expected_param: "expected",
method_args: "head, left, right",

// REQUIRED: Linked list-specific test setup
test_setup: "head = ListNode.from_list(head_list)\nexpected = ListNode.from_list(expected_list)",
test_logging: 'logger.success(f"Got result: {result.to_list() if result else []}")',
assertion_code: "assert result == expected",

// REQUIRED: Notebook setup for linked list problems
test_input_setup: "# Example test case\nhead = ListNode.from_list([1, 2, 3, 4, 5])\nleft = 2\nright = 4",
expected_output_setup: "expected = ListNode.from_list([1, 4, 3, 2, 5])",
}
2 changes: 1 addition & 1 deletion .templates/leetcode/examples/matrix.json5
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"method_name": "rotate",

// REQUIRED: Problem metadata
"problem_number": "48",
"problem_number": "48", // OPTIONAL: omit if no LeetCode number
"problem_title": "Rotate Image",
"difficulty": "Medium",
"topics": "Array, Math, Matrix",
Expand Down
2 changes: 1 addition & 1 deletion .templates/leetcode/examples/string.json5
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"method_name": "is_palindrome",

// REQUIRED: Problem metadata
"problem_number": "125",
"problem_number": "125", // OPTIONAL: omit if no LeetCode number
"problem_title": "Valid Palindrome",
"difficulty": "Easy",
"topics": "Two Pointers, String",
Expand Down
Loading
Loading