diff --git a/.amazonq/plans/check_problem_lists.py b/.amazonq/plans/check_problem_lists.py deleted file mode 100644 index 430c5fe..0000000 --- a/.amazonq/plans/check_problem_lists.py +++ /dev/null @@ -1,66 +0,0 @@ -# TODO: temporary use only while completing ongoing list - -import json -import sys -from pathlib import Path - -# Import the tuple lists -sys.path.append(str(Path(__file__).parent.parent.parent)) -from algo_master_75_tuples import algo_master_75_tuples -from blind_75_tuples import blind_75_tuples -from neetcode_150_tuples import neetcode_150_tuples - - -def get_existing_problems(): - """Get problem numbers from existing JSON files.""" - json_dir = Path(__file__).parent.parent.parent / "leetcode_py/cli/resources/leetcode/json/problems" - existing_problems = set() - - for json_file in json_dir.glob("*.json"): - try: - with open(json_file, "r") as f: - data = json.load(f) - problem_number = int(data.get("problem_number", 0)) - if problem_number > 0: - existing_problems.add(problem_number) - except (json.JSONDecodeError, ValueError, KeyError): - continue - - return existing_problems - - -def check_problem_list(name, problem_tuples, existing_problems): - """Check how many problems from a list are available.""" - problem_numbers = {num for num, _ in problem_tuples} - have = problem_numbers & existing_problems - missing = problem_numbers - existing_problems - - print(f"\n=== {name} ===") - print(f"Total problems: {len(problem_numbers)}") - print(f"Problems you have: {len(have)} ({len(have)/len(problem_numbers)*100:.1f}%)") - print(f"Problems missing: {len(missing)} ({len(missing)/len(problem_numbers)*100:.1f}%)") - - if missing: - print(f"Missing problems: {sorted(missing)}") - - return have, missing - - -def main(): - existing = get_existing_problems() - print(f"Total existing problems in JSON: {len(existing)}") - - # Check each list - blind_have, blind_missing = check_problem_list("BLIND 75", blind_75_tuples, existing) - neetcode_have, neetcode_missing = check_problem_list("NEETCODE 150", neetcode_150_tuples, existing) - algo_have, algo_missing = check_problem_list("ALGO MASTER 75", algo_master_75_tuples, existing) - - # Summary - print("\n=== SUMMARY ===") - print(f"Blind 75: {len(blind_have)}/75 ({len(blind_have)/75*100:.1f}%)") - print(f"NeetCode 150: {len(neetcode_have)}/150 ({len(neetcode_have)/150*100:.1f}%)") - print(f"Algo Master 75: {len(algo_have)}/75 ({len(algo_have)/75*100:.1f}%)") - - -if __name__ == "__main__": - main() diff --git a/.amazonq/plans/export_tags.py b/.amazonq/plans/export_tags.py deleted file mode 100644 index 9b3db10..0000000 --- a/.amazonq/plans/export_tags.py +++ /dev/null @@ -1,81 +0,0 @@ -# TODO: temporary use only while completing ongoing list - -import json -import sys -from pathlib import Path - -# Import the tuple lists -sys.path.append(str(Path(__file__).parent.parent.parent)) -from algo_master_75_tuples import algo_master_75_tuples -from neetcode_150_tuples import neetcode_150_tuples - - -def get_existing_problems(): - """Get problem numbers and names from existing JSON files.""" - json_dir = Path(__file__).parent.parent.parent / "leetcode_py/cli/resources/leetcode/json/problems" - existing_problems = {} - - for json_file in json_dir.glob("*.json"): - try: - with open(json_file, "r") as f: - data = json.load(f) - problem_number = int(data.get("problem_number", 0)) - if problem_number > 0: - existing_problems[problem_number] = json_file.stem - except (json.JSONDecodeError, ValueError, KeyError): - continue - - return existing_problems - - -def get_tag_problems(problem_tuples, existing_problems): - """Get problem names for existing problems from a tuple list.""" - problem_names = [] - for num, _ in problem_tuples: - if num in existing_problems: - problem_names.append(existing_problems[num]) - return sorted(problem_names) - - -def export_tags(): - """Export tags.json5 format for the three problem lists.""" - existing = get_existing_problems() - - # Get problem names for each list - neetcode_150_names = get_tag_problems(neetcode_150_tuples, existing) - algo_master_75_names = get_tag_problems(algo_master_75_tuples, existing) - - # Generate tags.json5 content - content = """{\n""" - - # NeetCode 150 - content += f" // NeetCode 150 - {len(neetcode_150_names)} problems\n" - content += ' "neetcode-150": [\n' - for name in neetcode_150_names: - content += f' "{name}",\n' - content += " ],\n\n" - - # Algo Master 75 - content += f" // Algo Master 75 - {len(algo_master_75_names)} problems\n" - content += ' "algo-master-75": [\n' - for name in algo_master_75_names: - content += f' "{name}",\n' - content += " ],\n\n" - - # Test tag - content += " // Test tag for development and testing\n" - content += ' test: ["binary_search", "two_sum", "valid_palindrome"],\n' - content += "}\n" - - # Write to file - output_file = Path(__file__).parent / "new_tags.json5" - with open(output_file, "w") as f: - f.write(content) - - print(f"Exported tags to {output_file}") - print(f"NeetCode 150: {len(neetcode_150_names)} problems") - print(f"Algo Master 75: {len(algo_master_75_names)} problems") - - -if __name__ == "__main__": - export_tags() diff --git a/.cursor/.dev/check_problem_lists.py b/.cursor/.dev/check_problem_lists.py new file mode 100644 index 0000000..84b19c0 --- /dev/null +++ b/.cursor/.dev/check_problem_lists.py @@ -0,0 +1,61 @@ +# TODO: temporary use only while completing ongoing list + +import sys +from pathlib import Path + +# Import the problem lists +sys.path.append(str(Path(__file__).parent.parent.parent)) +from problem_lists import available_lists +from problem_lists.utils import get_existing_problems + + +def check_problem_list(tag_name, problem_tuples, existing_problems): + """Check how many problems from a list are available.""" + problem_numbers = {num for num, _ in problem_tuples} + have = problem_numbers & existing_problems + missing = problem_numbers - existing_problems + + print(f"\n=== {tag_name.upper()} ===") + print(f"Total problems: {len(problem_numbers)}") + print(f"Problems you have: {len(have)} ({len(have)/len(problem_numbers)*100:.1f}%)") + print(f"Problems missing: {len(missing)} ({len(missing)/len(problem_numbers)*100:.1f}%)") + + if missing: + print(f"Missing problems: {sorted(missing)}") + + return have, missing + + +def check_problem_lists(tag_names=None): + """Check problem lists for available problems.""" + if tag_names is None: + tag_names = list(available_lists.keys()) + + existing = get_existing_problems() + print(f"Total existing problems in JSON: {len(existing)}") + + results = {} + + # Check each specified list + for tag_name, problem_tuples in available_lists.items(): + if tag_name in tag_names: + have, missing = check_problem_list(tag_name, problem_tuples, existing) + results[tag_name] = {"have": have, "missing": missing, "total": len(problem_tuples)} + + # Summary + print("\n=== SUMMARY ===") + for tag_name, result in results.items(): + total = result["total"] + have_count = len(result["have"]) + percentage = have_count / total * 100 + print(f"{tag_name}: {have_count}/{total} ({percentage:.1f}%)") + + return results + + +def main(): + check_problem_lists() + + +if __name__ == "__main__": + main() diff --git a/.cursor/.dev/next_problem.py b/.cursor/.dev/next_problem.py new file mode 100644 index 0000000..7adc9e6 --- /dev/null +++ b/.cursor/.dev/next_problem.py @@ -0,0 +1,75 @@ +# TODO: temporary use only while completing ongoing list + +import sys +from pathlib import Path + +# Import the problem lists +sys.path.append(str(Path(__file__).parent.parent.parent)) +from problem_lists import available_lists +from problem_lists.utils import get_existing_problems + + +def get_next_problem(tag_names=None): + """Get the next problem to work on from the list with the lowest missing problems.""" + if tag_names is None: + tag_names = list(available_lists.keys()) + + existing_problems = get_existing_problems() + + # Find the list with the lowest missing problems + best_list = None + min_missing = float("inf") + missing_problems = [] + + for tag_name, problem_tuples in available_lists.items(): + if tag_name in tag_names: + problem_numbers = {num for num, _ in problem_tuples} + missing = problem_numbers - existing_problems + missing_count = len(missing) + + if missing_count > 0 and missing_count < min_missing: + min_missing = missing_count + best_list = tag_name + missing_problems = sorted(missing) + + if not missing_problems: + print("No missing problems found in any of the specified lists!") + return None + + # Get the first missing problem from the best list + next_problem_number = missing_problems[0] + + # Find the problem name + problem_tuples = available_lists[best_list] + problem_name = None + for num, name in problem_tuples: + if num == next_problem_number: + problem_name = name + break + + result = { + "tag_name": best_list, + "problem_number": next_problem_number, + "problem_name": problem_name, + "missing_count": min_missing, + "total_in_list": len(available_lists[best_list]), + } + + return result + + +def main(): + next_problem = get_next_problem() + if next_problem: + completed = next_problem["total_in_list"] - next_problem["missing_count"] + total = next_problem["total_in_list"] + percentage = completed / total * 100 + + print("\n🎯 Next problem to work on:") + print(f" Problem #{next_problem['problem_number']} - {next_problem['problem_name']}") + print(f" Tag: {next_problem['tag_name']}") + print(f" Progress: {completed}/{total} ({percentage:.1f}%)") + + +if __name__ == "__main__": + main() diff --git a/.cursor/.dev/problem_lists/__init__.py b/.cursor/.dev/problem_lists/__init__.py new file mode 100644 index 0000000..a226c45 --- /dev/null +++ b/.cursor/.dev/problem_lists/__init__.py @@ -0,0 +1,7 @@ +from . import algo_master_75, blind_75, neetcode_150 + +available_lists = { + neetcode_150.tag_name: neetcode_150.problems_list, + algo_master_75.tag_name: algo_master_75.problems_list, + blind_75.tag_name: blind_75.problem_list, +} diff --git a/.amazonq/plans/algo_master_75_tuples.py b/.cursor/.dev/problem_lists/algo_master_75.py similarity index 98% rename from .amazonq/plans/algo_master_75_tuples.py rename to .cursor/.dev/problem_lists/algo_master_75.py index 255422e..ae91c14 100644 --- a/.amazonq/plans/algo_master_75_tuples.py +++ b/.cursor/.dev/problem_lists/algo_master_75.py @@ -1,4 +1,6 @@ -algo_master_75_tuples = [ +tag_name = "algo-master-75" + +problems_list = [ (2, "Add Two Numbers"), (3, "Longest Substring Without Repeating Characters"), (4, "Median of Two Sorted Arrays"), diff --git a/.amazonq/plans/blind_75_tuples.py b/.cursor/.dev/problem_lists/blind_75.py similarity index 98% rename from .amazonq/plans/blind_75_tuples.py rename to .cursor/.dev/problem_lists/blind_75.py index bf6af06..813be85 100644 --- a/.amazonq/plans/blind_75_tuples.py +++ b/.cursor/.dev/problem_lists/blind_75.py @@ -1,4 +1,6 @@ -blind_75_tuples = [ +tag_name = "blind-75" + +problem_list = [ (1, "Two Sum"), (3, "Longest Substring Without Repeating Characters"), (5, "Longest Palindromic Substring"), diff --git a/.amazonq/plans/neetcode_150_tuples.py b/.cursor/.dev/problem_lists/neetcode_150.py similarity index 99% rename from .amazonq/plans/neetcode_150_tuples.py rename to .cursor/.dev/problem_lists/neetcode_150.py index 51753de..da7bf30 100644 --- a/.amazonq/plans/neetcode_150_tuples.py +++ b/.cursor/.dev/problem_lists/neetcode_150.py @@ -1,4 +1,6 @@ -neetcode_150_tuples = [ +tag_name = "neetcode-150" + +problems_list = [ (1, "Two Sum"), (2, "Add Two Numbers"), (3, "Longest Substring Without Repeating Characters"), diff --git a/.cursor/.dev/problem_lists/utils.py b/.cursor/.dev/problem_lists/utils.py new file mode 100644 index 0000000..f072215 --- /dev/null +++ b/.cursor/.dev/problem_lists/utils.py @@ -0,0 +1,9 @@ +"""Shared utilities for problem list management.""" + +from leetcode_py.cli.utils.problem_finder import _build_problem_number_cache + + +def get_existing_problems(): + """Get problem numbers from existing JSON files.""" + cache = _build_problem_number_cache() + return set(cache.keys()) diff --git a/.cursor/.dev/update_tags.py b/.cursor/.dev/update_tags.py new file mode 100644 index 0000000..e725c52 --- /dev/null +++ b/.cursor/.dev/update_tags.py @@ -0,0 +1,94 @@ +# TODO: temporary use only while completing ongoing list + +import json +import sys +from pathlib import Path + +# Import the problem lists and resources +sys.path.append(str(Path(__file__).parent.parent.parent)) +from problem_lists import available_lists + +from leetcode_py.cli.utils.problem_finder import find_problems_by_tag + + +def get_existing_problems(): + """Get problem numbers and names from existing JSON files.""" + json_dir = Path(__file__).parent.parent.parent / "leetcode_py/cli/resources/leetcode/json/problems" + existing_problems = {} + + for json_file in json_dir.glob("*.json"): + try: + with open(json_file, "r") as f: + data = json.load(f) + problem_number = int(data.get("problem_number", 0)) + if problem_number > 0: + existing_problems[problem_number] = json_file.stem + except (json.JSONDecodeError, ValueError, KeyError): + continue + + return existing_problems + + +def get_tag_problems(problem_tuples, existing_problems): + """Get problem names for existing problems from a tuple list.""" + problem_names = [] + for num, _ in problem_tuples: + if num in existing_problems: + problem_names.append(existing_problems[num]) + return sorted(problem_names) + + +def update_tags(tag_names=None): + """Update tags.json5 format for the specified tag names, comparing with existing tags.""" + if tag_names is None: + tag_names = list(available_lists.keys()) + + existing_problems = get_existing_problems() + + # Generate update tags content with only missing problems + update_tags = {} + changes_found = False + + for tag_name, problem_tuples in available_lists.items(): + if tag_name in tag_names: + # Get new problems from our problem lists + new_problem_names = set(get_tag_problems(problem_tuples, existing_problems)) + + # Get existing problems using the recursive tag resolution + existing_problem_names = set(find_problems_by_tag(tag_name)) + + # Only include missing problems (added, not removed) + missing_problems = new_problem_names - existing_problem_names + removed_problems = existing_problem_names - new_problem_names + + if missing_problems or removed_problems: + changes_found = True + + # Only include missing problems in the update + if missing_problems: + update_tags[tag_name] = sorted(missing_problems) + print( + f"{tag_name}: Missing {len(missing_problems)} problems: {sorted(missing_problems)}" + ) + + if removed_problems: + print( + f"{tag_name}: Removed {len(removed_problems)} problems: {sorted(removed_problems)} (not included in update)" + ) + + if not changes_found: + print("No changes found in any of the specified tags.") + return + + # Generate update_tags.json content with only missing problems + output_file = Path(__file__).parent / "update_tags.json" + with open(output_file, "w") as f: + json.dump(update_tags, f, indent=4) + + print(f"\nUpdate tags with missing problems written to {output_file}") + print(f"Total tags with missing problems: {len(update_tags)}") + + +if __name__ == "__main__": + # Update all available lists by default + update_tags() diff --git a/.amazonq/rules/problem-creation.md b/.cursor/commands/problem-creation.md similarity index 98% rename from .amazonq/rules/problem-creation.md rename to .cursor/commands/problem-creation.md index c4da01a..19277ad 100644 --- a/.amazonq/rules/problem-creation.md +++ b/.cursor/commands/problem-creation.md @@ -19,6 +19,14 @@ When user requests a problem by **number** or **name/slug**, the assistant will: 8. **Verify** with `make p-lint` - fix template issues in JSON if possible, or manually fix generated files if template limitations 9. **Iterate** if JSON fixes: re-run `make p-gen PROBLEM={problem_name} FORCE=1` and `make p-lint` until passes to ensure reproducibility +**If user does not specify a problem number or name/slug**, run: + +```bash +poetry run python .cursor/.dev/next_problem.py +``` + +This will suggest the next problem to work on from the available problem lists based on completion status. + ## Scraping Commands ```bash diff --git a/.amazonq/rules/test-quality-assurance.md b/.cursor/commands/test-quality-assurance.md similarity index 100% rename from .amazonq/rules/test-quality-assurance.md rename to .cursor/commands/test-quality-assurance.md diff --git a/.amazonq/rules/development-rules.md b/.cursor/rules/development-rules.mdc similarity index 98% rename from .amazonq/rules/development-rules.md rename to .cursor/rules/development-rules.mdc index 8d11859..ee54a45 100644 --- a/.amazonq/rules/development-rules.md +++ b/.cursor/rules/development-rules.mdc @@ -1,3 +1,6 @@ +--- +alwaysApply: true +--- # LeetCode Repository Rules ## Discussion Mode diff --git a/Makefile b/Makefile index ac32679..5d3e60d 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ PYTHON_VERSION = 3.13 -PROBLEM ?= jump_game +PROBLEM ?= same_tree FORCE ?= 0 COMMA := , diff --git a/README.md b/README.md index c4ae951..82eeb33 100644 --- a/README.md +++ b/README.md @@ -222,8 +222,8 @@ To extend the problem collection beyond the current catalog, leverage an LLM ass **Required LLM Context**: Include these rule files in your LLM context for automated problem generation and test enhancement: -- [`.amazonq/rules/problem-creation.md`](https://github.com/wisarootl/leetcode-py/blob/main/.amazonq/rules/problem-creation.md) - Complete problem generation workflow -- [`.amazonq/rules/test-quality-assurance.md`](https://github.com/wisarootl/leetcode-py/blob/main/.amazonq/rules/test-quality-assurance.md) - Test enhancement and reproducibility verification +- [`.cursor/commands/problem-creation.md`](https://github.com/wisarootl/leetcode-py/blob/main/.cursor/commands/problem-creation.md) - Complete problem generation workflow +- [`.cursor/commands/test-quality-assurance.md`](https://github.com/wisarootl/leetcode-py/blob/main/.cursor/commands/test-quality-assurance.md) - Test enhancement and reproducibility verification **Manual Check**: Find problems needing more test cases: diff --git a/docs/llm-assisted-problem-creation.md b/docs/llm-assisted-problem-creation.md index 073cd2e..5cedb16 100644 --- a/docs/llm-assisted-problem-creation.md +++ b/docs/llm-assisted-problem-creation.md @@ -12,9 +12,9 @@ The LLM-assisted workflow enables you to add new problems to your collection wit For optimal results, include these rule files in your LLM context: -- [`.amazonq/rules/problem-creation.md`](../.amazonq/rules/problem-creation.md) - Complete problem generation workflow -- [`.amazonq/rules/test-quality-assurance.md`](../.amazonq/rules/test-quality-assurance.md) - Test enhancement and reproducibility verification -- [`.amazonq/rules/development-rules.md`](../.amazonq/rules/development-rules.md) - Code standards and testing patterns +- [`.cursor/commands/problem-creation.md`](../.cursor/commands/problem-creation.md) - Complete problem generation workflow +- [`.cursor/commands/test-quality-assurance.md`](../.cursor/commands/test-quality-assurance.md) - Test enhancement and reproducibility verification +- [`.cursor/rules/development-rules.mdc`](../.cursor/rules/development-rules.mdc) - Code standards and testing patterns ### Setup Your IDE diff --git a/leetcode/same_tree/README.md b/leetcode/same_tree/README.md new file mode 100644 index 0000000..54c11bf --- /dev/null +++ b/leetcode/same_tree/README.md @@ -0,0 +1,47 @@ +# Same Tree + +**Difficulty:** Easy +**Topics:** Tree, Depth-First Search, Breadth-First Search, Binary Tree +**Tags:** blind-75 + +**LeetCode:** [Problem 100](https://leetcode.com/problems/same-tree/description/) + +## Problem Description + +Given the roots of two binary trees `p` and `q`, write a function to check if they are the same or not. + +Two binary trees are considered the same if they are structurally identical, and the nodes have the same value. + +## Examples + +### Example 1: + +![Example 1](https://assets.leetcode.com/uploads/2020/12/20/ex1.jpg) + +``` +Input: p = [1,2,3], q = [1,2,3] +Output: true +``` + +### Example 2: + +![Example 2](https://assets.leetcode.com/uploads/2020/12/20/ex2.jpg) + +``` +Input: p = [1,2], q = [1,null,2] +Output: false +``` + +### Example 3: + +![Example 3](https://assets.leetcode.com/uploads/2020/12/20/ex3.jpg) + +``` +Input: p = [1,2,1], q = [1,1,2] +Output: false +``` + +## Constraints + +- The number of nodes in both trees is in the range [0, 100]. +- -10^4 <= Node.val <= 10^4 diff --git a/.amazonq/plans/.gitkeep b/leetcode/same_tree/__init__.py similarity index 100% rename from .amazonq/plans/.gitkeep rename to leetcode/same_tree/__init__.py diff --git a/leetcode/same_tree/helpers.py b/leetcode/same_tree/helpers.py new file mode 100644 index 0000000..7a3c493 --- /dev/null +++ b/leetcode/same_tree/helpers.py @@ -0,0 +1,13 @@ +from leetcode_py import TreeNode + + +def run_is_same_tree(solution_class: type, p_list: list[int | None], q_list: list[int | None]): + p = TreeNode[int].from_list(p_list) + q = TreeNode[int].from_list(q_list) + implementation = solution_class() + return implementation.is_same_tree(p, q) + + +def assert_is_same_tree(result: bool, expected: bool) -> bool: + assert result == expected + return True diff --git a/leetcode/same_tree/playground.py b/leetcode/same_tree/playground.py new file mode 100644 index 0000000..a1caea3 --- /dev/null +++ b/leetcode/same_tree/playground.py @@ -0,0 +1,30 @@ +# --- +# jupyter: +# jupytext: +# text_representation: +# extension: .py +# format_name: percent +# format_version: '1.3' +# jupytext_version: 1.17.3 +# kernelspec: +# display_name: leetcode-py-py3.13 +# language: python +# name: python3 +# --- + +# %% +from helpers import assert_is_same_tree, run_is_same_tree +from solution import Solution + +# %% +# Example test case +p_list: list[int | None] = [1, 2, 3] +q_list: list[int | None] = [1, 2, 3] +expected = True + +# %% +result = run_is_same_tree(Solution, p_list, q_list) +result + +# %% +assert_is_same_tree(result, expected) diff --git a/leetcode/same_tree/solution.py b/leetcode/same_tree/solution.py new file mode 100644 index 0000000..62affc1 --- /dev/null +++ b/leetcode/same_tree/solution.py @@ -0,0 +1,22 @@ +from leetcode_py import TreeNode + + +class Solution: + + # Time: O(min(m, n)) where m and n are the number of nodes in the two trees + # Space: O(min(m, n)) for the recursion stack + def is_same_tree(self, p: TreeNode[int] | None, q: TreeNode[int] | None) -> bool: + # Base case: both nodes are None + if p is None and q is None: + return True + + # Base case: one node is None, the other is not + if p is None or q is None: + return False + + # Check if current nodes have the same value + if p.val != q.val: + return False + + # Recursively check left and right subtrees + return self.is_same_tree(p.left, q.left) and self.is_same_tree(p.right, q.right) diff --git a/leetcode/same_tree/test_solution.py b/leetcode/same_tree/test_solution.py new file mode 100644 index 0000000..3bf689d --- /dev/null +++ b/leetcode/same_tree/test_solution.py @@ -0,0 +1,32 @@ +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_is_same_tree, run_is_same_tree +from .solution import Solution + + +class TestSameTree: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize( + "p_list, q_list, expected", + [ + ([1, 2, 3], [1, 2, 3], True), + ([1, 2], [1, None, 2], False), + ([1, 2, 1], [1, 1, 2], False), + ([], [], True), + ([1], [1], True), + ([1], [2], False), + ([1, None, 2], [1, 2], False), + ([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], True), + ([1, 2, 3, 4, 5], [1, 2, 3, 4, 6], False), + ([1, 2, 3, None, 4], [1, 2, 3, None, 4], True), + ([1, 2, 3, None, 4], [1, 2, 3, 4, None], False), + ], + ) + def test_is_same_tree(self, p_list: list[int | None], q_list: list[int | None], expected: bool): + result = run_is_same_tree(Solution, p_list, q_list) + assert_is_same_tree(result, expected) diff --git a/leetcode_py/cli/resources/leetcode/json/problems/same_tree.json b/leetcode_py/cli/resources/leetcode/json/problems/same_tree.json new file mode 100644 index 0000000..3fa5f8c --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/same_tree.json @@ -0,0 +1,67 @@ +{ + "problem_name": "same_tree", + "solution_class_name": "Solution", + "problem_number": "100", + "problem_title": "Same Tree", + "difficulty": "Easy", + "topics": "Tree, Depth-First Search, Breadth-First Search, Binary Tree", + "_tags": { "list": ["blind-75"] }, + "readme_description": "Given the roots of two binary trees `p` and `q`, write a function to check if they are the same or not.\n\nTwo binary trees are considered the same if they are structurally identical, and the nodes have the same value.", + "_readme_examples": { + "list": [ + { + "content": "![Example 1](https://assets.leetcode.com/uploads/2020/12/20/ex1.jpg)\n\n```\nInput: p = [1,2,3], q = [1,2,3]\nOutput: true\n```" + }, + { + "content": "![Example 2](https://assets.leetcode.com/uploads/2020/12/20/ex2.jpg)\n\n```\nInput: p = [1,2], q = [1,null,2]\nOutput: false\n```" + }, + { + "content": "![Example 3](https://assets.leetcode.com/uploads/2020/12/20/ex3.jpg)\n\n```\nInput: p = [1,2,1], q = [1,1,2]\nOutput: false\n```" + } + ] + }, + "readme_constraints": "- The number of nodes in both trees is in the range [0, 100].\n- -10^4 <= Node.val <= 10^4", + "readme_additional": "", + "helpers_imports": "from leetcode_py import TreeNode", + "helpers_content": "", + "helpers_run_name": "is_same_tree", + "helpers_run_signature": "(solution_class: type, p_list: list[int | None], q_list: list[int | None])", + "helpers_run_body": " p = TreeNode[int].from_list(p_list)\n q = TreeNode[int].from_list(q_list)\n implementation = solution_class()\n return implementation.is_same_tree(p, q)", + "helpers_assert_name": "is_same_tree", + "helpers_assert_signature": "(result: bool, expected: bool) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "solution_imports": "from leetcode_py import TreeNode", + "solution_contents": "", + "solution_class_content": "", + "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_is_same_tree, run_is_same_tree\nfrom .solution import Solution", + "test_content": "", + "test_class_name": "SameTree", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_solution_methods": { + "list": [ + { + "name": "is_same_tree", + "signature": "(self, p: TreeNode[int] | None, q: TreeNode[int] | None) -> bool", + "body": " # TODO: Implement is_same_tree\n return False" + } + ] + }, + "_test_helper_methods": { + "list": [{ "name": "setup_method", "parameters": "", "body": "self.solution = Solution()" }] + }, + "_test_methods": { + "list": [ + { + "name": "test_is_same_tree", + "signature": "(self, p_list: list[int | None], q_list: list[int | None], expected: bool)", + "parametrize": "p_list, q_list, expected", + "test_cases": "[([1, 2, 3], [1, 2, 3], True), ([1, 2], [1, None, 2], False), ([1, 2, 1], [1, 1, 2], False), ([], [], True), ([1], [1], True), ([1], [2], False), ([1, None, 2], [1, 2], False), ([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], True), ([1, 2, 3, 4, 5], [1, 2, 3, 4, 6], False), ([1, 2, 3, None, 4], [1, 2, 3, None, 4], True), ([1, 2, 3, None, 4], [1, 2, 3, 4, None], False)]", + "body": " result = run_is_same_tree(Solution, p_list, q_list)\n assert_is_same_tree(result, expected)" + } + ] + }, + "playground_imports": "from helpers import run_is_same_tree, assert_is_same_tree\nfrom solution import Solution\nfrom leetcode_py import TreeNode", + "playground_setup": "# Example test case\np_list: list[int | None] = [1, 2, 3]\nq_list: list[int | None] = [1, 2, 3]\nexpected = True", + "playground_run": "result = run_is_same_tree(Solution, p_list, q_list)\nresult", + "playground_assert": "assert_is_same_tree(result, expected)" +} diff --git a/leetcode_py/cli/resources/leetcode/json/tags.json5 b/leetcode_py/cli/resources/leetcode/json/tags.json5 index 90b2c59..44a8642 100644 --- a/leetcode_py/cli/resources/leetcode/json/tags.json5 +++ b/leetcode_py/cli/resources/leetcode/json/tags.json5 @@ -110,6 +110,7 @@ // Blind 75 - (on-going) "blind-75": [ + "alien_dictionary", "best_time_to_buy_and_sell_stock", "binary_tree_level_order_traversal", "climbing_stairs", @@ -149,6 +150,7 @@ "remove_nth_node_from_end_of_list", "reverse_linked_list", "rotate_image", + "same_tree", "search_in_rotated_sorted_array", "serialize_and_deserialize_binary_tree", "set_matrix_zeroes", @@ -166,6 +168,7 @@ // NeetCode 150 - (on-going) "neetcode-150": [ + "alien_dictionary", "balanced_binary_tree", "best_time_to_buy_and_sell_stock", "binary_search", @@ -181,6 +184,7 @@ "course_schedule", "course_schedule_ii", "daily_temperatures", + "decode_ways", "design_add_and_search_words_data_structure", "diameter_of_binary_tree", "evaluate_reverse_polish_notation", @@ -192,6 +196,7 @@ "implement_trie_prefix_tree", "insert_interval", "invert_binary_tree", + "jump_game", "k_closest_points_to_origin", "kth_smallest_element_in_a_bst", "largest_rectangle_in_histogram", @@ -218,9 +223,12 @@ "product_of_array_except_self", "remove_nth_node_from_end_of_list", "reverse_linked_list", + "rotate_image", "rotting_oranges", + "same_tree", "search_in_rotated_sorted_array", "serialize_and_deserialize_binary_tree", + "set_matrix_zeroes", "spiral_matrix", "subsets", "task_scheduler", @@ -269,6 +277,7 @@ "permutations", "product_of_array_except_self", "remove_nth_node_from_end_of_list", + "rotate_image", "rotting_oranges", "search_in_rotated_sorted_array", "serialize_and_deserialize_binary_tree", diff --git a/poetry.lock b/poetry.lock index be8805d..b7fdfd8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -712,14 +712,14 @@ test = ["coverage", "pytest (>=7,<8.1)", "pytest-cov", "pytest-mock (>=3)"] [[package]] name = "identify" -version = "2.6.14" +version = "2.6.15" description = "File identification library for Python" optional = false python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "identify-2.6.14-py2.py3-none-any.whl", hash = "sha256:11a073da82212c6646b1f39bb20d4483bfb9543bd5566fec60053c4bb309bf2e"}, - {file = "identify-2.6.14.tar.gz", hash = "sha256:663494103b4f717cb26921c52f8751363dc89db64364cd836a9bf1535f53cd6a"}, + {file = "identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757"}, + {file = "identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf"}, ] [package.extras] @@ -1050,73 +1050,101 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions", "requests"] [[package]] name = "markupsafe" -version = "3.0.2" +version = "3.0.3" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, - {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, + {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, + {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591"}, + {file = "markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6"}, + {file = "markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1"}, + {file = "markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa"}, + {file = "markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8"}, + {file = "markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad"}, + {file = "markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf"}, + {file = "markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115"}, + {file = "markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a"}, + {file = "markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01"}, + {file = "markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e"}, + {file = "markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d"}, + {file = "markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f"}, + {file = "markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b"}, + {file = "markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c"}, + {file = "markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f"}, + {file = "markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795"}, + {file = "markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676"}, + {file = "markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc"}, + {file = "markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12"}, + {file = "markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed"}, + {file = "markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5"}, + {file = "markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485"}, + {file = "markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73"}, + {file = "markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025"}, + {file = "markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb"}, + {file = "markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218"}, + {file = "markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287"}, + {file = "markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe"}, + {file = "markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97"}, + {file = "markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf"}, + {file = "markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe"}, + {file = "markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9"}, + {file = "markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581"}, + {file = "markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4"}, + {file = "markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab"}, + {file = "markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50"}, + {file = "markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523"}, + {file = "markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9"}, + {file = "markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa"}, + {file = "markupsafe-3.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15d939a21d546304880945ca1ecb8a039db6b4dc49b2c5a400387cdae6a62e26"}, + {file = "markupsafe-3.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f71a396b3bf33ecaa1626c255855702aca4d3d9fea5e051b41ac59a9c1c41edc"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f4b68347f8c5eab4a13419215bdfd7f8c9b19f2b25520968adfad23eb0ce60c"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8fc20152abba6b83724d7ff268c249fa196d8259ff481f3b1476383f8f24e42"}, + {file = "markupsafe-3.0.3-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:949b8d66bc381ee8b007cd945914c721d9aba8e27f71959d750a46f7c282b20b"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3537e01efc9d4dccdf77221fb1cb3b8e1a38d5428920e0657ce299b20324d758"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:591ae9f2a647529ca990bc681daebdd52c8791ff06c2bfa05b65163e28102ef2"}, + {file = "markupsafe-3.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a320721ab5a1aba0a233739394eb907f8c8da5c98c9181d1161e77a0c8e36f2d"}, + {file = "markupsafe-3.0.3-cp39-cp39-win32.whl", hash = "sha256:df2449253ef108a379b8b5d6b43f4b1a8e81a061d6537becd5582fba5f9196d7"}, + {file = "markupsafe-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:7c3fb7d25180895632e5d3148dbdc29ea38ccb7fd210aa27acbd1201a1902c6e"}, + {file = "markupsafe-3.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:38664109c14ffc9e7437e86b4dceb442b0096dfe3541d7864d9cbe1da4cf36c8"}, + {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] [[package]] @@ -1651,13 +1679,6 @@ optional = false python-versions = ">=3.8" groups = ["main", "dev"] files = [ - {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, - {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, - {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3"}, - {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6"}, - {file = "PyYAML-6.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369"}, - {file = "PyYAML-6.0.3-cp38-cp38-win32.whl", hash = "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295"}, - {file = "PyYAML-6.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b"}, {file = "pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b"}, {file = "pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956"}, {file = "pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8"}, diff --git a/scripts/sort_tags.py b/scripts/sort_tags.py index 94aa364..ad0d372 100644 --- a/scripts/sort_tags.py +++ b/scripts/sort_tags.py @@ -22,7 +22,6 @@ print("❌ Found unsorted problem lists:") for tag_name, current, expected in unsorted_tags: print(f"\n{tag_name}:") - print(f" Current: {current}") print(f" Expected: {expected}") sys.exit(1) else: