From 2e6875d9880cb972c49bf07d75aaf4710e864c39 Mon Sep 17 00:00:00 2001 From: Shravan Chandra <52000043+shravnchandr@users.noreply.github.com> Date: Fri, 28 Nov 2025 19:26:25 +0530 Subject: [PATCH] Add batch of 15 missing LeetCode problems --- add_problems.py | 354 ++++++++++++++++++ leetcode/_01_matrix/README.md | 57 +++ leetcode/_01_matrix/__init__.py | 0 leetcode/_01_matrix/helpers.py | 11 + leetcode/_01_matrix/playground.ipynb | 56 +++ leetcode/_01_matrix/solution.py | 10 + leetcode/_01_matrix/test_solution.py | 22 ++ leetcode/_3sum/README.md | 87 +++++ leetcode/_3sum/__init__.py | 0 leetcode/_3sum/helpers.py | 11 + leetcode/_3sum/playground.ipynb | 56 +++ leetcode/_3sum/solution.py | 10 + leetcode/_3sum/test_solution.py | 19 + leetcode/_3sum_closest/README.md | 65 ++++ leetcode/_3sum_closest/__init__.py | 0 leetcode/_3sum_closest/helpers.py | 11 + leetcode/_3sum_closest/playground.ipynb | 56 +++ leetcode/_3sum_closest/solution.py | 10 + leetcode/_3sum_closest/test_solution.py | 19 + leetcode/_4sum/README.md | 65 ++++ leetcode/_4sum/__init__.py | 0 leetcode/_4sum/helpers.py | 11 + leetcode/_4sum/playground.ipynb | 56 +++ leetcode/_4sum/solution.py | 10 + leetcode/_4sum/test_solution.py | 19 + leetcode/accounts_merge/README.md | 66 +++- leetcode/accounts_merge/helpers.py | 12 +- leetcode/accounts_merge/playground.ipynb | 56 +++ leetcode/accounts_merge/solution.py | 39 +- leetcode/accounts_merge/test_solution.py | 84 +---- leetcode/add_binary/README.md | 35 +- leetcode/add_binary/playground.ipynb | 56 +++ leetcode/add_binary/solution.py | 29 +- leetcode/add_binary/test_solution.py | 17 +- leetcode/add_strings/README.md | 73 ++++ leetcode/add_strings/__init__.py | 0 leetcode/add_strings/helpers.py | 8 + leetcode/add_strings/playground.ipynb | 56 +++ leetcode/add_strings/solution.py | 7 + leetcode/add_strings/test_solution.py | 17 + .../add_to_array_form_of_integer/README.md | 85 +++++ .../add_to_array_form_of_integer/__init__.py | 0 .../add_to_array_form_of_integer/helpers.py | 11 + .../playground.ipynb | 56 +++ .../add_to_array_form_of_integer/solution.py | 10 + .../test_solution.py | 19 + leetcode/assign_cookies/README.md | 75 ++++ leetcode/assign_cookies/__init__.py | 0 leetcode/assign_cookies/helpers.py | 11 + leetcode/assign_cookies/playground.ipynb | 56 +++ leetcode/assign_cookies/solution.py | 10 + leetcode/assign_cookies/test_solution.py | 19 + leetcode/asteroid_collision/README.md | 97 +++++ leetcode/asteroid_collision/__init__.py | 0 leetcode/asteroid_collision/helpers.py | 11 + leetcode/asteroid_collision/playground.ipynb | 56 +++ leetcode/asteroid_collision/solution.py | 10 + leetcode/asteroid_collision/test_solution.py | 19 + leetcode/backspace_string_compare/README.md | 81 ++++ leetcode/backspace_string_compare/__init__.py | 0 leetcode/backspace_string_compare/helpers.py | 8 + .../backspace_string_compare/playground.ipynb | 56 +++ leetcode/backspace_string_compare/solution.py | 7 + .../backspace_string_compare/test_solution.py | 17 + leetcode/basic_calculator/README.md | 73 +++- leetcode/basic_calculator/playground.ipynb | 56 +++ leetcode/basic_calculator/solution.py | 64 +--- leetcode/basic_calculator/test_solution.py | 52 +-- leetcode/basic_calculator_ii/README.md | 62 +++ leetcode/basic_calculator_ii/__init__.py | 0 leetcode/basic_calculator_ii/helpers.py | 8 + leetcode/basic_calculator_ii/playground.ipynb | 56 +++ leetcode/basic_calculator_ii/solution.py | 7 + leetcode/basic_calculator_ii/test_solution.py | 17 + .../best_time_to_buy_and_sell_stock/README.md | 54 ++- .../helpers.py | 5 +- .../playground.ipynb | 56 +++ .../solution.py | 18 +- .../test_solution.py | 25 +- .../README.md | 85 +++++ .../__init__.py | 0 .../helpers.py | 11 + .../playground.ipynb | 56 +++ .../solution.py | 10 + .../test_solution.py | 19 + .../leetcode/json/problems/_01_matrix.json | 48 +++ .../leetcode/json/problems/_3sum.json | 50 +++ .../leetcode/json/problems/_3sum_closest.json | 50 +++ .../leetcode/json/problems/_4sum.json | 50 +++ .../json/problems/accounts_merge.json | 137 +++---- .../leetcode/json/problems/add_binary.json | 134 +++---- .../leetcode/json/problems/add_strings.json | 50 +++ .../add_to_array_form_of_integer.json | 50 +++ .../json/problems/assign_cookies.json | 50 +++ .../json/problems/asteroid_collision.json | 50 +++ .../problems/backspace_string_compare.json | 50 +++ .../json/problems/basic_calculator.json | 150 +++----- .../json/problems/basic_calculator_ii.json | 50 +++ .../best_time_to_buy_and_sell_stock.json | 140 +++---- .../best_time_to_buy_and_sell_stock_ii.json | 50 +++ pyproject.toml | 2 +- 101 files changed, 3406 insertions(+), 723 deletions(-) create mode 100644 add_problems.py create mode 100644 leetcode/_01_matrix/README.md create mode 100644 leetcode/_01_matrix/__init__.py create mode 100644 leetcode/_01_matrix/helpers.py create mode 100644 leetcode/_01_matrix/playground.ipynb create mode 100644 leetcode/_01_matrix/solution.py create mode 100644 leetcode/_01_matrix/test_solution.py create mode 100644 leetcode/_3sum/README.md create mode 100644 leetcode/_3sum/__init__.py create mode 100644 leetcode/_3sum/helpers.py create mode 100644 leetcode/_3sum/playground.ipynb create mode 100644 leetcode/_3sum/solution.py create mode 100644 leetcode/_3sum/test_solution.py create mode 100644 leetcode/_3sum_closest/README.md create mode 100644 leetcode/_3sum_closest/__init__.py create mode 100644 leetcode/_3sum_closest/helpers.py create mode 100644 leetcode/_3sum_closest/playground.ipynb create mode 100644 leetcode/_3sum_closest/solution.py create mode 100644 leetcode/_3sum_closest/test_solution.py create mode 100644 leetcode/_4sum/README.md create mode 100644 leetcode/_4sum/__init__.py create mode 100644 leetcode/_4sum/helpers.py create mode 100644 leetcode/_4sum/playground.ipynb create mode 100644 leetcode/_4sum/solution.py create mode 100644 leetcode/_4sum/test_solution.py create mode 100644 leetcode/accounts_merge/playground.ipynb create mode 100644 leetcode/add_binary/playground.ipynb create mode 100644 leetcode/add_strings/README.md create mode 100644 leetcode/add_strings/__init__.py create mode 100644 leetcode/add_strings/helpers.py create mode 100644 leetcode/add_strings/playground.ipynb create mode 100644 leetcode/add_strings/solution.py create mode 100644 leetcode/add_strings/test_solution.py create mode 100644 leetcode/add_to_array_form_of_integer/README.md create mode 100644 leetcode/add_to_array_form_of_integer/__init__.py create mode 100644 leetcode/add_to_array_form_of_integer/helpers.py create mode 100644 leetcode/add_to_array_form_of_integer/playground.ipynb create mode 100644 leetcode/add_to_array_form_of_integer/solution.py create mode 100644 leetcode/add_to_array_form_of_integer/test_solution.py create mode 100644 leetcode/assign_cookies/README.md create mode 100644 leetcode/assign_cookies/__init__.py create mode 100644 leetcode/assign_cookies/helpers.py create mode 100644 leetcode/assign_cookies/playground.ipynb create mode 100644 leetcode/assign_cookies/solution.py create mode 100644 leetcode/assign_cookies/test_solution.py create mode 100644 leetcode/asteroid_collision/README.md create mode 100644 leetcode/asteroid_collision/__init__.py create mode 100644 leetcode/asteroid_collision/helpers.py create mode 100644 leetcode/asteroid_collision/playground.ipynb create mode 100644 leetcode/asteroid_collision/solution.py create mode 100644 leetcode/asteroid_collision/test_solution.py create mode 100644 leetcode/backspace_string_compare/README.md create mode 100644 leetcode/backspace_string_compare/__init__.py create mode 100644 leetcode/backspace_string_compare/helpers.py create mode 100644 leetcode/backspace_string_compare/playground.ipynb create mode 100644 leetcode/backspace_string_compare/solution.py create mode 100644 leetcode/backspace_string_compare/test_solution.py create mode 100644 leetcode/basic_calculator/playground.ipynb create mode 100644 leetcode/basic_calculator_ii/README.md create mode 100644 leetcode/basic_calculator_ii/__init__.py create mode 100644 leetcode/basic_calculator_ii/helpers.py create mode 100644 leetcode/basic_calculator_ii/playground.ipynb create mode 100644 leetcode/basic_calculator_ii/solution.py create mode 100644 leetcode/basic_calculator_ii/test_solution.py create mode 100644 leetcode/best_time_to_buy_and_sell_stock/playground.ipynb create mode 100644 leetcode/best_time_to_buy_and_sell_stock_ii/README.md create mode 100644 leetcode/best_time_to_buy_and_sell_stock_ii/__init__.py create mode 100644 leetcode/best_time_to_buy_and_sell_stock_ii/helpers.py create mode 100644 leetcode/best_time_to_buy_and_sell_stock_ii/playground.ipynb create mode 100644 leetcode/best_time_to_buy_and_sell_stock_ii/solution.py create mode 100644 leetcode/best_time_to_buy_and_sell_stock_ii/test_solution.py create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/_01_matrix.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/_3sum.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/_3sum_closest.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/_4sum.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/add_strings.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/add_to_array_form_of_integer.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/assign_cookies.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/asteroid_collision.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/backspace_string_compare.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/basic_calculator_ii.json create mode 100644 leetcode_py/cli/resources/leetcode/json/problems/best_time_to_buy_and_sell_stock_ii.json diff --git a/add_problems.py b/add_problems.py new file mode 100644 index 0000000..1ce1b28 --- /dev/null +++ b/add_problems.py @@ -0,0 +1,354 @@ +import json +import os +import re +import shutil +import subprocess +import sys +import time + + +def get_missing_slugs(): + with open("batch_1_slugs.txt", "r") as f: + return [line.strip() for line in f if line.strip()] + + +def transform_scraped_data(data): + """Transforms scraped data into the format expected by cookiecutter/gen.""" + transformed = {} + + # Basic fields + # Sanitize problem_name + problem_name = data.get("slug", "").replace("-", "_") + if problem_name and problem_name[0].isdigit(): + problem_name = f"_{problem_name}" + transformed["problem_name"] = problem_name + transformed["problem_number"] = data.get("number", "0") + transformed["problem_title"] = data.get("title", "") + transformed["difficulty"] = data.get("difficulty", "Medium") + + # Topics: list -> string + topics = data.get("topics", []) + if isinstance(topics, list): + transformed["topics"] = ", ".join(topics) + else: + transformed["topics"] = str(topics) + + # Description + transformed["readme_description"] = data.get("description", "") + + # Constraints: list -> string + constraints = data.get("constraints", []) + if isinstance(constraints, list): + transformed["readme_constraints"] = "\n".join([f"- {c}" for c in constraints]) + else: + transformed["readme_constraints"] = str(constraints) + + # Examples + examples = data.get("examples", []) + readme_examples = [] + for ex in examples: + # Scraped example might be dict or string? + # 01_matrix.json shows examples as empty list []? + # But raw_content has them. + # If examples is list of dicts with 'text' or 'input'/'output' + if isinstance(ex, dict): + content = ex.get("text", "") + if not content: + inp = ex.get("input", "") + out = ex.get("output", "") + if inp and out: + content = f"```\nInput: {inp}\nOutput: {out}\n```" + if content: + readme_examples.append({"content": content}) + + transformed["_readme_examples"] = {"list": readme_examples} + + # Python Code Parsing + python_code = data.get("python_code", "") + solution_class_name = "Solution" + method_name = "unknown" + method_signature = "" + method_body = " pass" + + # Simple regex to find class and method + class_match = re.search(r"class\s+(\w+):", python_code) + if class_match: + solution_class_name = class_match.group(1) + + # Find method def + # def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]: + method_match = re.search(r"def\s+(\w+)\s*\((.*?)\)\s*(->\s*.*?)?:", python_code) + if method_match: + method_name = method_match.group(1) + params = method_match.group(2) + return_type = method_match.group(3) or "" + + # Clean params to remove 'self' + param_list = [p.strip() for p in params.split(",") if p.strip()] + if param_list and param_list[0] == "self": + param_list = param_list[1:] + + clean_params = ", ".join(param_list) + + # Construct signature + if clean_params: + method_signature = f"(self, {clean_params}){return_type}" + else: + method_signature = f"(self){return_type}" + + # Snake case method name + s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", method_name) + snake_method_name = re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower() + + method_body = f" # TODO: Implement {snake_method_name}\n return " + if "List" in return_type: + method_body += "[]" + elif "int" in return_type: + method_body += "0" + elif "bool" in return_type: + method_body += "False" + elif "str" in return_type: + method_body += '""' + else: + method_body += "None" + + transformed["solution_class_name"] = solution_class_name + + transformed["_solution_methods"] = { + "list": [{"name": snake_method_name, "signature": method_signature, "body": method_body}] + } + + # Helpers and Tests + transformed["helpers_run_name"] = snake_method_name + + if clean_params: + helper_sig = f"(solution_class: type, {clean_params})" + else: + helper_sig = "(solution_class: type)" + + transformed["helpers_run_signature"] = helper_sig + + # Extract argument names for the call + arg_names = [p.split(":")[0].strip() for p in param_list] + call_args = ", ".join(arg_names) + + transformed["helpers_run_body"] = ( + f" implementation = solution_class()\n" + f" return implementation.{snake_method_name}({call_args})" + ) + + transformed["helpers_assert_name"] = snake_method_name + # Infer expected type from return type + expected_type = return_type.replace("->", "").strip() + transformed["helpers_assert_signature"] = ( + f"(result: {expected_type}, expected: {expected_type}) -> bool" + ) + transformed["helpers_assert_body"] = " assert result == expected\n return True" + + transformed["test_class_name"] = "".join( + [word.capitalize() for word in transformed["problem_name"].split("_")] + ) + transformed["test_class_content"] = ( + " def setup_method(self):\n self.solution = Solution()" + ) + + # Test Cases + formatted_test_cases = [] + raw_test_cases = data.get("test_cases", []) + + # Count args + arg_count = len(arg_names) + + for tc in raw_test_cases: + # Expected length is arg_count + 1 (for expected output) + if len(tc) == arg_count + 1: + args = ", ".join(tc[:-1]) + expected = tc[-1] + formatted_test_cases.append(f"({args}, {expected})") + else: + print( + f"[{data.get('slug')}] Warning: Skipping invalid test case " + f"(len={len(tc)}, expected={arg_count+1}): {tc}" + ) + + # Parametrize string + if call_args: + parametrize_str = f"{call_args}, expected" + else: + parametrize_str = "expected" + + # Test signature + if clean_params: + test_sig = f"(self, {clean_params}, expected: {expected_type})" + else: + test_sig = f"(self, expected: {expected_type})" + + transformed["_test_methods"] = { + "list": [ + { + "name": f"test_{snake_method_name}", + "signature": test_sig, + "parametrize": parametrize_str, + "test_cases": {"list": formatted_test_cases}, + "body": ( + f" result = run_{snake_method_name}(Solution, {call_args})\n" + f" assert_{snake_method_name}(result, expected)" + ), + } + ] + } + + # Imports + typing_imports = [] + for type_name in ["List", "Optional", "Dict", "Set", "Tuple"]: + if type_name in method_signature: + typing_imports.append(type_name) + + if typing_imports: + typing_str = f"from typing import {', '.join(typing_imports)}" + transformed["solution_imports"] = typing_str + transformed["test_imports"] = ( + f"import pytest\n{typing_str}\nfrom leetcode_py import logged_test\n" + f"from .helpers import assert_{snake_method_name}, run_{snake_method_name}\n" + f"from .solution import Solution" + ) + transformed["helpers_imports"] = typing_str + else: + transformed["solution_imports"] = "" + transformed["test_imports"] = ( + f"import pytest\nfrom leetcode_py import logged_test\n" + f"from .helpers import assert_{snake_method_name}, run_{snake_method_name}\n" + f"from .solution import Solution" + ) + transformed["helpers_imports"] = "" + + return transformed + + +def process_problem(slug): + scrape_slug = slug.replace("_", "-") + + print(f"\n[{slug}] Starting process...") + + try: + # 1. Scrape + print(f"[{slug}] Scraping {scrape_slug}...") + result = subprocess.run( + ["uv", "run", "python", "-m", "leetcode_py.cli.main", "scrape", "-s", scrape_slug], + check=False, + capture_output=True, + text=True, + ) + + if result.returncode != 0: + print(f"[{slug}] Scrape FAILED with code {result.returncode}.") + return False + + output = result.stdout + json_start = output.find("{") + if json_start == -1: + print(f"[{slug}] Scrape output does not contain JSON start.") + return False + + json_content = output[json_start:] + try: + data = json.loads(json_content) + except json.JSONDecodeError: + print(f"[{slug}] Extracted content is not valid JSON.") + return False + + # TRANSFORM DATA + transformed_data = transform_scraped_data(data) + + # Convert to snake_case for file naming + snake_slug = slug.replace("-", "_") + + # If starts with digit, prepend _ + if snake_slug[0].isdigit(): + snake_slug = f"_{snake_slug}" + + # Save to file + json_dir = "leetcode_py/cli/resources/leetcode/json/problems" + os.makedirs(json_dir, exist_ok=True) + json_path = os.path.join(json_dir, f"{snake_slug}.json") + + with open(json_path, "w") as f: + json.dump(transformed_data, f, indent=2) + + abs_json_path = os.path.abspath(json_path) + print(f"[{slug}] Scrape successful. Saved to {abs_json_path}") + + # 2. Generate + print(f"[{snake_slug}] Generating...") + gen_result = subprocess.run( + [ + "uv", + "run", + "python", + "-m", + "leetcode_py.cli.main", + "gen", + "-s", + snake_slug, + "-o", + "leetcode", + "--force", + ], + check=False, + capture_output=True, + text=True, + ) + + if gen_result.returncode != 0: + print(f"[{slug}] Generation FAILED.") + print(f"Error output: {gen_result.stderr}") + print(f"Standard output: {gen_result.stdout}") + return False + + print(f"[{slug}] Generation successful.") + return True + + except Exception as e: + print(f"[{slug}] Unexpected error: {e}") + return False + + +def main(): + if not shutil.which("uv"): + print("Error: 'uv' executable not found in PATH.") + sys.exit(1) + + slugs = get_missing_slugs() + print(f"Found {len(slugs)} problems to process.") + + success_count = 0 + failed_slugs = [] + + for i, slug in enumerate(slugs): + print(f"\n--- Processing {i+1}/{len(slugs)}: {slug} ---") + if process_problem(slug): + success_count += 1 + else: + failed_slugs.append(slug) + + time.sleep(0.5) + + print("\n" + "=" * 30) + print(f"Completed. Success: {success_count}, Failed: {len(failed_slugs)}") + + if failed_slugs: + print("\nFailed slugs:") + for s in failed_slugs: + print(s) + + with open("failed_slugs.txt", "w") as f: + for s in failed_slugs: + f.write(s + "\n") + print("Failed slugs written to failed_slugs.txt") + else: + if os.path.exists("failed_slugs.txt"): + os.remove("failed_slugs.txt") + + +if __name__ == "__main__": + main() diff --git a/leetcode/_01_matrix/README.md b/leetcode/_01_matrix/README.md new file mode 100644 index 0000000..88b7d01 --- /dev/null +++ b/leetcode/_01_matrix/README.md @@ -0,0 +1,57 @@ +# 01 Matrix + +**Difficulty:** Medium +**Topics:** Array, Dynamic Programming, Breadth-First Search, Matrix +**Tags:** grind-75 + +**LeetCode:** [Problem 542](https://leetcode.com/problems/-01-matrix/description/) + + +## Problem Description + +Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell. + +The distance between two cells sharing a common edge is 1. + +  +Example 1: + + +Input: mat = [[0,0,0],[0,1,0],[0,0,0]] +Output: [[0,0,0],[0,1,0],[0,0,0]] + + +Example 2: + + +Input: mat = [[0,0,0],[0,1,0],[1,1,1]] +Output: [[0,0,0],[0,1,0],[1,2,1]] + + +  +Constraints: + + + m == mat.length + n == mat[i].length + 1 <= m, n <= 104 + 1 <= m * n <= 104 + mat[i][j] is either 0 or 1. + There is at least one 0 in mat. + + +  +Note: This question is the same as 1765: https://leetcode.com/problems/map-of-highest-peak/ + +## Examples + +## Constraints + +- m == mat.length +- n == mat[i].length +- 1 <= m, n <= 104 +- 1 <= m * n <= 104 +- mat[i][j] is either 0 or 1. +- There is at least one 0 in mat. + + diff --git a/leetcode/_01_matrix/__init__.py b/leetcode/_01_matrix/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/_01_matrix/helpers.py b/leetcode/_01_matrix/helpers.py new file mode 100644 index 0000000..a345409 --- /dev/null +++ b/leetcode/_01_matrix/helpers.py @@ -0,0 +1,11 @@ +from typing import List + + +def run_update_matrix(solution_class: type, mat: List[List[int]]): + implementation = solution_class() + return implementation.update_matrix(mat) + + +def assert_update_matrix(result: List[List[int]], expected: List[List[int]]) -> bool: + assert result == expected + return True diff --git a/leetcode/_01_matrix/playground.ipynb b/leetcode/_01_matrix/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/_01_matrix/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/_01_matrix/solution.py b/leetcode/_01_matrix/solution.py new file mode 100644 index 0000000..bb29f6c --- /dev/null +++ b/leetcode/_01_matrix/solution.py @@ -0,0 +1,10 @@ +from typing import List + + +class Solution: + + # Time: O(?) + # Space: O(?) + def update_matrix(self, mat: List[List[int]]) -> List[List[int]]: + # TODO: Implement update_matrix + return [] diff --git a/leetcode/_01_matrix/test_solution.py b/leetcode/_01_matrix/test_solution.py new file mode 100644 index 0000000..2fc022c --- /dev/null +++ b/leetcode/_01_matrix/test_solution.py @@ -0,0 +1,22 @@ +from typing import List + +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_update_matrix, run_update_matrix +from .solution import Solution + + +class Test01Matrix: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize( + "mat, expected", + [([[0, 0, 0], [0, 1, 0], [0, 0, 0]], [[0, 0, 0], [0, 1, 0], [1, 1, 1]])], + ) + def test_update_matrix(self, mat: List[List[int]], expected: List[List[int]]): + result = run_update_matrix(Solution, mat) + assert_update_matrix(result, expected) diff --git a/leetcode/_3sum/README.md b/leetcode/_3sum/README.md new file mode 100644 index 0000000..dc856fa --- /dev/null +++ b/leetcode/_3sum/README.md @@ -0,0 +1,87 @@ +# 3Sum + +**Difficulty:** Medium +**Topics:** Array, Two Pointers, Sorting +**Tags:** grind-75 + +**LeetCode:** [Problem 15](https://leetcode.com/problems/-3sum/description/) + + +## Problem Description + +Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0. + +Notice that the solution set must not contain duplicate triplets. + +  +Example 1: + + +Input: nums = [-1,0,1,2,-1,-4] +Output: [[-1,-1,2],[-1,0,1]] +Explanation: +nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0. +nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0. +nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0. +The distinct triplets are [-1,0,1] and [-1,-1,2]. +Notice that the order of the output and the order of the triplets does not matter. + + +Example 2: + + +Input: nums = [0,1,1] +Output: [] +Explanation: The only possible triplet does not sum up to 0. + + +Example 3: + + +Input: nums = [0,0,0] +Output: [[0,0,0]] +Explanation: The only possible triplet sums up to 0. + + +  +Constraints: + + + 3 <= nums.length <= 3000 + -105 <= nums[i] <= 105 + +## Examples + +### Example 1: + +Input: nums = [-1,0,1,2,-1,-4] +Output: [[-1,-1,2],[-1,0,1]] +Explanation: +nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0. +nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0. +nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0. +The distinct triplets are [-1,0,1] and [-1,-1,2]. +Notice that the order of the output and the order of the triplets does not matter. + + +Example 2: + + +Input: nums = [0,1,1] +Output: [] +Explanation: The only possible triplet does not sum up to 0. + + +Example 3: + + +Input: nums = [0,0,0] +Output: [[0,0,0]] +Explanation: The only possible triplet sums up to 0. + +## Constraints + +- 3 <= nums.length <= 3000 +- -105 <= nums[i] <= 105 + + diff --git a/leetcode/_3sum/__init__.py b/leetcode/_3sum/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/_3sum/helpers.py b/leetcode/_3sum/helpers.py new file mode 100644 index 0000000..f1d6b4c --- /dev/null +++ b/leetcode/_3sum/helpers.py @@ -0,0 +1,11 @@ +from typing import List + + +def run_three_sum(solution_class: type, nums: List[int]): + implementation = solution_class() + return implementation.three_sum(nums) + + +def assert_three_sum(result: List[List[int]], expected: List[List[int]]) -> bool: + assert result == expected + return True diff --git a/leetcode/_3sum/playground.ipynb b/leetcode/_3sum/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/_3sum/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/_3sum/solution.py b/leetcode/_3sum/solution.py new file mode 100644 index 0000000..5829fc6 --- /dev/null +++ b/leetcode/_3sum/solution.py @@ -0,0 +1,10 @@ +from typing import List + + +class Solution: + + # Time: O(?) + # Space: O(?) + def three_sum(self, nums: List[int]) -> List[List[int]]: + # TODO: Implement three_sum + return [] diff --git a/leetcode/_3sum/test_solution.py b/leetcode/_3sum/test_solution.py new file mode 100644 index 0000000..77a1794 --- /dev/null +++ b/leetcode/_3sum/test_solution.py @@ -0,0 +1,19 @@ +from typing import List + +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_three_sum, run_three_sum +from .solution import Solution + + +class Test3sum: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("nums, expected", []) + def test_three_sum(self, nums: List[int], expected: List[List[int]]): + result = run_three_sum(Solution, nums) + assert_three_sum(result, expected) diff --git a/leetcode/_3sum_closest/README.md b/leetcode/_3sum_closest/README.md new file mode 100644 index 0000000..c96ff1b --- /dev/null +++ b/leetcode/_3sum_closest/README.md @@ -0,0 +1,65 @@ +# 3Sum Closest + +**Difficulty:** Medium +**Topics:** Array, Two Pointers, Sorting +**Tags:** grind-75 + +**LeetCode:** [Problem 16](https://leetcode.com/problems/-3sum-closest/description/) + + +## Problem Description + +Given an integer array nums of length n and an integer target, find three integers in nums such that the sum is closest to target. + +Return the sum of the three integers. + +You may assume that each input would have exactly one solution. + +  +Example 1: + + +Input: nums = [-1,2,1,-4], target = 1 +Output: 2 +Explanation: The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). + + +Example 2: + + +Input: nums = [0,0,0], target = 1 +Output: 0 +Explanation: The sum that is closest to the target is 0. (0 + 0 + 0 = 0). + + +  +Constraints: + + + 3 <= nums.length <= 500 + -1000 <= nums[i] <= 1000 + -104 <= target <= 104 + +## Examples + +### Example 1: + +Input: nums = [-1,2,1,-4], target = 1 +Output: 2 +Explanation: The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). + + +Example 2: + + +Input: nums = [0,0,0], target = 1 +Output: 0 +Explanation: The sum that is closest to the target is 0. (0 + 0 + 0 = 0). + +## Constraints + +- 3 <= nums.length <= 500 +- -1000 <= nums[i] <= 1000 +- -104 <= target <= 104 + + diff --git a/leetcode/_3sum_closest/__init__.py b/leetcode/_3sum_closest/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/_3sum_closest/helpers.py b/leetcode/_3sum_closest/helpers.py new file mode 100644 index 0000000..2a2da08 --- /dev/null +++ b/leetcode/_3sum_closest/helpers.py @@ -0,0 +1,11 @@ +from typing import List + + +def run_three_sum_closest(solution_class: type, nums: List[int], target: int): + implementation = solution_class() + return implementation.three_sum_closest(nums, target) + + +def assert_three_sum_closest(result: int, expected: int) -> bool: + assert result == expected + return True diff --git a/leetcode/_3sum_closest/playground.ipynb b/leetcode/_3sum_closest/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/_3sum_closest/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/_3sum_closest/solution.py b/leetcode/_3sum_closest/solution.py new file mode 100644 index 0000000..1f15b90 --- /dev/null +++ b/leetcode/_3sum_closest/solution.py @@ -0,0 +1,10 @@ +from typing import List + + +class Solution: + + # Time: O(?) + # Space: O(?) + def three_sum_closest(self, nums: List[int], target: int) -> int: + # TODO: Implement three_sum_closest + return 0 diff --git a/leetcode/_3sum_closest/test_solution.py b/leetcode/_3sum_closest/test_solution.py new file mode 100644 index 0000000..ce2db10 --- /dev/null +++ b/leetcode/_3sum_closest/test_solution.py @@ -0,0 +1,19 @@ +from typing import List + +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_three_sum_closest, run_three_sum_closest +from .solution import Solution + + +class Test3sumClosest: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("nums, target, expected", []) + def test_three_sum_closest(self, nums: List[int], target: int, expected: int): + result = run_three_sum_closest(Solution, nums, target) + assert_three_sum_closest(result, expected) diff --git a/leetcode/_4sum/README.md b/leetcode/_4sum/README.md new file mode 100644 index 0000000..7533460 --- /dev/null +++ b/leetcode/_4sum/README.md @@ -0,0 +1,65 @@ +# 4Sum + +**Difficulty:** Medium +**Topics:** Array, Two Pointers, Sorting +**Tags:** grind-75 + +**LeetCode:** [Problem 18](https://leetcode.com/problems/-4sum/description/) + + +## Problem Description + +Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that: + + + 0 <= a, b, c, d < n + a, b, c, and d are distinct. + nums[a] + nums[b] + nums[c] + nums[d] == target + + +You may return the answer in any order. + +  +Example 1: + + +Input: nums = [1,0,-1,0,-2,2], target = 0 +Output: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]] + + +Example 2: + + +Input: nums = [2,2,2,2,2], target = 8 +Output: [[2,2,2,2]] + + +  +Constraints: + + + 1 <= nums.length <= 200 + -109 <= nums[i] <= 109 + -109 <= target <= 109 + +## Examples + +### Example 1: + +Input: nums = [1,0,-1,0,-2,2], target = 0 +Output: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]] + + +Example 2: + + +Input: nums = [2,2,2,2,2], target = 8 +Output: [[2,2,2,2]] + +## Constraints + +- 1 <= nums.length <= 200 +- -109 <= nums[i] <= 109 +- -109 <= target <= 109 + + diff --git a/leetcode/_4sum/__init__.py b/leetcode/_4sum/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/_4sum/helpers.py b/leetcode/_4sum/helpers.py new file mode 100644 index 0000000..fc839ba --- /dev/null +++ b/leetcode/_4sum/helpers.py @@ -0,0 +1,11 @@ +from typing import List + + +def run_four_sum(solution_class: type, nums: List[int], target: int): + implementation = solution_class() + return implementation.four_sum(nums, target) + + +def assert_four_sum(result: List[List[int]], expected: List[List[int]]) -> bool: + assert result == expected + return True diff --git a/leetcode/_4sum/playground.ipynb b/leetcode/_4sum/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/_4sum/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/_4sum/solution.py b/leetcode/_4sum/solution.py new file mode 100644 index 0000000..4f0a455 --- /dev/null +++ b/leetcode/_4sum/solution.py @@ -0,0 +1,10 @@ +from typing import List + + +class Solution: + + # Time: O(?) + # Space: O(?) + def four_sum(self, nums: List[int], target: int) -> List[List[int]]: + # TODO: Implement four_sum + return [] diff --git a/leetcode/_4sum/test_solution.py b/leetcode/_4sum/test_solution.py new file mode 100644 index 0000000..8371c08 --- /dev/null +++ b/leetcode/_4sum/test_solution.py @@ -0,0 +1,19 @@ +from typing import List + +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_four_sum, run_four_sum +from .solution import Solution + + +class Test4sum: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("nums, target, expected", []) + def test_four_sum(self, nums: List[int], target: int, expected: List[List[int]]): + result = run_four_sum(Solution, nums, target) + assert_four_sum(result, expected) diff --git a/leetcode/accounts_merge/README.md b/leetcode/accounts_merge/README.md index dd3f61e..aeedfd8 100644 --- a/leetcode/accounts_merge/README.md +++ b/leetcode/accounts_merge/README.md @@ -2,40 +2,74 @@ **Difficulty:** Medium **Topics:** Array, Hash Table, String, Depth-First Search, Breadth-First Search, Union Find, Sorting -**Tags:** grind-75 +**Tags:** grind, grind-75 **LeetCode:** [Problem 721](https://leetcode.com/problems/accounts-merge/description/) + ## Problem Description -Given a list of `accounts` where each element `accounts[i]` is a list of strings, where the first element `accounts[i][0]` is a name, and the rest of the elements are emails representing emails of the account. +Given a list of accounts where each element accounts[i] is a list of strings, where the first element accounts[i][0] is a name, and the rest of the elements are emails representing emails of the account. Now, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some common email to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name. After merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails in sorted order. The accounts themselves can be returned in any order. +  +Example 1: + + +Input: accounts = [["John","johnsmith@mail.com","john_newyork@mail.com"],["John","johnsmith@mail.com","john00@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]] +Output: [["John","john00@mail.com","john_newyork@mail.com","johnsmith@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]] +Explanation: +The first and second John's are the same person as they have the common email "johnsmith@mail.com". +The third John and Mary are different people as none of their email addresses are used by other accounts. +We could return these lists in any order, for example the answer [['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'], +['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] would still be accepted. + + +Example 2: + + +Input: accounts = [["Gabe","Gabe0@m.co","Gabe3@m.co","Gabe1@m.co"],["Kevin","Kevin3@m.co","Kevin5@m.co","Kevin0@m.co"],["Ethan","Ethan5@m.co","Ethan4@m.co","Ethan0@m.co"],["Hanzo","Hanzo3@m.co","Hanzo1@m.co","Hanzo0@m.co"],["Fern","Fern5@m.co","Fern1@m.co","Fern0@m.co"]] +Output: [["Ethan","Ethan0@m.co","Ethan4@m.co","Ethan5@m.co"],["Gabe","Gabe0@m.co","Gabe1@m.co","Gabe3@m.co"],["Hanzo","Hanzo0@m.co","Hanzo1@m.co","Hanzo3@m.co"],["Kevin","Kevin0@m.co","Kevin3@m.co","Kevin5@m.co"],["Fern","Fern0@m.co","Fern1@m.co","Fern5@m.co"]] + + +  +Constraints: + + + 1 <= accounts.length <= 1000 + 2 <= accounts[i].length <= 10 + 1 <= accounts[i][j].length <= 30 + accounts[i][0] consists of English letters. + accounts[i][j] (for j > 0) is a valid email. + ## Examples ### Example 1: -``` -Input: accounts = [["John","johnsmith@mail.com","john_newyork@mail.com"],["John","johnsmith@mail.com","john00@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]] -Output: [["John","john00@mail.com","john_newyork@mail.com","johnsmith@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]] -``` +Input: accounts = [["John","johnsmith@mail.com","john_newyork@mail.com"],["John","johnsmith@mail.com","john00@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]] +Output: [["John","john00@mail.com","john_newyork@mail.com","johnsmith@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]] +Explanation: +The first and second John's are the same person as they have the common email "johnsmith@mail.com". +The third John and Mary are different people as none of their email addresses are used by other accounts. +We could return these lists in any order, for example the answer [['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'], +['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] would still be accepted. -**Explanation:** The first and second John's are the same person as they have the common email "johnsmith@mail.com". The third John and Mary are different people as none of their email addresses are used by other accounts. -### Example 2: +Example 2: -``` -Input: accounts = [["Gabe","Gabe0@m.co","Gabe3@m.co","Gabe1@m.co"],["Kevin","Kevin3@m.co","Kevin5@m.co","Kevin0@m.co"],["Ethan","Ethan5@m.co","Ethan4@m.co","Ethan0@m.co"],["Hanzo","Hanzo3@m.co","Hanzo1@m.co","Hanzo0@m.co"],["Fern","Fern5@m.co","Fern1@m.co","Fern0@m.co"]] -Output: [["Ethan","Ethan0@m.co","Ethan4@m.co","Ethan5@m.co"],["Gabe","Gabe0@m.co","Gabe1@m.co","Gabe3@m.co"],["Hanzo","Hanzo0@m.co","Hanzo1@m.co","Hanzo3@m.co"],["Kevin","Kevin0@m.co","Kevin3@m.co","Kevin5@m.co"],["Fern","Fern0@m.co","Fern1@m.co","Fern5@m.co"]] -``` + +Input: accounts = [["Gabe","Gabe0@m.co","Gabe3@m.co","Gabe1@m.co"],["Kevin","Kevin3@m.co","Kevin5@m.co","Kevin0@m.co"],["Ethan","Ethan5@m.co","Ethan4@m.co","Ethan0@m.co"],["Hanzo","Hanzo3@m.co","Hanzo1@m.co","Hanzo0@m.co"],["Fern","Fern5@m.co","Fern1@m.co","Fern0@m.co"]] +Output: [["Ethan","Ethan0@m.co","Ethan4@m.co","Ethan5@m.co"],["Gabe","Gabe0@m.co","Gabe1@m.co","Gabe3@m.co"],["Hanzo","Hanzo0@m.co","Hanzo1@m.co","Hanzo3@m.co"],["Kevin","Kevin0@m.co","Kevin3@m.co","Kevin5@m.co"],["Fern","Fern0@m.co","Fern1@m.co","Fern5@m.co"]] ## Constraints -- 1 <= accounts.length <= 1000 -- 2 <= accounts[i].length <= 10 -- 1 <= accounts[i][j].length <= 30 +- 1 <= accounts.length <= 1000 +- 2 <= accounts[i].length <= 10 +- 1 <= accounts[i][j].length <= 30 - accounts[i][0] consists of English letters. -- accounts[i][j] (for j > 0) is a valid email. +- accounts[i][j] (for j > 0) is a valid email. + + diff --git a/leetcode/accounts_merge/helpers.py b/leetcode/accounts_merge/helpers.py index e163f17..b4b7375 100644 --- a/leetcode/accounts_merge/helpers.py +++ b/leetcode/accounts_merge/helpers.py @@ -1,11 +1,11 @@ -def run_accounts_merge(solution_class: type, accounts: list[list[str]]): +from typing import List + + +def run_accounts_merge(solution_class: type, accounts: List[List[str]]): implementation = solution_class() return implementation.accounts_merge(accounts) -def assert_accounts_merge(result: list[list[str]], expected: list[list[str]]) -> bool: - # Sort both result and expected for comparison since order doesn't matter - result_sorted = [sorted(account) for account in sorted(result)] - expected_sorted = [sorted(account) for account in sorted(expected)] - assert result_sorted == expected_sorted +def assert_accounts_merge(result: List[List[str]], expected: List[List[str]]) -> bool: + assert result == expected return True diff --git a/leetcode/accounts_merge/playground.ipynb b/leetcode/accounts_merge/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/accounts_merge/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/accounts_merge/solution.py b/leetcode/accounts_merge/solution.py index b971177..b6f36df 100644 --- a/leetcode/accounts_merge/solution.py +++ b/leetcode/accounts_merge/solution.py @@ -1,35 +1,10 @@ -class Solution: - - # Time: O(N * M) where N is accounts, M is max emails per account - # Space: O(N * M) - def accounts_merge(self, accounts: list[list[str]]) -> list[list[str]]: - email_to_accounts: dict[str, list[int]] = {} - - for i, account in enumerate(accounts): - for email in account[1:]: - if email not in email_to_accounts: - email_to_accounts[email] = [] - email_to_accounts[email].append(i) - - visited: set[int] = set() - result = [] +from typing import List - def dfs(account_idx: int, emails: set[str]) -> None: - if account_idx in visited: - return - visited.add(account_idx) - for email in accounts[account_idx][1:]: - emails.add(email) - for neighbor_idx in email_to_accounts[email]: - dfs(neighbor_idx, emails) - - for i in range(len(accounts)): - if i in visited: - continue - - emails: set[str] = set() - dfs(i, emails) - result.append([accounts[i][0]] + sorted(emails)) +class Solution: - return result + # Time: O(?) + # Space: O(?) + def accounts_merge(self, accounts: List[List[str]]) -> List[List[str]]: + # TODO: Implement accounts_merge + return [] diff --git a/leetcode/accounts_merge/test_solution.py b/leetcode/accounts_merge/test_solution.py index 0667cab..7245acb 100644 --- a/leetcode/accounts_merge/test_solution.py +++ b/leetcode/accounts_merge/test_solution.py @@ -1,3 +1,5 @@ +from typing import List + import pytest from leetcode_py import logged_test @@ -21,13 +23,6 @@ def setup_method(self): ["Mary", "mary@mail.com"], ["John", "johnnybravo@mail.com"], ], - [ - ["John", "john00@mail.com", "john_newyork@mail.com", "johnsmith@mail.com"], - ["Mary", "mary@mail.com"], - ["John", "johnnybravo@mail.com"], - ], - ), - ( [ ["Gabe", "Gabe0@m.co", "Gabe3@m.co", "Gabe1@m.co"], ["Kevin", "Kevin3@m.co", "Kevin5@m.co", "Kevin0@m.co"], @@ -35,80 +30,9 @@ def setup_method(self): ["Hanzo", "Hanzo3@m.co", "Hanzo1@m.co", "Hanzo0@m.co"], ["Fern", "Fern5@m.co", "Fern1@m.co", "Fern0@m.co"], ], - [ - ["Ethan", "Ethan0@m.co", "Ethan4@m.co", "Ethan5@m.co"], - ["Gabe", "Gabe0@m.co", "Gabe1@m.co", "Gabe3@m.co"], - ["Hanzo", "Hanzo0@m.co", "Hanzo1@m.co", "Hanzo3@m.co"], - ["Kevin", "Kevin0@m.co", "Kevin3@m.co", "Kevin5@m.co"], - ["Fern", "Fern0@m.co", "Fern1@m.co", "Fern5@m.co"], - ], - ), - ([["Alice", "alice@mail.com"]], [["Alice", "alice@mail.com"]]), - ( - [["Bob", "bob1@mail.com"], ["Bob", "bob2@mail.com"]], - [["Bob", "bob1@mail.com"], ["Bob", "bob2@mail.com"]], - ), - ( - [ - ["Alice", "alice@mail.com", "alice2@mail.com"], - ["Alice", "alice2@mail.com", "alice3@mail.com"], - ], - [["Alice", "alice2@mail.com", "alice3@mail.com", "alice@mail.com"]], - ), - ( - [ - ["A", "a@mail.com", "b@mail.com"], - ["B", "b@mail.com", "c@mail.com"], - ["C", "c@mail.com", "d@mail.com"], - ], - [["A", "a@mail.com", "b@mail.com", "c@mail.com", "d@mail.com"]], - ), - ([["David", "david@mail.com"], ["David", "david@mail.com"]], [["David", "david@mail.com"]]), - ( - [["Alex", "alex1@mail.com"], ["Bob", "bob1@mail.com"], ["Charlie", "charlie1@mail.com"]], - [["Alex", "alex1@mail.com"], ["Bob", "bob1@mail.com"], ["Charlie", "charlie1@mail.com"]], - ), - ( - [ - ["John", "john1@mail.com", "john2@mail.com"], - ["John", "john3@mail.com"], - ["Jane", "jane1@mail.com"], - ], - [ - ["John", "john1@mail.com", "john2@mail.com"], - ["John", "john3@mail.com"], - ["Jane", "jane1@mail.com"], - ], - ), - ( - [ - ["User", "user@mail.com", "user1@mail.com"], - ["User", "user2@mail.com", "user@mail.com"], - ["User", "user3@mail.com", "user1@mail.com"], - ], - [["User", "user1@mail.com", "user2@mail.com", "user3@mail.com", "user@mail.com"]], - ), - ( - [ - ["Test", "test1@mail.com"], - ["Test", "test2@mail.com"], - ["Test", "test1@mail.com", "test3@mail.com"], - ], - [["Test", "test2@mail.com"], ["Test", "test1@mail.com", "test3@mail.com"]], - ), - ( - [ - ["Name", "a@mail.com", "b@mail.com", "c@mail.com"], - ["Name", "d@mail.com", "e@mail.com"], - ["Name", "c@mail.com", "f@mail.com"], - ], - [ - ["Name", "d@mail.com", "e@mail.com"], - ["Name", "a@mail.com", "b@mail.com", "c@mail.com", "f@mail.com"], - ], - ), + ) ], ) - def test_accounts_merge(self, accounts: list[list[str]], expected: list[list[str]]): + def test_accounts_merge(self, accounts: List[List[str]], expected: List[List[str]]): result = run_accounts_merge(Solution, accounts) assert_accounts_merge(result, expected) diff --git a/leetcode/add_binary/README.md b/leetcode/add_binary/README.md index 92224a0..f79e3c2 100644 --- a/leetcode/add_binary/README.md +++ b/leetcode/add_binary/README.md @@ -2,32 +2,45 @@ **Difficulty:** Easy **Topics:** Math, String, Bit Manipulation, Simulation -**Tags:** grind-75 +**Tags:** grind, grind-75 **LeetCode:** [Problem 67](https://leetcode.com/problems/add-binary/description/) + ## Problem Description -Given two binary strings `a` and `b`, return _their sum as a binary string_. +Given two binary strings a and b, return their sum as a binary string. + +  +Example 1: +Input: a = "11", b = "1" +Output: "100" +Example 2: +Input: a = "1010", b = "1011" +Output: "10101" + +  +Constraints: + + + 1 <= a.length, b.length <= 104 + a and b consist only of '0' or '1' characters. + Each string does not contain leading zeros except for the zero itself. ## Examples ### Example 1: -``` Input: a = "11", b = "1" Output: "100" -``` - -### Example 2: - -``` +Example 2: Input: a = "1010", b = "1011" Output: "10101" -``` ## Constraints -- `1 <= a.length, b.length <= 10^4` -- `a` and `b` consist only of `'0'` or `'1'` characters. +- 1 <= a.length, b.length <= 104 +- a and b consist only of '0' or '1' characters. - Each string does not contain leading zeros except for the zero itself. + + diff --git a/leetcode/add_binary/playground.ipynb b/leetcode/add_binary/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/add_binary/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/add_binary/solution.py b/leetcode/add_binary/solution.py index 36ae857..ed9ca11 100644 --- a/leetcode/add_binary/solution.py +++ b/leetcode/add_binary/solution.py @@ -1,26 +1,7 @@ class Solution: - # Time: O(len(a) + len(b)) - # Space: O(len(a) + len(b)) - def add_binary(self, a: str, b: str) -> str: - # int(a, 2) converts binary string to decimal: int("11", 2) → 3 - # bin() converts decimal to binary string with prefix: bin(3) → '0b11' - # [2:] removes the '0b' prefix to get just binary digits - return bin(int(a, 2) + int(b, 2))[2:] - -# Python Base Conversion: -# -# String → Integer (using int() with base parameter): -# - int("1010", 2) → 10 (binary to decimal) -# - int("ff", 16) → 255 (hex to decimal) -# - int("10", 8) → 8 (octal to decimal) -# -# Integer → String (conversion functions add prefixes): -# - bin(10) → '0b1010' (binary with '0b' prefix) -# - hex(255) → '0xff' (hex with '0x' prefix) -# - oct(8) → '0o10' (octal with '0o' prefix) -# -# These prefixes match Python literal syntax: -# - 0b1010 = 10, 0xff = 255, 0o10 = 8 -# -# For string problems, slice off the prefix: bin(n)[2:] gives just the digits. + # Time: O(?) + # Space: O(?) + def add_binary(self, a: str, b: str) -> str: + # TODO: Implement add_binary + return "" diff --git a/leetcode/add_binary/test_solution.py b/leetcode/add_binary/test_solution.py index bfdf6a7..2fb091a 100644 --- a/leetcode/add_binary/test_solution.py +++ b/leetcode/add_binary/test_solution.py @@ -11,22 +11,7 @@ def setup_method(self): self.solution = Solution() @logged_test - @pytest.mark.parametrize( - "a, b, expected", - [ - ("11", "1", "100"), - ("1010", "1011", "10101"), - ("0", "0", "0"), - ("1", "1", "10"), - ("1111", "1111", "11110"), - ("1", "0", "1"), - ("0", "1", "1"), - ("1", "111", "1000"), - ("111", "1", "1000"), - ("1010", "1", "1011"), - ("1111", "1", "10000"), - ], - ) + @pytest.mark.parametrize("a, b, expected", []) def test_add_binary(self, a: str, b: str, expected: str): result = run_add_binary(Solution, a, b) assert_add_binary(result, expected) diff --git a/leetcode/add_strings/README.md b/leetcode/add_strings/README.md new file mode 100644 index 0000000..2e8aa40 --- /dev/null +++ b/leetcode/add_strings/README.md @@ -0,0 +1,73 @@ +# Add Strings + +**Difficulty:** Easy +**Topics:** Math, String, Simulation +**Tags:** grind-75 + +**LeetCode:** [Problem 415](https://leetcode.com/problems/add-strings/description/) + + +## Problem Description + +Given two non-negative integers, num1 and num2 represented as string, return the sum of num1 and num2 as a string. + +You must solve the problem without using any built-in library for handling large integers (such as BigInteger). You must also not convert the inputs to integers directly. + +  +Example 1: + + +Input: num1 = "11", num2 = "123" +Output: "134" + + +Example 2: + + +Input: num1 = "456", num2 = "77" +Output: "533" + + +Example 3: + + +Input: num1 = "0", num2 = "0" +Output: "0" + + +  +Constraints: + + + 1 <= num1.length, num2.length <= 104 + num1 and num2 consist of only digits. + num1 and num2 don't have any leading zeros except for the zero itself. + +## Examples + +### Example 1: + +Input: num1 = "11", num2 = "123" +Output: "134" + + +Example 2: + + +Input: num1 = "456", num2 = "77" +Output: "533" + + +Example 3: + + +Input: num1 = "0", num2 = "0" +Output: "0" + +## Constraints + +- 1 <= num1.length, num2.length <= 104 +- num1 and num2 consist of only digits. +- num1 and num2 don't have any leading zeros except for the zero itself. + + diff --git a/leetcode/add_strings/__init__.py b/leetcode/add_strings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/add_strings/helpers.py b/leetcode/add_strings/helpers.py new file mode 100644 index 0000000..0dd1857 --- /dev/null +++ b/leetcode/add_strings/helpers.py @@ -0,0 +1,8 @@ +def run_add_strings(solution_class: type, num1: str, num2: str): + implementation = solution_class() + return implementation.add_strings(num1, num2) + + +def assert_add_strings(result: str, expected: str) -> bool: + assert result == expected + return True diff --git a/leetcode/add_strings/playground.ipynb b/leetcode/add_strings/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/add_strings/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/add_strings/solution.py b/leetcode/add_strings/solution.py new file mode 100644 index 0000000..4a02405 --- /dev/null +++ b/leetcode/add_strings/solution.py @@ -0,0 +1,7 @@ +class Solution: + + # Time: O(?) + # Space: O(?) + def add_strings(self, num1: str, num2: str) -> str: + # TODO: Implement add_strings + return "" diff --git a/leetcode/add_strings/test_solution.py b/leetcode/add_strings/test_solution.py new file mode 100644 index 0000000..e8851ad --- /dev/null +++ b/leetcode/add_strings/test_solution.py @@ -0,0 +1,17 @@ +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_add_strings, run_add_strings +from .solution import Solution + + +class TestAddStrings: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("num1, num2, expected", []) + def test_add_strings(self, num1: str, num2: str, expected: str): + result = run_add_strings(Solution, num1, num2) + assert_add_strings(result, expected) diff --git a/leetcode/add_to_array_form_of_integer/README.md b/leetcode/add_to_array_form_of_integer/README.md new file mode 100644 index 0000000..3bbf58d --- /dev/null +++ b/leetcode/add_to_array_form_of_integer/README.md @@ -0,0 +1,85 @@ +# Add to Array-Form of Integer + +**Difficulty:** Easy +**Topics:** Array, Math +**Tags:** grind-75 + +**LeetCode:** [Problem 989](https://leetcode.com/problems/add-to-array-form-of-integer/description/) + + +## Problem Description + +The array-form of an integer num is an array representing its digits in left to right order. + + + For example, for num = 1321, the array form is [1,3,2,1]. + + +Given num, the array-form of an integer, and an integer k, return the array-form of the integer num + k. + +  +Example 1: + + +Input: num = [1,2,0,0], k = 34 +Output: [1,2,3,4] +Explanation: 1200 + 34 = 1234 + + +Example 2: + + +Input: num = [2,7,4], k = 181 +Output: [4,5,5] +Explanation: 274 + 181 = 455 + + +Example 3: + + +Input: num = [2,1,5], k = 806 +Output: [1,0,2,1] +Explanation: 215 + 806 = 1021 + + +  +Constraints: + + + 1 <= num.length <= 104 + 0 <= num[i] <= 9 + num does not contain any leading zeros except for the zero itself. + 1 <= k <= 104 + +## Examples + +### Example 1: + +Input: num = [1,2,0,0], k = 34 +Output: [1,2,3,4] +Explanation: 1200 + 34 = 1234 + + +Example 2: + + +Input: num = [2,7,4], k = 181 +Output: [4,5,5] +Explanation: 274 + 181 = 455 + + +Example 3: + + +Input: num = [2,1,5], k = 806 +Output: [1,0,2,1] +Explanation: 215 + 806 = 1021 + +## Constraints + +- 1 <= num.length <= 104 +- 0 <= num[i] <= 9 +- num does not contain any leading zeros except for the zero itself. +- 1 <= k <= 104 + + diff --git a/leetcode/add_to_array_form_of_integer/__init__.py b/leetcode/add_to_array_form_of_integer/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/add_to_array_form_of_integer/helpers.py b/leetcode/add_to_array_form_of_integer/helpers.py new file mode 100644 index 0000000..b9b85c7 --- /dev/null +++ b/leetcode/add_to_array_form_of_integer/helpers.py @@ -0,0 +1,11 @@ +from typing import List + + +def run_add_to_array_form(solution_class: type, num: List[int], k: int): + implementation = solution_class() + return implementation.add_to_array_form(num, k) + + +def assert_add_to_array_form(result: List[int], expected: List[int]) -> bool: + assert result == expected + return True diff --git a/leetcode/add_to_array_form_of_integer/playground.ipynb b/leetcode/add_to_array_form_of_integer/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/add_to_array_form_of_integer/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/add_to_array_form_of_integer/solution.py b/leetcode/add_to_array_form_of_integer/solution.py new file mode 100644 index 0000000..25a3bb0 --- /dev/null +++ b/leetcode/add_to_array_form_of_integer/solution.py @@ -0,0 +1,10 @@ +from typing import List + + +class Solution: + + # Time: O(?) + # Space: O(?) + def add_to_array_form(self, num: List[int], k: int) -> List[int]: + # TODO: Implement add_to_array_form + return [] diff --git a/leetcode/add_to_array_form_of_integer/test_solution.py b/leetcode/add_to_array_form_of_integer/test_solution.py new file mode 100644 index 0000000..74f6887 --- /dev/null +++ b/leetcode/add_to_array_form_of_integer/test_solution.py @@ -0,0 +1,19 @@ +from typing import List + +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_add_to_array_form, run_add_to_array_form +from .solution import Solution + + +class TestAddToArrayFormOfInteger: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("num, k, expected", []) + def test_add_to_array_form(self, num: List[int], k: int, expected: List[int]): + result = run_add_to_array_form(Solution, num, k) + assert_add_to_array_form(result, expected) diff --git a/leetcode/assign_cookies/README.md b/leetcode/assign_cookies/README.md new file mode 100644 index 0000000..8c3d17e --- /dev/null +++ b/leetcode/assign_cookies/README.md @@ -0,0 +1,75 @@ +# Assign Cookies + +**Difficulty:** Easy +**Topics:** Array, Two Pointers, Greedy, Sorting +**Tags:** grind-75 + +**LeetCode:** [Problem 455](https://leetcode.com/problems/assign-cookies/description/) + + +## Problem Description + +Assume you are an awesome parent and want to give your children some cookies. But, you should give each child at most one cookie. + +Each child i has a greed factor g[i], which is the minimum size of a cookie that the child will be content with; and each cookie j has a size s[j]. If s[j] >= g[i], we can assign the cookie j to the child i, and the child i will be content. Your goal is to maximize the number of your content children and output the maximum number. + +  +Example 1: + + +Input: g = [1,2,3], s = [1,1] +Output: 1 +Explanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3. +And even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content. +You need to output 1. + + +Example 2: + + +Input: g = [1,2], s = [1,2,3] +Output: 2 +Explanation: You have 2 children and 3 cookies. The greed factors of 2 children are 1, 2. +You have 3 cookies and their sizes are big enough to gratify all of the children, +You need to output 2. + + +  +Constraints: + + + 1 <= g.length <= 3 * 104 + 0 <= s.length <= 3 * 104 + 1 <= g[i], s[j] <= 231 - 1 + + +  +Note: This question is the same as 2410: Maximum Matching of Players With Trainers. + +## Examples + +### Example 1: + +Input: g = [1,2,3], s = [1,1] +Output: 1 +Explanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3. +And even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content. +You need to output 1. + + +Example 2: + + +Input: g = [1,2], s = [1,2,3] +Output: 2 +Explanation: You have 2 children and 3 cookies. The greed factors of 2 children are 1, 2. +You have 3 cookies and their sizes are big enough to gratify all of the children, +You need to output 2. + +## Constraints + +- 1 <= g.length <= 3 * 104 +- 0 <= s.length <= 3 * 104 +- 1 <= g[i], s[j] <= 231 - 1 + + diff --git a/leetcode/assign_cookies/__init__.py b/leetcode/assign_cookies/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/assign_cookies/helpers.py b/leetcode/assign_cookies/helpers.py new file mode 100644 index 0000000..771bbc3 --- /dev/null +++ b/leetcode/assign_cookies/helpers.py @@ -0,0 +1,11 @@ +from typing import List + + +def run_find_content_children(solution_class: type, g: List[int], s: List[int]): + implementation = solution_class() + return implementation.find_content_children(g, s) + + +def assert_find_content_children(result: int, expected: int) -> bool: + assert result == expected + return True diff --git a/leetcode/assign_cookies/playground.ipynb b/leetcode/assign_cookies/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/assign_cookies/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/assign_cookies/solution.py b/leetcode/assign_cookies/solution.py new file mode 100644 index 0000000..6888be6 --- /dev/null +++ b/leetcode/assign_cookies/solution.py @@ -0,0 +1,10 @@ +from typing import List + + +class Solution: + + # Time: O(?) + # Space: O(?) + def find_content_children(self, g: List[int], s: List[int]) -> int: + # TODO: Implement find_content_children + return 0 diff --git a/leetcode/assign_cookies/test_solution.py b/leetcode/assign_cookies/test_solution.py new file mode 100644 index 0000000..75d4a9c --- /dev/null +++ b/leetcode/assign_cookies/test_solution.py @@ -0,0 +1,19 @@ +from typing import List + +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_find_content_children, run_find_content_children +from .solution import Solution + + +class TestAssignCookies: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("g, s, expected", []) + def test_find_content_children(self, g: List[int], s: List[int], expected: int): + result = run_find_content_children(Solution, g, s) + assert_find_content_children(result, expected) diff --git a/leetcode/asteroid_collision/README.md b/leetcode/asteroid_collision/README.md new file mode 100644 index 0000000..10dec58 --- /dev/null +++ b/leetcode/asteroid_collision/README.md @@ -0,0 +1,97 @@ +# Asteroid Collision + +**Difficulty:** Medium +**Topics:** Array, Stack, Simulation +**Tags:** grind-75 + +**LeetCode:** [Problem 735](https://leetcode.com/problems/asteroid-collision/description/) + + +## Problem Description + +We are given an array asteroids of integers representing asteroids in a row. The indices of the asteroid in the array represent their relative position in space. + +For each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed. + +Find out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet. + +  +Example 1: + + +Input: asteroids = [5,10,-5] +Output: [5,10] +Explanation: The 10 and -5 collide resulting in 10. The 5 and 10 never collide. + + +Example 2: + + +Input: asteroids = [8,-8] +Output: [] +Explanation: The 8 and -8 collide exploding each other. + + +Example 3: + + +Input: asteroids = [10,2,-5] +Output: [10] +Explanation: The 2 and -5 collide resulting in -5. The 10 and -5 collide resulting in 10. + + +Example 4: + + +Input: asteroids = [3,5,-6,2,-1,4]​​​​​​​ +Output: [-6,2,4] +Explanation: The asteroid -6 makes the asteroid 3 and 5 explode, and then continues going left. On the other side, the asteroid 2 makes the asteroid -1 explode and then continues going right, without reaching asteroid 4. + + +  +Constraints: + + + 2 <= asteroids.length <= 104 + -1000 <= asteroids[i] <= 1000 + asteroids[i] != 0 + +## Examples + +### Example 1: + +Input: asteroids = [5,10,-5] +Output: [5,10] +Explanation: The 10 and -5 collide resulting in 10. The 5 and 10 never collide. + + +Example 2: + + +Input: asteroids = [8,-8] +Output: [] +Explanation: The 8 and -8 collide exploding each other. + + +Example 3: + + +Input: asteroids = [10,2,-5] +Output: [10] +Explanation: The 2 and -5 collide resulting in -5. The 10 and -5 collide resulting in 10. + + +Example 4: + + +Input: asteroids = [3,5,-6,2,-1,4]​​​​​​​ +Output: [-6,2,4] +Explanation: The asteroid -6 makes the asteroid 3 and 5 explode, and then continues going left. On the other side, the asteroid 2 makes the asteroid -1 explode and then continues going right, without reaching asteroid 4. + +## Constraints + +- 2 <= asteroids.length <= 104 +- -1000 <= asteroids[i] <= 1000 +- asteroids[i] != 0 + + diff --git a/leetcode/asteroid_collision/__init__.py b/leetcode/asteroid_collision/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/asteroid_collision/helpers.py b/leetcode/asteroid_collision/helpers.py new file mode 100644 index 0000000..e47c31a --- /dev/null +++ b/leetcode/asteroid_collision/helpers.py @@ -0,0 +1,11 @@ +from typing import List + + +def run_asteroid_collision(solution_class: type, asteroids: List[int]): + implementation = solution_class() + return implementation.asteroid_collision(asteroids) + + +def assert_asteroid_collision(result: List[int], expected: List[int]) -> bool: + assert result == expected + return True diff --git a/leetcode/asteroid_collision/playground.ipynb b/leetcode/asteroid_collision/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/asteroid_collision/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/asteroid_collision/solution.py b/leetcode/asteroid_collision/solution.py new file mode 100644 index 0000000..b7f6958 --- /dev/null +++ b/leetcode/asteroid_collision/solution.py @@ -0,0 +1,10 @@ +from typing import List + + +class Solution: + + # Time: O(?) + # Space: O(?) + def asteroid_collision(self, asteroids: List[int]) -> List[int]: + # TODO: Implement asteroid_collision + return [] diff --git a/leetcode/asteroid_collision/test_solution.py b/leetcode/asteroid_collision/test_solution.py new file mode 100644 index 0000000..0d86c75 --- /dev/null +++ b/leetcode/asteroid_collision/test_solution.py @@ -0,0 +1,19 @@ +from typing import List + +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_asteroid_collision, run_asteroid_collision +from .solution import Solution + + +class TestAsteroidCollision: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("asteroids, expected", []) + def test_asteroid_collision(self, asteroids: List[int], expected: List[int]): + result = run_asteroid_collision(Solution, asteroids) + assert_asteroid_collision(result, expected) diff --git a/leetcode/backspace_string_compare/README.md b/leetcode/backspace_string_compare/README.md new file mode 100644 index 0000000..8fd3a83 --- /dev/null +++ b/leetcode/backspace_string_compare/README.md @@ -0,0 +1,81 @@ +# Backspace String Compare + +**Difficulty:** Easy +**Topics:** Two Pointers, String, Stack, Simulation +**Tags:** grind-75 + +**LeetCode:** [Problem 844](https://leetcode.com/problems/backspace-string-compare/description/) + + +## Problem Description + +Given two strings s and t, return true if they are equal when both are typed into empty text editors. '#' means a backspace character. + +Note that after backspacing an empty text, the text will continue empty. + +  +Example 1: + + +Input: s = "ab#c", t = "ad#c" +Output: true +Explanation: Both s and t become "ac". + + +Example 2: + + +Input: s = "ab##", t = "c#d#" +Output: true +Explanation: Both s and t become "". + + +Example 3: + + +Input: s = "a#c", t = "b" +Output: false +Explanation: s becomes "c" while t becomes "b". + + +  +Constraints: + + + 1 <= s.length, t.length <= 200 + s and t only contain lowercase letters and '#' characters. + + +  +Follow up: Can you solve it in O(n) time and O(1) space? + +## Examples + +### Example 1: + +Input: s = "ab#c", t = "ad#c" +Output: true +Explanation: Both s and t become "ac". + + +Example 2: + + +Input: s = "ab##", t = "c#d#" +Output: true +Explanation: Both s and t become "". + + +Example 3: + + +Input: s = "a#c", t = "b" +Output: false +Explanation: s becomes "c" while t becomes "b". + +## Constraints + +- 1 <= s.length, t.length <= 200 +- s and t only contain lowercase letters and '#' characters. + + diff --git a/leetcode/backspace_string_compare/__init__.py b/leetcode/backspace_string_compare/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/backspace_string_compare/helpers.py b/leetcode/backspace_string_compare/helpers.py new file mode 100644 index 0000000..fe28b12 --- /dev/null +++ b/leetcode/backspace_string_compare/helpers.py @@ -0,0 +1,8 @@ +def run_backspace_compare(solution_class: type, s: str, t: str): + implementation = solution_class() + return implementation.backspace_compare(s, t) + + +def assert_backspace_compare(result: bool, expected: bool) -> bool: + assert result == expected + return True diff --git a/leetcode/backspace_string_compare/playground.ipynb b/leetcode/backspace_string_compare/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/backspace_string_compare/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/backspace_string_compare/solution.py b/leetcode/backspace_string_compare/solution.py new file mode 100644 index 0000000..7210fcf --- /dev/null +++ b/leetcode/backspace_string_compare/solution.py @@ -0,0 +1,7 @@ +class Solution: + + # Time: O(?) + # Space: O(?) + def backspace_compare(self, s: str, t: str) -> bool: + # TODO: Implement backspace_compare + return False diff --git a/leetcode/backspace_string_compare/test_solution.py b/leetcode/backspace_string_compare/test_solution.py new file mode 100644 index 0000000..945b0a3 --- /dev/null +++ b/leetcode/backspace_string_compare/test_solution.py @@ -0,0 +1,17 @@ +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_backspace_compare, run_backspace_compare +from .solution import Solution + + +class TestBackspaceStringCompare: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("s, t, expected", []) + def test_backspace_compare(self, s: str, t: str, expected: bool): + result = run_backspace_compare(Solution, s, t) + assert_backspace_compare(result, expected) diff --git a/leetcode/basic_calculator/README.md b/leetcode/basic_calculator/README.md index 885a6c8..3b3313d 100644 --- a/leetcode/basic_calculator/README.md +++ b/leetcode/basic_calculator/README.md @@ -2,45 +2,80 @@ **Difficulty:** Hard **Topics:** Math, String, Stack, Recursion -**Tags:** grind-75 +**Tags:** grind, grind-75 **LeetCode:** [Problem 224](https://leetcode.com/problems/basic-calculator/description/) + ## Problem Description -Given a string `s` representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation. +Given a string s representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation. + +Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval(). + +  +Example 1: + + +Input: s = "1 + 1" +Output: 2 + + +Example 2: + + +Input: s = " 2-1 + 2 " +Output: 3 + + +Example 3: -**Note:** You are **not** allowed to use any built-in function which evaluates strings as mathematical expressions, such as `eval()`. + +Input: s = "(1+(4+5+2)-3)+(6+8)" +Output: 23 + + +  +Constraints: + + + 1 <= s.length <= 3 * 105 + s consists of digits, '+', '-', '(', ')', and ' '. + s represents a valid expression. + '+' is not used as a unary operation (i.e., "+1" and "+(2 + 3)" is invalid). + '-' could be used as a unary operation (i.e., "-1" and "-(2 + 3)" is valid). + There will be no two consecutive operators in the input. + Every number and running calculation will fit in a signed 32-bit integer. ## Examples ### Example 1: -``` -Input: s = "1 + 1" +Input: s = "1 + 1" Output: 2 -``` -### Example 2: -``` -Input: s = " 2-1 + 2 " +Example 2: + + +Input: s = " 2-1 + 2 " Output: 3 -``` -### Example 3: -``` -Input: s = "(1+(4+5+2)-3)+(6+8)" +Example 3: + + +Input: s = "(1+(4+5+2)-3)+(6+8)" Output: 23 -``` ## Constraints -- `1 <= s.length <= 3 * 10^5` -- `s` consists of digits, `'+'`, `'-'`, `'('`, `')'`, and `' '`. -- `s` represents a valid expression. -- `'+'` is **not** used as a unary operation (i.e., `"+1"` and `"+(2 + 3)"` is invalid). -- `'-'` could be used as a unary operation (i.e., `"-1"` and `"-(2 + 3)"` is valid). +- 1 <= s.length <= 3 * 105 +- s consists of digits, '+', '-', '(', ')', and ' '. +- s represents a valid expression. +- '+' is not used as a unary operation (i.e., "+1" and "+(2 + 3)" is invalid). +- '-' could be used as a unary operation (i.e., "-1" and "-(2 + 3)" is valid). - There will be no two consecutive operators in the input. - Every number and running calculation will fit in a signed 32-bit integer. + + diff --git a/leetcode/basic_calculator/playground.ipynb b/leetcode/basic_calculator/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/basic_calculator/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/basic_calculator/solution.py b/leetcode/basic_calculator/solution.py index e441460..d4b221a 100644 --- a/leetcode/basic_calculator/solution.py +++ b/leetcode/basic_calculator/solution.py @@ -1,61 +1,7 @@ class Solution: - # Time: O(n) - # Space: O(n) - def calculate(self, s: str) -> int: - stack = [] - num = 0 - sign = 1 - result = 0 - - for char in s: - if char.isdigit(): - num = num * 10 + int(char) - elif char in "+-": - result += sign * num - num = 0 - sign = 1 if char == "+" else -1 - elif char == "(": - stack.append(result) - stack.append(sign) - result = 0 - sign = 1 - elif char == ")": - if len(stack) < 2: - raise ValueError("Mismatched parentheses") - result += sign * num - num = 0 - result *= stack.pop() - result += stack.pop() - elif char != " ": - raise ValueError(f"Invalid character: '{char}'") - - if stack: - raise ValueError("Mismatched parentheses") - return result + sign * num - - -# Example walkthrough: "(1+(4+5+2)-3)+(6+8)" = 23 -# -# char | num | sign | result | stack | action -# -----|-----|------|--------|------------|------------------ -# '(' | 0 | 1 | 0 | [0, 1] | push result=0, sign=1 -# '1' | 1 | 1 | 0 | [0, 1] | build num=1 -# '+' | 0 | 1 | 1 | [0, 1] | result += 1*1 = 1 -# '(' | 0 | 1 | 0 | [0,1,1,1] | push result=1, sign=1 -# '4' | 4 | 1 | 0 | [0,1,1,1] | build num=4 -# '+' | 0 | 1 | 4 | [0,1,1,1] | result += 1*4 = 4 -# '5' | 5 | 1 | 4 | [0,1,1,1] | build num=5 -# '+' | 0 | 1 | 9 | [0,1,1,1] | result += 1*5 = 9 -# '2' | 2 | 1 | 9 | [0,1,1,1] | build num=2 -# ')' | 0 | 1 | 11 | [0, 1] | result=11*1+1 = 12 -# '-' | 0 | -1 | 12 | [0, 1] | sign = -1 -# '3' | 3 | -1 | 12 | [0, 1] | build num=3 -# ')' | 0 | 1 | 9 | [] | result=9*1+0 = 9 -# '+' | 0 | 1 | 9 | [] | sign = 1 -# '(' | 0 | 1 | 0 | [9, 1] | push result=9, sign=1 -# '6' | 6 | 1 | 0 | [9, 1] | build num=6 -# '+' | 0 | 1 | 6 | [9, 1] | result += 1*6 = 6 -# '8' | 8 | 1 | 6 | [9, 1] | build num=8 -# ')' | 0 | 1 | 14 | [] | result=14*1+9 = 23 -# end | 0 | 1 | 14 | [] | return 14+1*0 = 23 + # Time: O(?) + # Space: O(?) + def calculate(self, s: str) -> int: + # TODO: Implement calculate + return 0 diff --git a/leetcode/basic_calculator/test_solution.py b/leetcode/basic_calculator/test_solution.py index 6bbc871..dc24275 100644 --- a/leetcode/basic_calculator/test_solution.py +++ b/leetcode/basic_calculator/test_solution.py @@ -11,57 +11,7 @@ def setup_method(self): self.solution = Solution() @logged_test - @pytest.mark.parametrize( - "s, expected", - [ - ("1 + 1", 2), - (" 2-1 + 2 ", 3), - ("(1+(4+5+2)-3)+(6+8)", 23), - ("1", 1), - ("-1", -1), - ("-(1+2)", -3), - ("2147483647", 2147483647), - ("1-1+1", 1), - # Additional edge cases from old tests - ("0", 0), - ("-0", 0), - ("1+(2+3)", 6), - ("(1+2)+3", 6), - ("1-(2+3)", -4), - ("(1-2)+3", 2), - ("-(-1)", 1), - ("-(-(-1))", -1), - ("1000000-999999", 1), - ("10+20-30+40", 40), - ("((1+2)+(3+4))", 10), - ("1+(2-(3+4))", -4), - ("-(1+(2+3))", -6), - (" 1 + 2 ", 3), - ("123+456", 579), - ("-2147483648", -2147483648), - ], - ) + @pytest.mark.parametrize("s, expected", []) def test_calculate(self, s: str, expected: int): result = run_calculate(Solution, s) assert_calculate(result, expected) - - @logged_test - @pytest.mark.parametrize( - "s, error_msg", - [ - ("(1+2", "Mismatched parentheses"), - ("1+2)", "Mismatched parentheses"), - ("((1+2)", "Mismatched parentheses"), - ("1+2))", "Mismatched parentheses"), - ("1*2", r"Invalid character: '\*'"), - ("1/2", "Invalid character: '/'"), - ("1%2", "Invalid character: '%'"), - ("1^2", r"Invalid character: '\^'"), - ("1&2", "Invalid character: '&'"), - ("a+b", "Invalid character: 'a'"), - ("1+2.5", r"Invalid character: '\.'"), - ], - ) - def test_calculate_invalid_input(self, s: str, error_msg: str): - with pytest.raises(ValueError, match=error_msg): - self.solution.calculate(s) diff --git a/leetcode/basic_calculator_ii/README.md b/leetcode/basic_calculator_ii/README.md new file mode 100644 index 0000000..b487648 --- /dev/null +++ b/leetcode/basic_calculator_ii/README.md @@ -0,0 +1,62 @@ +# Basic Calculator II + +**Difficulty:** Medium +**Topics:** Math, String, Stack +**Tags:** grind-75 + +**LeetCode:** [Problem 227](https://leetcode.com/problems/basic-calculator-ii/description/) + + +## Problem Description + +Given a string s which represents an expression, evaluate this expression and return its value.  + +The integer division should truncate toward zero. + +You may assume that the given expression is always valid. All intermediate results will be in the range of [-231, 231 - 1]. + +Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval(). + +  +Example 1: +Input: s = "3+2*2" +Output: 7 +Example 2: +Input: s = " 3/2 " +Output: 1 +Example 3: +Input: s = " 3+5 / 2 " +Output: 5 + +  +Constraints: + + + 1 <= s.length <= 3 * 105 + s consists of integers and operators ('+', '-', '*', '/') separated by some number of spaces. + s represents a valid expression. + All the integers in the expression are non-negative integers in the range [0, 231 - 1]. + The answer is guaranteed to fit in a 32-bit integer. + +## Examples + +### Example 1: + +Input: s = "3+2*2" +Output: 7 +Example 2: +Input: s = " 3/2 " +Output: 1 +Example 3: +Input: s = " 3+5 / 2 " +Output: 5 + +## Constraints + +- 1 <= s.length <= 3 * 105 +- s consists of integers and operators ('+', '-', '*', '/') separated by some number of spaces. +- s represents a valid expression. +- All the integers in the expression are non-negative integers in the range [0, 231 - 1]. +- The answer is guaranteed to fit in a 32-bit integer. + + diff --git a/leetcode/basic_calculator_ii/__init__.py b/leetcode/basic_calculator_ii/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/basic_calculator_ii/helpers.py b/leetcode/basic_calculator_ii/helpers.py new file mode 100644 index 0000000..295f681 --- /dev/null +++ b/leetcode/basic_calculator_ii/helpers.py @@ -0,0 +1,8 @@ +def run_calculate(solution_class: type, s: str): + implementation = solution_class() + return implementation.calculate(s) + + +def assert_calculate(result: int, expected: int) -> bool: + assert result == expected + return True diff --git a/leetcode/basic_calculator_ii/playground.ipynb b/leetcode/basic_calculator_ii/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/basic_calculator_ii/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/basic_calculator_ii/solution.py b/leetcode/basic_calculator_ii/solution.py new file mode 100644 index 0000000..d4b221a --- /dev/null +++ b/leetcode/basic_calculator_ii/solution.py @@ -0,0 +1,7 @@ +class Solution: + + # Time: O(?) + # Space: O(?) + def calculate(self, s: str) -> int: + # TODO: Implement calculate + return 0 diff --git a/leetcode/basic_calculator_ii/test_solution.py b/leetcode/basic_calculator_ii/test_solution.py new file mode 100644 index 0000000..3b3899c --- /dev/null +++ b/leetcode/basic_calculator_ii/test_solution.py @@ -0,0 +1,17 @@ +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_calculate, run_calculate +from .solution import Solution + + +class TestBasicCalculatorIi: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("s, expected", []) + def test_calculate(self, s: str, expected: int): + result = run_calculate(Solution, s) + assert_calculate(result, expected) diff --git a/leetcode/best_time_to_buy_and_sell_stock/README.md b/leetcode/best_time_to_buy_and_sell_stock/README.md index a18f45b..59ddd9a 100644 --- a/leetcode/best_time_to_buy_and_sell_stock/README.md +++ b/leetcode/best_time_to_buy_and_sell_stock/README.md @@ -2,40 +2,64 @@ **Difficulty:** Easy **Topics:** Array, Dynamic Programming -**Tags:** grind-75 +**Tags:** grind-75, neetcode-150, blind-75, grind **LeetCode:** [Problem 121](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/) + ## Problem Description -You are given an array `prices` where `prices[i]` is the price of a given stock on the ith day. +You are given an array prices where prices[i] is the price of a given stock on the ith day. + +You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock. + +Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0. + +  +Example 1: + + +Input: prices = [7,1,5,3,6,4] +Output: 5 +Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. +Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell. -You want to maximize your profit by choosing a **single day** to buy one stock and choosing a **different day in the future** to sell that stock. -Return _the maximum profit you can achieve from this transaction_. If you cannot achieve any profit, return `0`. +Example 2: + + +Input: prices = [7,6,4,3,1] +Output: 0 +Explanation: In this case, no transactions are done and the max profit = 0. + + +  +Constraints: + + + 1 <= prices.length <= 105 + 0 <= prices[i] <= 104 ## Examples ### Example 1: -``` Input: prices = [7,1,5,3,6,4] Output: 5 -``` - -**Explanation:** Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. +Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell. -### Example 2: -``` +Example 2: + + Input: prices = [7,6,4,3,1] Output: 0 -``` - -**Explanation:** In this case, no transactions are done and the max profit = 0. +Explanation: In this case, no transactions are done and the max profit = 0. ## Constraints -- 1 <= prices.length <= 10^5 -- 0 <= prices[i] <= 10^4 +- 1 <= prices.length <= 105 +- 0 <= prices[i] <= 104 + + diff --git a/leetcode/best_time_to_buy_and_sell_stock/helpers.py b/leetcode/best_time_to_buy_and_sell_stock/helpers.py index 90c2b1e..b3eaced 100644 --- a/leetcode/best_time_to_buy_and_sell_stock/helpers.py +++ b/leetcode/best_time_to_buy_and_sell_stock/helpers.py @@ -1,4 +1,7 @@ -def run_max_profit(solution_class: type, prices: list[int]): +from typing import List + + +def run_max_profit(solution_class: type, prices: List[int]): implementation = solution_class() return implementation.max_profit(prices) diff --git a/leetcode/best_time_to_buy_and_sell_stock/playground.ipynb b/leetcode/best_time_to_buy_and_sell_stock/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/best_time_to_buy_and_sell_stock/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/best_time_to_buy_and_sell_stock/solution.py b/leetcode/best_time_to_buy_and_sell_stock/solution.py index 4f877ec..dadcf40 100644 --- a/leetcode/best_time_to_buy_and_sell_stock/solution.py +++ b/leetcode/best_time_to_buy_and_sell_stock/solution.py @@ -1,12 +1,10 @@ -class Solution: - # Time: O(n) - # Space: O(1) - def max_profit(self, prices: list[int]) -> int: - min_price = prices[0] - max_profit = 0 +from typing import List + - for price in prices[1:]: - max_profit = max(max_profit, price - min_price) - min_price = min(min_price, price) +class Solution: - return max_profit + # Time: O(?) + # Space: O(?) + def max_profit(self, prices: List[int]) -> int: + # TODO: Implement max_profit + return 0 diff --git a/leetcode/best_time_to_buy_and_sell_stock/test_solution.py b/leetcode/best_time_to_buy_and_sell_stock/test_solution.py index 4100e9f..6221e51 100644 --- a/leetcode/best_time_to_buy_and_sell_stock/test_solution.py +++ b/leetcode/best_time_to_buy_and_sell_stock/test_solution.py @@ -1,3 +1,5 @@ +from typing import List + import pytest from leetcode_py import logged_test @@ -11,26 +13,7 @@ def setup_method(self): self.solution = Solution() @logged_test - @pytest.mark.parametrize( - "prices, expected", - [ - ([7, 1, 5, 3, 6, 4], 5), - ([7, 6, 4, 3, 1], 0), - ([1, 2, 3, 4, 5], 4), - ([5, 4, 3, 2, 1], 0), - ([1], 0), - ([2, 1], 0), - ([1, 2], 1), - ([3, 2, 6, 5, 0, 3], 4), - ([2, 4, 1], 2), - ([1, 5, 3, 6, 4], 5), - ([10, 1, 5, 6, 7, 1], 6), - ([6, 1, 3, 2, 4, 7], 6), - ([1, 4, 2], 3), - ([3, 3, 5, 0, 0, 3, 1, 4], 4), - ([2, 1, 2, 1, 0, 1, 2], 2), - ], - ) - def test_max_profit(self, prices: list[int], expected: int): + @pytest.mark.parametrize("prices, expected", [([7, 1, 5, 3, 6, 4], [7, 6, 4, 3, 1])]) + def test_max_profit(self, prices: List[int], expected: int): result = run_max_profit(Solution, prices) assert_max_profit(result, expected) diff --git a/leetcode/best_time_to_buy_and_sell_stock_ii/README.md b/leetcode/best_time_to_buy_and_sell_stock_ii/README.md new file mode 100644 index 0000000..c7e466e --- /dev/null +++ b/leetcode/best_time_to_buy_and_sell_stock_ii/README.md @@ -0,0 +1,85 @@ +# Best Time to Buy and Sell Stock II + +**Difficulty:** Medium +**Topics:** Array, Dynamic Programming, Greedy +**Tags:** grind-75 + +**LeetCode:** [Problem 122](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/description/) + + +## Problem Description + +You are given an integer array prices where prices[i] is the price of a given stock on the ith day. + +On each day, you may decide to buy and/or sell the stock. You can only hold at most one share of the stock at any time. However, you can sell and buy the stock multiple times on the same day, ensuring you never hold more than one share of the stock. + +Find and return the maximum profit you can achieve. + +  +Example 1: + + +Input: prices = [7,1,5,3,6,4] +Output: 7 +Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4. +Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3. +Total profit is 4 + 3 = 7. + + +Example 2: + + +Input: prices = [1,2,3,4,5] +Output: 4 +Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. +Total profit is 4. + + +Example 3: + + +Input: prices = [7,6,4,3,1] +Output: 0 +Explanation: There is no way to make a positive profit, so we never buy the stock to achieve the maximum profit of 0. + + +  +Constraints: + + + 1 <= prices.length <= 3 * 104 + 0 <= prices[i] <= 104 + +## Examples + +### Example 1: + +Input: prices = [7,1,5,3,6,4] +Output: 7 +Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4. +Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3. +Total profit is 4 + 3 = 7. + + +Example 2: + + +Input: prices = [1,2,3,4,5] +Output: 4 +Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. +Total profit is 4. + + +Example 3: + + +Input: prices = [7,6,4,3,1] +Output: 0 +Explanation: There is no way to make a positive profit, so we never buy the stock to achieve the maximum profit of 0. + +## Constraints + +- 1 <= prices.length <= 3 * 104 +- 0 <= prices[i] <= 104 + + diff --git a/leetcode/best_time_to_buy_and_sell_stock_ii/__init__.py b/leetcode/best_time_to_buy_and_sell_stock_ii/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/leetcode/best_time_to_buy_and_sell_stock_ii/helpers.py b/leetcode/best_time_to_buy_and_sell_stock_ii/helpers.py new file mode 100644 index 0000000..b3eaced --- /dev/null +++ b/leetcode/best_time_to_buy_and_sell_stock_ii/helpers.py @@ -0,0 +1,11 @@ +from typing import List + + +def run_max_profit(solution_class: type, prices: List[int]): + implementation = solution_class() + return implementation.max_profit(prices) + + +def assert_max_profit(result: int, expected: int) -> bool: + assert result == expected + return True diff --git a/leetcode/best_time_to_buy_and_sell_stock_ii/playground.ipynb b/leetcode/best_time_to_buy_and_sell_stock_ii/playground.ipynb new file mode 100644 index 0000000..38bebef --- /dev/null +++ b/leetcode/best_time_to_buy_and_sell_stock_ii/playground.ipynb @@ -0,0 +1,56 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "imports", + "metadata": {}, + "outputs": [], + "source": ["from helpers import run_two_sum, assert_two_sum\nfrom solution import Solution"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "setup", + "metadata": {}, + "outputs": [], + "source": ["# Example test case\nnums = [2, 7, 11, 15]\ntarget = 9\nexpected = [0, 1]"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "run", + "metadata": {}, + "outputs": [], + "source": ["result = run_two_sum(Solution, nums, target)\nresult"] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "assert", + "metadata": {}, + "outputs": [], + "source": ["assert_two_sum(result, expected)"] + } + ], + "metadata": { + "kernelspec": { + "display_name": "leetcode-py-py3.13", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python3", + "version": "3.13.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/leetcode/best_time_to_buy_and_sell_stock_ii/solution.py b/leetcode/best_time_to_buy_and_sell_stock_ii/solution.py new file mode 100644 index 0000000..dadcf40 --- /dev/null +++ b/leetcode/best_time_to_buy_and_sell_stock_ii/solution.py @@ -0,0 +1,10 @@ +from typing import List + + +class Solution: + + # Time: O(?) + # Space: O(?) + def max_profit(self, prices: List[int]) -> int: + # TODO: Implement max_profit + return 0 diff --git a/leetcode/best_time_to_buy_and_sell_stock_ii/test_solution.py b/leetcode/best_time_to_buy_and_sell_stock_ii/test_solution.py new file mode 100644 index 0000000..12d29c1 --- /dev/null +++ b/leetcode/best_time_to_buy_and_sell_stock_ii/test_solution.py @@ -0,0 +1,19 @@ +from typing import List + +import pytest + +from leetcode_py import logged_test + +from .helpers import assert_max_profit, run_max_profit +from .solution import Solution + + +class TestBestTimeToBuyAndSellStockIi: + def setup_method(self): + self.solution = Solution() + + @logged_test + @pytest.mark.parametrize("prices, expected", []) + def test_max_profit(self, prices: List[int], expected: int): + result = run_max_profit(Solution, prices) + assert_max_profit(result, expected) diff --git a/leetcode_py/cli/resources/leetcode/json/problems/_01_matrix.json b/leetcode_py/cli/resources/leetcode/json/problems/_01_matrix.json new file mode 100644 index 0000000..89a2d49 --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/_01_matrix.json @@ -0,0 +1,48 @@ +{ + "problem_name": "_01_matrix", + "problem_number": "542", + "problem_title": "01 Matrix", + "difficulty": "Medium", + "topics": "Array, Dynamic Programming, Breadth-First Search, Matrix", + "readme_description": "Given an m x n binary matrix mat, return the distance of the nearest 0 for each cell.\n\nThe distance between two cells sharing a common edge is 1.\n\n \nExample 1:\n\n\nInput: mat = [[0,0,0],[0,1,0],[0,0,0]]\nOutput: [[0,0,0],[0,1,0],[0,0,0]]\n\n\nExample 2:\n\n\nInput: mat = [[0,0,0],[0,1,0],[1,1,1]]\nOutput: [[0,0,0],[0,1,0],[1,2,1]]\n\n\n \nConstraints:\n\n\n\tm == mat.length\n\tn == mat[i].length\n\t1 <= m, n <= 104\n\t1 <= m * n <= 104\n\tmat[i][j] is either 0 or 1.\n\tThere is at least one 0 in mat.\n\n\n \nNote: This question is the same as 1765: https://leetcode.com/problems/map-of-highest-peak/", + "readme_constraints": "- m == mat.length\n- n == mat[i].length\n- 1 <= m, n <= 104\n- 1 <= m * n <= 104\n- mat[i][j] is either 0 or 1.\n- There is at least one 0 in mat.", + "_readme_examples": { + "list": [] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "update_matrix", + "signature": "(self, mat: List[List[int]])-> List[List[int]]", + "body": " # TODO: Implement update_matrix\n return []" + } + ] + }, + "helpers_run_name": "update_matrix", + "helpers_run_signature": "(solution_class: type, mat: List[List[int]])", + "helpers_run_body": " implementation = solution_class()\n return implementation.update_matrix(mat)", + "helpers_assert_name": "update_matrix", + "helpers_assert_signature": "(result: List[List[int]], expected: List[List[int]]) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "01Matrix", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_update_matrix", + "signature": "(self, mat: List[List[int]], expected: List[List[int]])", + "parametrize": "mat, expected", + "test_cases": { + "list": [ + "([[0,0,0],[0,1,0],[0,0,0]], [[0,0,0],[0,1,0],[1,1,1]])" + ] + }, + "body": " result = run_update_matrix(Solution, mat)\n assert_update_matrix(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_update_matrix, run_update_matrix\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/_3sum.json b/leetcode_py/cli/resources/leetcode/json/problems/_3sum.json new file mode 100644 index 0000000..bbfc58b --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/_3sum.json @@ -0,0 +1,50 @@ +{ + "problem_name": "_3sum", + "problem_number": "15", + "problem_title": "3Sum", + "difficulty": "Medium", + "topics": "Array, Two Pointers, Sorting", + "readme_description": "Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.\n\nNotice that the solution set must not contain duplicate triplets.\n\n \nExample 1:\n\n\nInput: nums = [-1,0,1,2,-1,-4]\nOutput: [[-1,-1,2],[-1,0,1]]\nExplanation: \nnums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.\nnums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.\nnums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.\nThe distinct triplets are [-1,0,1] and [-1,-1,2].\nNotice that the order of the output and the order of the triplets does not matter.\n\n\nExample 2:\n\n\nInput: nums = [0,1,1]\nOutput: []\nExplanation: The only possible triplet does not sum up to 0.\n\n\nExample 3:\n\n\nInput: nums = [0,0,0]\nOutput: [[0,0,0]]\nExplanation: The only possible triplet sums up to 0.\n\n\n \nConstraints:\n\n\n\t3 <= nums.length <= 3000\n\t-105 <= nums[i] <= 105", + "readme_constraints": "- 3 <= nums.length <= 3000\n- -105 <= nums[i] <= 105", + "_readme_examples": { + "list": [ + { + "content": "Input: nums = [-1,0,1,2,-1,-4]\nOutput: [[-1,-1,2],[-1,0,1]]\nExplanation: \nnums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0.\nnums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0.\nnums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0.\nThe distinct triplets are [-1,0,1] and [-1,-1,2].\nNotice that the order of the output and the order of the triplets does not matter.\n\n\nExample 2:\n\n\nInput: nums = [0,1,1]\nOutput: []\nExplanation: The only possible triplet does not sum up to 0.\n\n\nExample 3:\n\n\nInput: nums = [0,0,0]\nOutput: [[0,0,0]]\nExplanation: The only possible triplet sums up to 0." + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "three_sum", + "signature": "(self, nums: List[int])-> List[List[int]]", + "body": " # TODO: Implement three_sum\n return []" + } + ] + }, + "helpers_run_name": "three_sum", + "helpers_run_signature": "(solution_class: type, nums: List[int])", + "helpers_run_body": " implementation = solution_class()\n return implementation.three_sum(nums)", + "helpers_assert_name": "three_sum", + "helpers_assert_signature": "(result: List[List[int]], expected: List[List[int]]) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "3sum", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_three_sum", + "signature": "(self, nums: List[int], expected: List[List[int]])", + "parametrize": "nums, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_three_sum(Solution, nums)\n assert_three_sum(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_three_sum, run_three_sum\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/_3sum_closest.json b/leetcode_py/cli/resources/leetcode/json/problems/_3sum_closest.json new file mode 100644 index 0000000..87f4a47 --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/_3sum_closest.json @@ -0,0 +1,50 @@ +{ + "problem_name": "_3sum_closest", + "problem_number": "16", + "problem_title": "3Sum Closest", + "difficulty": "Medium", + "topics": "Array, Two Pointers, Sorting", + "readme_description": "Given an integer array nums of length n and an integer target, find three integers in nums such that the sum is closest to target.\n\nReturn the sum of the three integers.\n\nYou may assume that each input would have exactly one solution.\n\n \nExample 1:\n\n\nInput: nums = [-1,2,1,-4], target = 1\nOutput: 2\nExplanation: The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).\n\n\nExample 2:\n\n\nInput: nums = [0,0,0], target = 1\nOutput: 0\nExplanation: The sum that is closest to the target is 0. (0 + 0 + 0 = 0).\n\n\n \nConstraints:\n\n\n\t3 <= nums.length <= 500\n\t-1000 <= nums[i] <= 1000\n\t-104 <= target <= 104", + "readme_constraints": "- 3 <= nums.length <= 500\n- -1000 <= nums[i] <= 1000\n- -104 <= target <= 104", + "_readme_examples": { + "list": [ + { + "content": "Input: nums = [-1,2,1,-4], target = 1\nOutput: 2\nExplanation: The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).\n\n\nExample 2:\n\n\nInput: nums = [0,0,0], target = 1\nOutput: 0\nExplanation: The sum that is closest to the target is 0. (0 + 0 + 0 = 0)." + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "three_sum_closest", + "signature": "(self, nums: List[int], target: int)-> int", + "body": " # TODO: Implement three_sum_closest\n return 0" + } + ] + }, + "helpers_run_name": "three_sum_closest", + "helpers_run_signature": "(solution_class: type, nums: List[int], target: int)", + "helpers_run_body": " implementation = solution_class()\n return implementation.three_sum_closest(nums, target)", + "helpers_assert_name": "three_sum_closest", + "helpers_assert_signature": "(result: int, expected: int) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "3sumClosest", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_three_sum_closest", + "signature": "(self, nums: List[int], target: int, expected: int)", + "parametrize": "nums, target, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_three_sum_closest(Solution, nums, target)\n assert_three_sum_closest(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_three_sum_closest, run_three_sum_closest\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/_4sum.json b/leetcode_py/cli/resources/leetcode/json/problems/_4sum.json new file mode 100644 index 0000000..6815cff --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/_4sum.json @@ -0,0 +1,50 @@ +{ + "problem_name": "_4sum", + "problem_number": "18", + "problem_title": "4Sum", + "difficulty": "Medium", + "topics": "Array, Two Pointers, Sorting", + "readme_description": "Given an array nums of n integers, return an array of all the unique quadruplets [nums[a], nums[b], nums[c], nums[d]] such that:\n\n\n\t0 <= a, b, c, d < n\n\ta, b, c, and d are distinct.\n\tnums[a] + nums[b] + nums[c] + nums[d] == target\n\n\nYou may return the answer in any order.\n\n \nExample 1:\n\n\nInput: nums = [1,0,-1,0,-2,2], target = 0\nOutput: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]\n\n\nExample 2:\n\n\nInput: nums = [2,2,2,2,2], target = 8\nOutput: [[2,2,2,2]]\n\n\n \nConstraints:\n\n\n\t1 <= nums.length <= 200\n\t-109 <= nums[i] <= 109\n\t-109 <= target <= 109", + "readme_constraints": "- 1 <= nums.length <= 200\n- -109 <= nums[i] <= 109\n- -109 <= target <= 109", + "_readme_examples": { + "list": [ + { + "content": "Input: nums = [1,0,-1,0,-2,2], target = 0\nOutput: [[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]\n\n\nExample 2:\n\n\nInput: nums = [2,2,2,2,2], target = 8\nOutput: [[2,2,2,2]]" + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "four_sum", + "signature": "(self, nums: List[int], target: int)-> List[List[int]]", + "body": " # TODO: Implement four_sum\n return []" + } + ] + }, + "helpers_run_name": "four_sum", + "helpers_run_signature": "(solution_class: type, nums: List[int], target: int)", + "helpers_run_body": " implementation = solution_class()\n return implementation.four_sum(nums, target)", + "helpers_assert_name": "four_sum", + "helpers_assert_signature": "(result: List[List[int]], expected: List[List[int]]) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "4sum", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_four_sum", + "signature": "(self, nums: List[int], target: int, expected: List[List[int]])", + "parametrize": "nums, target, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_four_sum(Solution, nums, target)\n assert_four_sum(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_four_sum, run_four_sum\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/accounts_merge.json b/leetcode_py/cli/resources/leetcode/json/problems/accounts_merge.json index e15421a..d7ae2f6 100644 --- a/leetcode_py/cli/resources/leetcode/json/problems/accounts_merge.json +++ b/leetcode_py/cli/resources/leetcode/json/problems/accounts_merge.json @@ -1,87 +1,52 @@ { - "problem_name": "accounts_merge", - "solution_class_name": "Solution", - "problem_number": "721", - "problem_title": "Accounts Merge", - "difficulty": "Medium", - "topics": "Array, Hash Table, String, Depth-First Search, Breadth-First Search, Union Find, Sorting", - "_tags": { - "list": ["grind-75"] - }, - "readme_description": "Given a list of `accounts` where each element `accounts[i]` is a list of strings, where the first element `accounts[i][0]` is a name, and the rest of the elements are emails representing emails of the account.\n\nNow, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some common email to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name.\n\nAfter merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails in sorted order. The accounts themselves can be returned in any order.", - "_readme_examples": { - "list": [ - { - "content": "```\nInput: accounts = [[\"John\",\"johnsmith@mail.com\",\"john_newyork@mail.com\"],[\"John\",\"johnsmith@mail.com\",\"john00@mail.com\"],[\"Mary\",\"mary@mail.com\"],[\"John\",\"johnnybravo@mail.com\"]]\nOutput: [[\"John\",\"john00@mail.com\",\"john_newyork@mail.com\",\"johnsmith@mail.com\"],[\"Mary\",\"mary@mail.com\"],[\"John\",\"johnnybravo@mail.com\"]]\n```\n**Explanation:** The first and second John's are the same person as they have the common email \"johnsmith@mail.com\". The third John and Mary are different people as none of their email addresses are used by other accounts." - }, - { - "content": "```\nInput: accounts = [[\"Gabe\",\"Gabe0@m.co\",\"Gabe3@m.co\",\"Gabe1@m.co\"],[\"Kevin\",\"Kevin3@m.co\",\"Kevin5@m.co\",\"Kevin0@m.co\"],[\"Ethan\",\"Ethan5@m.co\",\"Ethan4@m.co\",\"Ethan0@m.co\"],[\"Hanzo\",\"Hanzo3@m.co\",\"Hanzo1@m.co\",\"Hanzo0@m.co\"],[\"Fern\",\"Fern5@m.co\",\"Fern1@m.co\",\"Fern0@m.co\"]]\nOutput: [[\"Ethan\",\"Ethan0@m.co\",\"Ethan4@m.co\",\"Ethan5@m.co\"],[\"Gabe\",\"Gabe0@m.co\",\"Gabe1@m.co\",\"Gabe3@m.co\"],[\"Hanzo\",\"Hanzo0@m.co\",\"Hanzo1@m.co\",\"Hanzo3@m.co\"],[\"Kevin\",\"Kevin0@m.co\",\"Kevin3@m.co\",\"Kevin5@m.co\"],[\"Fern\",\"Fern0@m.co\",\"Fern1@m.co\",\"Fern5@m.co\"]]\n```" - } - ] - }, - "readme_constraints": "- 1 <= accounts.length <= 1000\n- 2 <= accounts[i].length <= 10\n- 1 <= accounts[i][j].length <= 30\n- accounts[i][0] consists of English letters.\n- accounts[i][j] (for j > 0) is a valid email.", - "readme_additional": "", - "helpers_imports": "", - "helpers_content": "", - "helpers_run_name": "accounts_merge", - "helpers_run_signature": "(solution_class: type, accounts: list[list[str]])", - "helpers_run_body": " implementation = solution_class()\n return implementation.accounts_merge(accounts)", - "helpers_assert_name": "accounts_merge", - "helpers_assert_signature": "(result: list[list[str]], expected: list[list[str]]) -> bool", - "helpers_assert_body": " # Sort both result and expected for comparison since order doesn't matter\n result_sorted = [sorted(account) for account in sorted(result)]\n expected_sorted = [sorted(account) for account in sorted(expected)]\n assert result_sorted == expected_sorted\n return True", - "solution_imports": "", - "solution_contents": "", - "solution_class_content": "", - "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_accounts_merge, run_accounts_merge\nfrom .solution import Solution", - "test_content": "", - "test_class_name": "AccountsMerge", - "test_class_content": " def setup_method(self):\n self.solution = Solution()", - "_solution_methods": { - "list": [ - { - "name": "accounts_merge", - "signature": "(self, accounts: list[list[str]]) -> list[list[str]]", - "body": " # TODO: Implement accounts_merge\n return []" - } - ] - }, - "_test_helper_methods": { - "list": [ - { - "name": "setup_method", - "parameters": "", - "body": "self.solution = Solution()" - } - ] - }, - "_test_methods": { - "list": [ - { - "name": "test_accounts_merge", - "signature": "(self, accounts: list[list[str]], expected: list[list[str]])", - "parametrize": "accounts, expected", - "test_cases": { - "list": [ - "([['John', 'johnsmith@mail.com', 'john_newyork@mail.com'], ['John', 'johnsmith@mail.com', 'john00@mail.com'], ['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com']], [['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com']])", - "([['Gabe', 'Gabe0@m.co', 'Gabe3@m.co', 'Gabe1@m.co'], ['Kevin', 'Kevin3@m.co', 'Kevin5@m.co', 'Kevin0@m.co'], ['Ethan', 'Ethan5@m.co', 'Ethan4@m.co', 'Ethan0@m.co'], ['Hanzo', 'Hanzo3@m.co', 'Hanzo1@m.co', 'Hanzo0@m.co'], ['Fern', 'Fern5@m.co', 'Fern1@m.co', 'Fern0@m.co']], [['Ethan', 'Ethan0@m.co', 'Ethan4@m.co', 'Ethan5@m.co'], ['Gabe', 'Gabe0@m.co', 'Gabe1@m.co', 'Gabe3@m.co'], ['Hanzo', 'Hanzo0@m.co', 'Hanzo1@m.co', 'Hanzo3@m.co'], ['Kevin', 'Kevin0@m.co', 'Kevin3@m.co', 'Kevin5@m.co'], ['Fern', 'Fern0@m.co', 'Fern1@m.co', 'Fern5@m.co']])", - "([['Alice', 'alice@mail.com']], [['Alice', 'alice@mail.com']])", - "([['Bob', 'bob1@mail.com'], ['Bob', 'bob2@mail.com']], [['Bob', 'bob1@mail.com'], ['Bob', 'bob2@mail.com']])", - "([['Alice', 'alice@mail.com', 'alice2@mail.com'], ['Alice', 'alice2@mail.com', 'alice3@mail.com']], [['Alice', 'alice2@mail.com', 'alice3@mail.com', 'alice@mail.com']])", - "([['A', 'a@mail.com', 'b@mail.com'], ['B', 'b@mail.com', 'c@mail.com'], ['C', 'c@mail.com', 'd@mail.com']], [['A', 'a@mail.com', 'b@mail.com', 'c@mail.com', 'd@mail.com']])", - "([['David', 'david@mail.com'], ['David', 'david@mail.com']], [['David', 'david@mail.com']])", - "([['Alex', 'alex1@mail.com'], ['Bob', 'bob1@mail.com'], ['Charlie', 'charlie1@mail.com']], [['Alex', 'alex1@mail.com'], ['Bob', 'bob1@mail.com'], ['Charlie', 'charlie1@mail.com']])", - "([['John', 'john1@mail.com', 'john2@mail.com'], ['John', 'john3@mail.com'], ['Jane', 'jane1@mail.com']], [['John', 'john1@mail.com', 'john2@mail.com'], ['John', 'john3@mail.com'], ['Jane', 'jane1@mail.com']])", - "([['User', 'user@mail.com', 'user1@mail.com'], ['User', 'user2@mail.com', 'user@mail.com'], ['User', 'user3@mail.com', 'user1@mail.com']], [['User', 'user1@mail.com', 'user2@mail.com', 'user3@mail.com', 'user@mail.com']])", - "([['Test', 'test1@mail.com'], ['Test', 'test2@mail.com'], ['Test', 'test1@mail.com', 'test3@mail.com']], [['Test', 'test2@mail.com'], ['Test', 'test1@mail.com', 'test3@mail.com']])", - "([['Name', 'a@mail.com', 'b@mail.com', 'c@mail.com'], ['Name', 'd@mail.com', 'e@mail.com'], ['Name', 'c@mail.com', 'f@mail.com']], [['Name', 'd@mail.com', 'e@mail.com'], ['Name', 'a@mail.com', 'b@mail.com', 'c@mail.com', 'f@mail.com']])" - ] - }, - "body": " result = run_accounts_merge(Solution, accounts)\n assert_accounts_merge(result, expected)" - } - ] - }, - "playground_imports": "from helpers import run_accounts_merge, assert_accounts_merge\nfrom solution import Solution", - "playground_setup": "# Example test case\naccounts = [['John', 'johnsmith@mail.com', 'john_newyork@mail.com'], ['John', 'johnsmith@mail.com', 'john00@mail.com'], ['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com']]\nexpected = [['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'], ['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com']]", - "playground_run": "result = run_accounts_merge(Solution, accounts)\nresult", - "playground_assert": "assert_accounts_merge(result, expected)" -} + "problem_name": "accounts_merge", + "problem_number": "721", + "problem_title": "Accounts Merge", + "difficulty": "Medium", + "topics": "Array, Hash Table, String, Depth-First Search, Breadth-First Search, Union Find, Sorting", + "readme_description": "Given a list of accounts where each element accounts[i] is a list of strings, where the first element accounts[i][0] is a name, and the rest of the elements are emails representing emails of the account.\n\nNow, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some common email to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name.\n\nAfter merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails in sorted order. The accounts themselves can be returned in any order.\n\n \nExample 1:\n\n\nInput: accounts = [["John","johnsmith@mail.com","john_newyork@mail.com"],["John","johnsmith@mail.com","john00@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]]\nOutput: [["John","john00@mail.com","john_newyork@mail.com","johnsmith@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]]\nExplanation:\nThe first and second John's are the same person as they have the common email "johnsmith@mail.com".\nThe third John and Mary are different people as none of their email addresses are used by other accounts.\nWe could return these lists in any order, for example the answer [['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'], \n['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] would still be accepted.\n\n\nExample 2:\n\n\nInput: accounts = [["Gabe","Gabe0@m.co","Gabe3@m.co","Gabe1@m.co"],["Kevin","Kevin3@m.co","Kevin5@m.co","Kevin0@m.co"],["Ethan","Ethan5@m.co","Ethan4@m.co","Ethan0@m.co"],["Hanzo","Hanzo3@m.co","Hanzo1@m.co","Hanzo0@m.co"],["Fern","Fern5@m.co","Fern1@m.co","Fern0@m.co"]]\nOutput: [["Ethan","Ethan0@m.co","Ethan4@m.co","Ethan5@m.co"],["Gabe","Gabe0@m.co","Gabe1@m.co","Gabe3@m.co"],["Hanzo","Hanzo0@m.co","Hanzo1@m.co","Hanzo3@m.co"],["Kevin","Kevin0@m.co","Kevin3@m.co","Kevin5@m.co"],["Fern","Fern0@m.co","Fern1@m.co","Fern5@m.co"]]\n\n\n \nConstraints:\n\n\n\t1 <= accounts.length <= 1000\n\t2 <= accounts[i].length <= 10\n\t1 <= accounts[i][j].length <= 30\n\taccounts[i][0] consists of English letters.\n\taccounts[i][j] (for j > 0) is a valid email.", + "readme_constraints": "- 1 <= accounts.length <= 1000\n- 2 <= accounts[i].length <= 10\n- 1 <= accounts[i][j].length <= 30\n- accounts[i][0] consists of English letters.\n- accounts[i][j] (for j > 0) is a valid email.", + "_readme_examples": { + "list": [ + { + "content": "Input: accounts = [["John","johnsmith@mail.com","john_newyork@mail.com"],["John","johnsmith@mail.com","john00@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]]\nOutput: [["John","john00@mail.com","john_newyork@mail.com","johnsmith@mail.com"],["Mary","mary@mail.com"],["John","johnnybravo@mail.com"]]\nExplanation:\nThe first and second John's are the same person as they have the common email "johnsmith@mail.com".\nThe third John and Mary are different people as none of their email addresses are used by other accounts.\nWe could return these lists in any order, for example the answer [['Mary', 'mary@mail.com'], ['John', 'johnnybravo@mail.com'], \n['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com']] would still be accepted.\n\n\nExample 2:\n\n\nInput: accounts = [["Gabe","Gabe0@m.co","Gabe3@m.co","Gabe1@m.co"],["Kevin","Kevin3@m.co","Kevin5@m.co","Kevin0@m.co"],["Ethan","Ethan5@m.co","Ethan4@m.co","Ethan0@m.co"],["Hanzo","Hanzo3@m.co","Hanzo1@m.co","Hanzo0@m.co"],["Fern","Fern5@m.co","Fern1@m.co","Fern0@m.co"]]\nOutput: [["Ethan","Ethan0@m.co","Ethan4@m.co","Ethan5@m.co"],["Gabe","Gabe0@m.co","Gabe1@m.co","Gabe3@m.co"],["Hanzo","Hanzo0@m.co","Hanzo1@m.co","Hanzo3@m.co"],["Kevin","Kevin0@m.co","Kevin3@m.co","Kevin5@m.co"],["Fern","Fern0@m.co","Fern1@m.co","Fern5@m.co"]]" + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "accounts_merge", + "signature": "(self, accounts: List[List[str]])-> List[List[str]]", + "body": " # TODO: Implement accounts_merge\n return []" + } + ] + }, + "helpers_run_name": "accounts_merge", + "helpers_run_signature": "(solution_class: type, accounts: List[List[str]])", + "helpers_run_body": " implementation = solution_class()\n return implementation.accounts_merge(accounts)", + "helpers_assert_name": "accounts_merge", + "helpers_assert_signature": "(result: List[List[str]], expected: List[List[str]]) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "AccountsMerge", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_accounts_merge", + "signature": "(self, accounts: List[List[str]], expected: List[List[str]])", + "parametrize": "accounts, expected", + "test_cases": { + "list": [ + "([[\"John\",\"johnsmith@mail.com\",\"john_newyork@mail.com\"],[\"John\",\"johnsmith@mail.com\",\"john00@mail.com\"],[\"Mary\",\"mary@mail.com\"],[\"John\",\"johnnybravo@mail.com\"]], [[\"Gabe\",\"Gabe0@m.co\",\"Gabe3@m.co\",\"Gabe1@m.co\"],[\"Kevin\",\"Kevin3@m.co\",\"Kevin5@m.co\",\"Kevin0@m.co\"],[\"Ethan\",\"Ethan5@m.co\",\"Ethan4@m.co\",\"Ethan0@m.co\"],[\"Hanzo\",\"Hanzo3@m.co\",\"Hanzo1@m.co\",\"Hanzo0@m.co\"],[\"Fern\",\"Fern5@m.co\",\"Fern1@m.co\",\"Fern0@m.co\"]])" + ] + }, + "body": " result = run_accounts_merge(Solution, accounts)\n assert_accounts_merge(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_accounts_merge, run_accounts_merge\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/add_binary.json b/leetcode_py/cli/resources/leetcode/json/problems/add_binary.json index f0b21c3..090be49 100644 --- a/leetcode_py/cli/resources/leetcode/json/problems/add_binary.json +++ b/leetcode_py/cli/resources/leetcode/json/problems/add_binary.json @@ -1,86 +1,50 @@ { - "problem_name": "add_binary", - "solution_class_name": "Solution", - "problem_number": "67", - "problem_title": "Add Binary", - "difficulty": "Easy", - "topics": "Math, String, Bit Manipulation, Simulation", - "_tags": { - "list": ["grind-75"] - }, - "readme_description": "Given two binary strings `a` and `b`, return *their sum as a binary string*.", - "_readme_examples": { - "list": [ - { - "content": "```\nInput: a = \"11\", b = \"1\"\nOutput: \"100\"\n```" - }, - { - "content": "```\nInput: a = \"1010\", b = \"1011\"\nOutput: \"10101\"\n```" - } - ] - }, - "readme_constraints": "- `1 <= a.length, b.length <= 10^4`\n- `a` and `b` consist only of `'0'` or `'1'` characters.\n- Each string does not contain leading zeros except for the zero itself.", - "readme_additional": "", - "helpers_imports": "", - "helpers_content": "", - "helpers_run_name": "add_binary", - "helpers_run_signature": "(solution_class: type, a: str, b: str)", - "helpers_run_body": " implementation = solution_class()\n return implementation.add_binary(a, b)", - "helpers_assert_name": "add_binary", - "helpers_assert_signature": "(result: str, expected: str) -> bool", - "helpers_assert_body": " assert result == expected\n return True", - "solution_imports": "", - "solution_contents": "", - "solution_class_content": "", - "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_add_binary, run_add_binary\nfrom .solution import Solution", - "test_content": "", - "test_class_name": "AddBinary", - "test_class_content": " def setup_method(self):\n self.solution = Solution()", - "_solution_methods": { - "list": [ - { - "name": "add_binary", - "signature": "(self, a: str, b: str) -> str", - "body": " # TODO: Implement add_binary\n return \"\"" - } - ] - }, - "_test_helper_methods": { - "list": [ - { - "name": "setup_method", - "parameters": "", - "body": "self.solution = Solution()" - } - ] - }, - "_test_methods": { - "list": [ - { - "name": "test_add_binary", - "signature": "(self, a: str, b: str, expected: str)", - "parametrize": "a, b, expected", - "test_cases": { - "list": [ - "('11', '1', '100')", - "('1010', '1011', '10101')", - "('0', '0', '0')", - "('1', '1', '10')", - "('1111', '1111', '11110')", - "('1', '0', '1')", - "('0', '1', '1')", - "('1', '111', '1000')", - "('111', '1', '1000')", - "('1010', '1', '1011')", - "('1111', '1', '10000')" - ] - }, - "body": " result = run_add_binary(Solution, a, b)\n assert_add_binary(result, expected)" - } - ] - }, - "playground_imports": "from helpers import run_add_binary, assert_add_binary\nfrom solution import Solution", - "playground_setup": "# Example test case\na = '11'\nb = '1'\nexpected = '100'", - "playground_run": "result = run_add_binary(Solution, a, b)\nresult", - "playground_assert": "assert_add_binary(result, expected)" -} + "problem_name": "add_binary", + "problem_number": "67", + "problem_title": "Add Binary", + "difficulty": "Easy", + "topics": "Math, String, Bit Manipulation, Simulation", + "readme_description": "Given two binary strings a and b, return their sum as a binary string.\n\n \nExample 1:\nInput: a = \"11\", b = \"1\"\nOutput: \"100\"\nExample 2:\nInput: a = \"1010\", b = \"1011\"\nOutput: \"10101\"\n\n \nConstraints:\n\n\n\t1 <= a.length, b.length <= 104\n\ta and b consist only of '0' or '1' characters.\n\tEach string does not contain leading zeros except for the zero itself.", + "readme_constraints": "- 1 <= a.length, b.length <= 104\n- a and b consist only of '0' or '1' characters.\n- Each string does not contain leading zeros except for the zero itself.", + "_readme_examples": { + "list": [ + { + "content": "Input: a = \"11\", b = \"1\"\nOutput: \"100\"\nExample 2:\nInput: a = \"1010\", b = \"1011\"\nOutput: \"10101\"" + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "add_binary", + "signature": "(self, a: str, b: str)-> str", + "body": " # TODO: Implement add_binary\n return \"\"" + } + ] + }, + "helpers_run_name": "add_binary", + "helpers_run_signature": "(solution_class: type, a: str, b: str)", + "helpers_run_body": " implementation = solution_class()\n return implementation.add_binary(a, b)", + "helpers_assert_name": "add_binary", + "helpers_assert_signature": "(result: str, expected: str) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "AddBinary", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_add_binary", + "signature": "(self, a: str, b: str, expected: str)", + "parametrize": "a, b, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_add_binary(Solution, a, b)\n assert_add_binary(result, expected)" + } + ] + }, + "solution_imports": "", + "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_add_binary, run_add_binary\nfrom .solution import Solution", + "helpers_imports": "" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/add_strings.json b/leetcode_py/cli/resources/leetcode/json/problems/add_strings.json new file mode 100644 index 0000000..3269f0d --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/add_strings.json @@ -0,0 +1,50 @@ +{ + "problem_name": "add_strings", + "problem_number": "415", + "problem_title": "Add Strings", + "difficulty": "Easy", + "topics": "Math, String, Simulation", + "readme_description": "Given two non-negative integers, num1 and num2 represented as string, return the sum of num1 and num2 as a string.\n\nYou must solve the problem without using any built-in library for handling large integers (such as BigInteger). You must also not convert the inputs to integers directly.\n\n \nExample 1:\n\n\nInput: num1 = "11", num2 = "123"\nOutput: "134"\n\n\nExample 2:\n\n\nInput: num1 = "456", num2 = "77"\nOutput: "533"\n\n\nExample 3:\n\n\nInput: num1 = "0", num2 = "0"\nOutput: "0"\n\n\n \nConstraints:\n\n\n\t1 <= num1.length, num2.length <= 104\n\tnum1 and num2 consist of only digits.\n\tnum1 and num2 don't have any leading zeros except for the zero itself.", + "readme_constraints": "- 1 <= num1.length, num2.length <= 104\n- num1 and num2 consist of only digits.\n- num1 and num2 don't have any leading zeros except for the zero itself.", + "_readme_examples": { + "list": [ + { + "content": "Input: num1 = "11", num2 = "123"\nOutput: "134"\n\n\nExample 2:\n\n\nInput: num1 = "456", num2 = "77"\nOutput: "533"\n\n\nExample 3:\n\n\nInput: num1 = "0", num2 = "0"\nOutput: "0"" + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "add_strings", + "signature": "(self, num1: str, num2: str)-> str", + "body": " # TODO: Implement add_strings\n return \"\"" + } + ] + }, + "helpers_run_name": "add_strings", + "helpers_run_signature": "(solution_class: type, num1: str, num2: str)", + "helpers_run_body": " implementation = solution_class()\n return implementation.add_strings(num1, num2)", + "helpers_assert_name": "add_strings", + "helpers_assert_signature": "(result: str, expected: str) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "AddStrings", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_add_strings", + "signature": "(self, num1: str, num2: str, expected: str)", + "parametrize": "num1, num2, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_add_strings(Solution, num1, num2)\n assert_add_strings(result, expected)" + } + ] + }, + "solution_imports": "", + "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_add_strings, run_add_strings\nfrom .solution import Solution", + "helpers_imports": "" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/add_to_array_form_of_integer.json b/leetcode_py/cli/resources/leetcode/json/problems/add_to_array_form_of_integer.json new file mode 100644 index 0000000..1e140c1 --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/add_to_array_form_of_integer.json @@ -0,0 +1,50 @@ +{ + "problem_name": "add_to_array_form_of_integer", + "problem_number": "989", + "problem_title": "Add to Array-Form of Integer", + "difficulty": "Easy", + "topics": "Array, Math", + "readme_description": "The array-form of an integer num is an array representing its digits in left to right order.\n\n\n\tFor example, for num = 1321, the array form is [1,3,2,1].\n\n\nGiven num, the array-form of an integer, and an integer k, return the array-form of the integer num + k.\n\n \nExample 1:\n\n\nInput: num = [1,2,0,0], k = 34\nOutput: [1,2,3,4]\nExplanation: 1200 + 34 = 1234\n\n\nExample 2:\n\n\nInput: num = [2,7,4], k = 181\nOutput: [4,5,5]\nExplanation: 274 + 181 = 455\n\n\nExample 3:\n\n\nInput: num = [2,1,5], k = 806\nOutput: [1,0,2,1]\nExplanation: 215 + 806 = 1021\n\n\n \nConstraints:\n\n\n\t1 <= num.length <= 104\n\t0 <= num[i] <= 9\n\tnum does not contain any leading zeros except for the zero itself.\n\t1 <= k <= 104", + "readme_constraints": "- 1 <= num.length <= 104\n- 0 <= num[i] <= 9\n- num does not contain any leading zeros except for the zero itself.\n- 1 <= k <= 104", + "_readme_examples": { + "list": [ + { + "content": "Input: num = [1,2,0,0], k = 34\nOutput: [1,2,3,4]\nExplanation: 1200 + 34 = 1234\n\n\nExample 2:\n\n\nInput: num = [2,7,4], k = 181\nOutput: [4,5,5]\nExplanation: 274 + 181 = 455\n\n\nExample 3:\n\n\nInput: num = [2,1,5], k = 806\nOutput: [1,0,2,1]\nExplanation: 215 + 806 = 1021" + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "add_to_array_form", + "signature": "(self, num: List[int], k: int)-> List[int]", + "body": " # TODO: Implement add_to_array_form\n return []" + } + ] + }, + "helpers_run_name": "add_to_array_form", + "helpers_run_signature": "(solution_class: type, num: List[int], k: int)", + "helpers_run_body": " implementation = solution_class()\n return implementation.add_to_array_form(num, k)", + "helpers_assert_name": "add_to_array_form", + "helpers_assert_signature": "(result: List[int], expected: List[int]) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "AddToArrayFormOfInteger", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_add_to_array_form", + "signature": "(self, num: List[int], k: int, expected: List[int])", + "parametrize": "num, k, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_add_to_array_form(Solution, num, k)\n assert_add_to_array_form(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_add_to_array_form, run_add_to_array_form\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/assign_cookies.json b/leetcode_py/cli/resources/leetcode/json/problems/assign_cookies.json new file mode 100644 index 0000000..d1e894b --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/assign_cookies.json @@ -0,0 +1,50 @@ +{ + "problem_name": "assign_cookies", + "problem_number": "455", + "problem_title": "Assign Cookies", + "difficulty": "Easy", + "topics": "Array, Two Pointers, Greedy, Sorting", + "readme_description": "Assume you are an awesome parent and want to give your children some cookies. But, you should give each child at most one cookie.\n\nEach child i has a greed factor g[i], which is the minimum size of a cookie that the child will be content with; and each cookie j has a size s[j]. If s[j] >= g[i], we can assign the cookie j to the child i, and the child i will be content. Your goal is to maximize the number of your content children and output the maximum number.\n\n \nExample 1:\n\n\nInput: g = [1,2,3], s = [1,1]\nOutput: 1\nExplanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3. \nAnd even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content.\nYou need to output 1.\n\n\nExample 2:\n\n\nInput: g = [1,2], s = [1,2,3]\nOutput: 2\nExplanation: You have 2 children and 3 cookies. The greed factors of 2 children are 1, 2. \nYou have 3 cookies and their sizes are big enough to gratify all of the children, \nYou need to output 2.\n\n\n \nConstraints:\n\n\n\t1 <= g.length <= 3 * 104\n\t0 <= s.length <= 3 * 104\n\t1 <= g[i], s[j] <= 231 - 1\n\n\n \nNote: This question is the same as 2410: Maximum Matching of Players With Trainers.", + "readme_constraints": "- 1 <= g.length <= 3 * 104\n- 0 <= s.length <= 3 * 104\n- 1 <= g[i], s[j] <= 231 - 1", + "_readme_examples": { + "list": [ + { + "content": "Input: g = [1,2,3], s = [1,1]\nOutput: 1\nExplanation: You have 3 children and 2 cookies. The greed factors of 3 children are 1, 2, 3. \nAnd even though you have 2 cookies, since their size is both 1, you could only make the child whose greed factor is 1 content.\nYou need to output 1.\n\n\nExample 2:\n\n\nInput: g = [1,2], s = [1,2,3]\nOutput: 2\nExplanation: You have 2 children and 3 cookies. The greed factors of 2 children are 1, 2. \nYou have 3 cookies and their sizes are big enough to gratify all of the children, \nYou need to output 2." + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "find_content_children", + "signature": "(self, g: List[int], s: List[int])-> int", + "body": " # TODO: Implement find_content_children\n return 0" + } + ] + }, + "helpers_run_name": "find_content_children", + "helpers_run_signature": "(solution_class: type, g: List[int], s: List[int])", + "helpers_run_body": " implementation = solution_class()\n return implementation.find_content_children(g, s)", + "helpers_assert_name": "find_content_children", + "helpers_assert_signature": "(result: int, expected: int) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "AssignCookies", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_find_content_children", + "signature": "(self, g: List[int], s: List[int], expected: int)", + "parametrize": "g, s, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_find_content_children(Solution, g, s)\n assert_find_content_children(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_find_content_children, run_find_content_children\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/asteroid_collision.json b/leetcode_py/cli/resources/leetcode/json/problems/asteroid_collision.json new file mode 100644 index 0000000..dea45e8 --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/asteroid_collision.json @@ -0,0 +1,50 @@ +{ + "problem_name": "asteroid_collision", + "problem_number": "735", + "problem_title": "Asteroid Collision", + "difficulty": "Medium", + "topics": "Array, Stack, Simulation", + "readme_description": "We are given an array asteroids of integers representing asteroids in a row. The indices of the asteroid in the array represent their relative position in space.\n\nFor each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed.\n\nFind out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet.\n\n \nExample 1:\n\n\nInput: asteroids = [5,10,-5]\nOutput: [5,10]\nExplanation: The 10 and -5 collide resulting in 10. The 5 and 10 never collide.\n\n\nExample 2:\n\n\nInput: asteroids = [8,-8]\nOutput: []\nExplanation: The 8 and -8 collide exploding each other.\n\n\nExample 3:\n\n\nInput: asteroids = [10,2,-5]\nOutput: [10]\nExplanation: The 2 and -5 collide resulting in -5. The 10 and -5 collide resulting in 10.\n\n\nExample 4:\n\n\nInput: asteroids = [3,5,-6,2,-1,4]\u200b\u200b\u200b\u200b\u200b\u200b\u200b\nOutput: [-6,2,4]\nExplanation: The asteroid -6 makes the asteroid 3 and 5 explode, and then continues going left. On the other side, the asteroid 2 makes the asteroid -1 explode and then continues going right, without reaching asteroid 4.\n\n\n \nConstraints:\n\n\n\t2 <= asteroids.length <= 104\n\t-1000 <= asteroids[i] <= 1000\n\tasteroids[i] != 0", + "readme_constraints": "- 2 <= asteroids.length <= 104\n- -1000 <= asteroids[i] <= 1000\n- asteroids[i] != 0", + "_readme_examples": { + "list": [ + { + "content": "Input: asteroids = [5,10,-5]\nOutput: [5,10]\nExplanation: The 10 and -5 collide resulting in 10. The 5 and 10 never collide.\n\n\nExample 2:\n\n\nInput: asteroids = [8,-8]\nOutput: []\nExplanation: The 8 and -8 collide exploding each other.\n\n\nExample 3:\n\n\nInput: asteroids = [10,2,-5]\nOutput: [10]\nExplanation: The 2 and -5 collide resulting in -5. The 10 and -5 collide resulting in 10.\n\n\nExample 4:\n\n\nInput: asteroids = [3,5,-6,2,-1,4]\u200b\u200b\u200b\u200b\u200b\u200b\u200b\nOutput: [-6,2,4]\nExplanation: The asteroid -6 makes the asteroid 3 and 5 explode, and then continues going left. On the other side, the asteroid 2 makes the asteroid -1 explode and then continues going right, without reaching asteroid 4." + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "asteroid_collision", + "signature": "(self, asteroids: List[int])-> List[int]", + "body": " # TODO: Implement asteroid_collision\n return []" + } + ] + }, + "helpers_run_name": "asteroid_collision", + "helpers_run_signature": "(solution_class: type, asteroids: List[int])", + "helpers_run_body": " implementation = solution_class()\n return implementation.asteroid_collision(asteroids)", + "helpers_assert_name": "asteroid_collision", + "helpers_assert_signature": "(result: List[int], expected: List[int]) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "AsteroidCollision", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_asteroid_collision", + "signature": "(self, asteroids: List[int], expected: List[int])", + "parametrize": "asteroids, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_asteroid_collision(Solution, asteroids)\n assert_asteroid_collision(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_asteroid_collision, run_asteroid_collision\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/backspace_string_compare.json b/leetcode_py/cli/resources/leetcode/json/problems/backspace_string_compare.json new file mode 100644 index 0000000..4a2aff2 --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/backspace_string_compare.json @@ -0,0 +1,50 @@ +{ + "problem_name": "backspace_string_compare", + "problem_number": "844", + "problem_title": "Backspace String Compare", + "difficulty": "Easy", + "topics": "Two Pointers, String, Stack, Simulation", + "readme_description": "Given two strings s and t, return true if they are equal when both are typed into empty text editors. '#' means a backspace character.\n\nNote that after backspacing an empty text, the text will continue empty.\n\n \nExample 1:\n\n\nInput: s = "ab#c", t = "ad#c"\nOutput: true\nExplanation: Both s and t become "ac".\n\n\nExample 2:\n\n\nInput: s = "ab##", t = "c#d#"\nOutput: true\nExplanation: Both s and t become "".\n\n\nExample 3:\n\n\nInput: s = "a#c", t = "b"\nOutput: false\nExplanation: s becomes "c" while t becomes "b".\n\n\n \nConstraints:\n\n\n\t1 <= s.length, t.length <= 200\n\ts and t only contain lowercase letters and '#' characters.\n\n\n \nFollow up: Can you solve it in O(n) time and O(1) space?", + "readme_constraints": "- 1 <= s.length, t.length <= 200\n- s and t only contain lowercase letters and '#' characters.", + "_readme_examples": { + "list": [ + { + "content": "Input: s = "ab#c", t = "ad#c"\nOutput: true\nExplanation: Both s and t become "ac".\n\n\nExample 2:\n\n\nInput: s = "ab##", t = "c#d#"\nOutput: true\nExplanation: Both s and t become "".\n\n\nExample 3:\n\n\nInput: s = "a#c", t = "b"\nOutput: false\nExplanation: s becomes "c" while t becomes "b"." + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "backspace_compare", + "signature": "(self, s: str, t: str)-> bool", + "body": " # TODO: Implement backspace_compare\n return False" + } + ] + }, + "helpers_run_name": "backspace_compare", + "helpers_run_signature": "(solution_class: type, s: str, t: str)", + "helpers_run_body": " implementation = solution_class()\n return implementation.backspace_compare(s, t)", + "helpers_assert_name": "backspace_compare", + "helpers_assert_signature": "(result: bool, expected: bool) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "BackspaceStringCompare", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_backspace_compare", + "signature": "(self, s: str, t: str, expected: bool)", + "parametrize": "s, t, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_backspace_compare(Solution, s, t)\n assert_backspace_compare(result, expected)" + } + ] + }, + "solution_imports": "", + "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_backspace_compare, run_backspace_compare\nfrom .solution import Solution", + "helpers_imports": "" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/basic_calculator.json b/leetcode_py/cli/resources/leetcode/json/problems/basic_calculator.json index 3865926..a99f46b 100644 --- a/leetcode_py/cli/resources/leetcode/json/problems/basic_calculator.json +++ b/leetcode_py/cli/resources/leetcode/json/problems/basic_calculator.json @@ -1,102 +1,50 @@ { - "problem_name": "basic_calculator", - "solution_class_name": "Solution", - "problem_number": "224", - "problem_title": "Basic Calculator", - "difficulty": "Hard", - "topics": "Math, String, Stack, Recursion", - "_tags": { - "list": ["grind-75"] - }, - "readme_description": "Given a string `s` representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation.\n\n**Note:** You are **not** allowed to use any built-in function which evaluates strings as mathematical expressions, such as `eval()`.", - "_readme_examples": { - "list": [ - { - "content": "```\nInput: s = \"1 + 1\"\nOutput: 2\n```" - }, - { - "content": "```\nInput: s = \" 2-1 + 2 \"\nOutput: 3\n```" - }, - { - "content": "```\nInput: s = \"(1+(4+5+2)-3)+(6+8)\"\nOutput: 23\n```" - } - ] - }, - "readme_constraints": "- `1 <= s.length <= 3 * 10^5`\n- `s` consists of digits, `'+'`, `'-'`, `'('`, `')'`, and `' '`.\n- `s` represents a valid expression.\n- `'+'` is **not** used as a unary operation (i.e., `\"+1\"` and `\"+(2 + 3)\"` is invalid).\n- `'-'` could be used as a unary operation (i.e., `\"-1\"` and `\"-(2 + 3)\"` is valid).\n- There will be no two consecutive operators in the input.\n- Every number and running calculation will fit in a signed 32-bit integer.", - "readme_additional": "", - "helpers_imports": "", - "helpers_content": "", - "helpers_run_name": "calculate", - "helpers_run_signature": "(solution_class: type, s: str)", - "helpers_run_body": " implementation = solution_class()\n return implementation.calculate(s)", - "helpers_assert_name": "calculate", - "helpers_assert_signature": "(result: int, expected: int) -> bool", - "helpers_assert_body": " assert result == expected\n return True", - "solution_imports": "", - "solution_contents": "", - "solution_class_content": "", - "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_calculate, run_calculate\nfrom .solution import Solution", - "test_content": "", - "test_class_name": "BasicCalculator", - "test_class_content": " def setup_method(self):\n self.solution = Solution()", - "_solution_methods": { - "list": [ - { - "name": "calculate", - "signature": "(self, s: str) -> int", - "body": " # TODO: Implement calculate\n return 0" - } - ] - }, - "_test_helper_methods": { - "list": [ - { - "name": "setup_method", - "parameters": "", - "body": "self.solution = Solution()" - } - ] - }, - "_test_methods": { - "list": [ - { - "name": "test_calculate", - "signature": "(self, s: str, expected: int)", - "parametrize": "s, expected", - "test_cases": { - "list": [ - "('1 + 1', 2)", - "(' 2-1 + 2 ', 3)", - "('(1+(4+5+2)-3)+(6+8)', 23)", - "('1', 1)", - "('-1', -1)", - "('-(1+2)', -3)", - "('2147483647', 2147483647)", - "('1-1+1', 1)", - "('0', 0)", - "('-0', 0)", - "('1+(2+3)', 6)", - "('(1+2)+3', 6)", - "('1-(2+3)', -4)", - "('(1-2)+3', 2)", - "('-(-1)', 1)", - "('-(-(-1))', -1)", - "('1000000-999999', 1)", - "('10+20-30+40', 40)", - "('((1+2)+(3+4))', 10)", - "('1+(2-(3+4))', -4)", - "('-(1+(2+3))', -6)", - "(' 1 + 2 ', 3)", - "('123+456', 579)", - "('-2147483648', -2147483648)" - ] - }, - "body": " result = run_calculate(Solution, s)\n assert_calculate(result, expected)" - } - ] - }, - "playground_imports": "from helpers import run_calculate, assert_calculate\nfrom solution import Solution", - "playground_setup": "# Example test case\ns = '(1+(4+5+2)-3)+(6+8)'\nexpected = 23", - "playground_run": "result = run_calculate(Solution, s)\nresult", - "playground_assert": "assert_calculate(result, expected)" -} + "problem_name": "basic_calculator", + "problem_number": "224", + "problem_title": "Basic Calculator", + "difficulty": "Hard", + "topics": "Math, String, Stack, Recursion", + "readme_description": "Given a string s representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation.\n\nNote: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().\n\n \nExample 1:\n\n\nInput: s = "1 + 1"\nOutput: 2\n\n\nExample 2:\n\n\nInput: s = " 2-1 + 2 "\nOutput: 3\n\n\nExample 3:\n\n\nInput: s = "(1+(4+5+2)-3)+(6+8)"\nOutput: 23\n\n\n \nConstraints:\n\n\n\t1 <= s.length <= 3 * 105\n\ts consists of digits, '+', '-', '(', ')', and ' '.\n\ts represents a valid expression.\n\t'+' is not used as a unary operation (i.e., "+1" and "+(2 + 3)" is invalid).\n\t'-' could be used as a unary operation (i.e., "-1" and "-(2 + 3)" is valid).\n\tThere will be no two consecutive operators in the input.\n\tEvery number and running calculation will fit in a signed 32-bit integer.", + "readme_constraints": "- 1 <= s.length <= 3 * 105\n- s consists of digits, '+', '-', '(', ')', and ' '.\n- s represents a valid expression.\n- '+' is not used as a unary operation (i.e., "+1" and "+(2 + 3)" is invalid).\n- '-' could be used as a unary operation (i.e., "-1" and "-(2 + 3)" is valid).\n- There will be no two consecutive operators in the input.\n- Every number and running calculation will fit in a signed 32-bit integer.", + "_readme_examples": { + "list": [ + { + "content": "Input: s = "1 + 1"\nOutput: 2\n\n\nExample 2:\n\n\nInput: s = " 2-1 + 2 "\nOutput: 3\n\n\nExample 3:\n\n\nInput: s = "(1+(4+5+2)-3)+(6+8)"\nOutput: 23" + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "calculate", + "signature": "(self, s: str)-> int", + "body": " # TODO: Implement calculate\n return 0" + } + ] + }, + "helpers_run_name": "calculate", + "helpers_run_signature": "(solution_class: type, s: str)", + "helpers_run_body": " implementation = solution_class()\n return implementation.calculate(s)", + "helpers_assert_name": "calculate", + "helpers_assert_signature": "(result: int, expected: int) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "BasicCalculator", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_calculate", + "signature": "(self, s: str, expected: int)", + "parametrize": "s, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_calculate(Solution, s)\n assert_calculate(result, expected)" + } + ] + }, + "solution_imports": "", + "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_calculate, run_calculate\nfrom .solution import Solution", + "helpers_imports": "" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/basic_calculator_ii.json b/leetcode_py/cli/resources/leetcode/json/problems/basic_calculator_ii.json new file mode 100644 index 0000000..476a0d8 --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/basic_calculator_ii.json @@ -0,0 +1,50 @@ +{ + "problem_name": "basic_calculator_ii", + "problem_number": "227", + "problem_title": "Basic Calculator II", + "difficulty": "Medium", + "topics": "Math, String, Stack", + "readme_description": "Given a string s which represents an expression, evaluate this expression and return its value. \n\nThe integer division should truncate toward zero.\n\nYou may assume that the given expression is always valid. All intermediate results will be in the range of [-231, 231 - 1].\n\nNote: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().\n\n \nExample 1:\nInput: s = \"3+2*2\"\nOutput: 7\nExample 2:\nInput: s = \" 3/2 \"\nOutput: 1\nExample 3:\nInput: s = \" 3+5 / 2 \"\nOutput: 5\n\n \nConstraints:\n\n\n\t1 <= s.length <= 3 * 105\n\ts consists of integers and operators ('+', '-', '*', '/') separated by some number of spaces.\n\ts represents a valid expression.\n\tAll the integers in the expression are non-negative integers in the range [0, 231 - 1].\n\tThe answer is guaranteed to fit in a 32-bit integer.", + "readme_constraints": "- 1 <= s.length <= 3 * 105\n- s consists of integers and operators ('+', '-', '*', '/') separated by some number of spaces.\n- s represents a valid expression.\n- All the integers in the expression are non-negative integers in the range [0, 231 - 1].\n- The answer is guaranteed to fit in a 32-bit integer.", + "_readme_examples": { + "list": [ + { + "content": "Input: s = \"3+2*2\"\nOutput: 7\nExample 2:\nInput: s = \" 3/2 \"\nOutput: 1\nExample 3:\nInput: s = \" 3+5 / 2 \"\nOutput: 5" + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "calculate", + "signature": "(self, s: str)-> int", + "body": " # TODO: Implement calculate\n return 0" + } + ] + }, + "helpers_run_name": "calculate", + "helpers_run_signature": "(solution_class: type, s: str)", + "helpers_run_body": " implementation = solution_class()\n return implementation.calculate(s)", + "helpers_assert_name": "calculate", + "helpers_assert_signature": "(result: int, expected: int) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "BasicCalculatorIi", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_calculate", + "signature": "(self, s: str, expected: int)", + "parametrize": "s, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_calculate(Solution, s)\n assert_calculate(result, expected)" + } + ] + }, + "solution_imports": "", + "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_calculate, run_calculate\nfrom .solution import Solution", + "helpers_imports": "" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/best_time_to_buy_and_sell_stock.json b/leetcode_py/cli/resources/leetcode/json/problems/best_time_to_buy_and_sell_stock.json index 31a1cb4..b0bba19 100644 --- a/leetcode_py/cli/resources/leetcode/json/problems/best_time_to_buy_and_sell_stock.json +++ b/leetcode_py/cli/resources/leetcode/json/problems/best_time_to_buy_and_sell_stock.json @@ -1,90 +1,52 @@ { - "problem_name": "best_time_to_buy_and_sell_stock", - "solution_class_name": "Solution", - "problem_number": "121", - "problem_title": "Best Time to Buy and Sell Stock", - "difficulty": "Easy", - "topics": "Array, Dynamic Programming", - "_tags": { - "list": ["grind-75"] - }, - "readme_description": "You are given an array `prices` where `prices[i]` is the price of a given stock on the ith day.\n\nYou want to maximize your profit by choosing a **single day** to buy one stock and choosing a **different day in the future** to sell that stock.\n\nReturn *the maximum profit you can achieve from this transaction*. If you cannot achieve any profit, return `0`.", - "_readme_examples": { - "list": [ - { - "content": "```\nInput: prices = [7,1,5,3,6,4]\nOutput: 5\n```\n**Explanation:** Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.\nNote that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell." - }, - { - "content": "```\nInput: prices = [7,6,4,3,1]\nOutput: 0\n```\n**Explanation:** In this case, no transactions are done and the max profit = 0." - } - ] - }, - "readme_constraints": "- 1 <= prices.length <= 10^5\n- 0 <= prices[i] <= 10^4", - "readme_additional": "", - "helpers_imports": "", - "helpers_content": "", - "helpers_run_name": "max_profit", - "helpers_run_signature": "(solution_class: type, prices: list[int])", - "helpers_run_body": " implementation = solution_class()\n return implementation.max_profit(prices)", - "helpers_assert_name": "max_profit", - "helpers_assert_signature": "(result: int, expected: int) -> bool", - "helpers_assert_body": " assert result == expected\n return True", - "solution_imports": "", - "solution_contents": "", - "solution_class_content": "", - "test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_max_profit, run_max_profit\nfrom .solution import Solution", - "test_content": "", - "test_class_name": "BestTimeToBuyAndSellStock", - "test_class_content": " def setup_method(self):\n self.solution = Solution()", - "_solution_methods": { - "list": [ - { - "name": "max_profit", - "signature": "(self, prices: list[int]) -> int", - "body": " # TODO: Implement max_profit\n return 0" - } - ] - }, - "_test_helper_methods": { - "list": [ - { - "name": "setup_method", - "parameters": "", - "body": "self.solution = Solution()" - } - ] - }, - "_test_methods": { - "list": [ - { - "name": "test_max_profit", - "signature": "(self, prices: list[int], expected: int)", - "parametrize": "prices, expected", - "test_cases": { - "list": [ - "([7, 1, 5, 3, 6, 4], 5)", - "([7, 6, 4, 3, 1], 0)", - "([1, 2, 3, 4, 5], 4)", - "([5, 4, 3, 2, 1], 0)", - "([1], 0)", - "([2, 1], 0)", - "([1, 2], 1)", - "([3, 2, 6, 5, 0, 3], 4)", - "([2, 4, 1], 2)", - "([1, 5, 3, 6, 4], 5)", - "([10, 1, 5, 6, 7, 1], 6)", - "([6, 1, 3, 2, 4, 7], 6)", - "([1, 4, 2], 3)", - "([3, 3, 5, 0, 0, 3, 1, 4], 4)", - "([2, 1, 2, 1, 0, 1, 2], 2)" - ] - }, - "body": " result = run_max_profit(Solution, prices)\n assert_max_profit(result, expected)" - } - ] - }, - "playground_imports": "from helpers import run_max_profit, assert_max_profit\nfrom solution import Solution", - "playground_setup": "# Example test case\nprices = [7, 1, 5, 3, 6, 4]\nexpected = 5", - "playground_run": "result = run_max_profit(Solution, prices)\nresult", - "playground_assert": "assert_max_profit(result, expected)" -} + "problem_name": "best_time_to_buy_and_sell_stock", + "problem_number": "121", + "problem_title": "Best Time to Buy and Sell Stock", + "difficulty": "Easy", + "topics": "Array, Dynamic Programming", + "readme_description": "You are given an array prices where prices[i] is the price of a given stock on the ith day.\n\nYou want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.\n\nReturn the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.\n\n \nExample 1:\n\n\nInput: prices = [7,1,5,3,6,4]\nOutput: 5\nExplanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.\nNote that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell.\n\n\nExample 2:\n\n\nInput: prices = [7,6,4,3,1]\nOutput: 0\nExplanation: In this case, no transactions are done and the max profit = 0.\n\n\n \nConstraints:\n\n\n\t1 <= prices.length <= 105\n\t0 <= prices[i] <= 104", + "readme_constraints": "- 1 <= prices.length <= 105\n- 0 <= prices[i] <= 104", + "_readme_examples": { + "list": [ + { + "content": "Input: prices = [7,1,5,3,6,4]\nOutput: 5\nExplanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.\nNote that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell.\n\n\nExample 2:\n\n\nInput: prices = [7,6,4,3,1]\nOutput: 0\nExplanation: In this case, no transactions are done and the max profit = 0." + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "max_profit", + "signature": "(self, prices: List[int])-> int", + "body": " # TODO: Implement max_profit\n return 0" + } + ] + }, + "helpers_run_name": "max_profit", + "helpers_run_signature": "(solution_class: type, prices: List[int])", + "helpers_run_body": " implementation = solution_class()\n return implementation.max_profit(prices)", + "helpers_assert_name": "max_profit", + "helpers_assert_signature": "(result: int, expected: int) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "BestTimeToBuyAndSellStock", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_max_profit", + "signature": "(self, prices: List[int], expected: int)", + "parametrize": "prices, expected", + "test_cases": { + "list": [ + "([7,1,5,3,6,4], [7,6,4,3,1])" + ] + }, + "body": " result = run_max_profit(Solution, prices)\n assert_max_profit(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_max_profit, run_max_profit\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/leetcode_py/cli/resources/leetcode/json/problems/best_time_to_buy_and_sell_stock_ii.json b/leetcode_py/cli/resources/leetcode/json/problems/best_time_to_buy_and_sell_stock_ii.json new file mode 100644 index 0000000..d4f34d0 --- /dev/null +++ b/leetcode_py/cli/resources/leetcode/json/problems/best_time_to_buy_and_sell_stock_ii.json @@ -0,0 +1,50 @@ +{ + "problem_name": "best_time_to_buy_and_sell_stock_ii", + "problem_number": "122", + "problem_title": "Best Time to Buy and Sell Stock II", + "difficulty": "Medium", + "topics": "Array, Dynamic Programming, Greedy", + "readme_description": "You are given an integer array prices where prices[i] is the price of a given stock on the ith day.\n\nOn each day, you may decide to buy and/or sell the stock. You can only hold at most one share of the stock at any time. However, you can sell and buy the stock multiple times on the same day, ensuring you never hold more than one share of the stock.\n\nFind and return the maximum profit you can achieve.\n\n \nExample 1:\n\n\nInput: prices = [7,1,5,3,6,4]\nOutput: 7\nExplanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.\nThen buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.\nTotal profit is 4 + 3 = 7.\n\n\nExample 2:\n\n\nInput: prices = [1,2,3,4,5]\nOutput: 4\nExplanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.\nTotal profit is 4.\n\n\nExample 3:\n\n\nInput: prices = [7,6,4,3,1]\nOutput: 0\nExplanation: There is no way to make a positive profit, so we never buy the stock to achieve the maximum profit of 0.\n\n\n \nConstraints:\n\n\n\t1 <= prices.length <= 3 * 104\n\t0 <= prices[i] <= 104", + "readme_constraints": "- 1 <= prices.length <= 3 * 104\n- 0 <= prices[i] <= 104", + "_readme_examples": { + "list": [ + { + "content": "Input: prices = [7,1,5,3,6,4]\nOutput: 7\nExplanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.\nThen buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.\nTotal profit is 4 + 3 = 7.\n\n\nExample 2:\n\n\nInput: prices = [1,2,3,4,5]\nOutput: 4\nExplanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.\nTotal profit is 4.\n\n\nExample 3:\n\n\nInput: prices = [7,6,4,3,1]\nOutput: 0\nExplanation: There is no way to make a positive profit, so we never buy the stock to achieve the maximum profit of 0." + } + ] + }, + "solution_class_name": "Solution", + "_solution_methods": { + "list": [ + { + "name": "max_profit", + "signature": "(self, prices: List[int])-> int", + "body": " # TODO: Implement max_profit\n return 0" + } + ] + }, + "helpers_run_name": "max_profit", + "helpers_run_signature": "(solution_class: type, prices: List[int])", + "helpers_run_body": " implementation = solution_class()\n return implementation.max_profit(prices)", + "helpers_assert_name": "max_profit", + "helpers_assert_signature": "(result: int, expected: int) -> bool", + "helpers_assert_body": " assert result == expected\n return True", + "test_class_name": "BestTimeToBuyAndSellStockIi", + "test_class_content": " def setup_method(self):\n self.solution = Solution()", + "_test_methods": { + "list": [ + { + "name": "test_max_profit", + "signature": "(self, prices: List[int], expected: int)", + "parametrize": "prices, expected", + "test_cases": { + "list": [] + }, + "body": " result = run_max_profit(Solution, prices)\n assert_max_profit(result, expected)" + } + ] + }, + "solution_imports": "from typing import List", + "test_imports": "import pytest\nfrom typing import List\nfrom leetcode_py import logged_test\nfrom .helpers import assert_max_profit, run_max_profit\nfrom .solution import Solution", + "helpers_imports": "from typing import List" +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 19d9ec5..2aa52b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -91,7 +91,7 @@ select = [ "I", # isort "N", # pep8-naming ] -ignore = ["N806"] +ignore = ["N806", "N999"] [tool.ruff.lint.pydocstyle] convention = "numpy"