diff --git a/.codecov.yml b/.codecov.yml
index 7c00c0a..c11c152 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -1,4 +1,6 @@
coverage:
+ ignore:
+ - "**/playground.py"
status:
project:
default:
diff --git a/.github/workflows/ci-pre-commit.yml b/.github/workflows/ci-pre-commit.yml
index 2e8ee70..2ff49f4 100644
--- a/.github/workflows/ci-pre-commit.yml
+++ b/.github/workflows/ci-pre-commit.yml
@@ -9,6 +9,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ fetch-depth: 0
+ submodules: recursive
+ token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5123e0d..23a8453 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -22,6 +22,17 @@ repos:
id: gitleaks
- repo: local
hooks:
+ - id: sync-submodules
+ name: Sync git submodules
+ entry: bash -c 'output=$(git submodule update --init --recursive --remote 2>&1); [ -z "$output" ]'
+ language: system
+ always_run: true
+ pass_filenames: false
+ - id: nb-to-py
+ name: convert notebooks to python
+ entry: make nb-to-py
+ language: system
+ pass_filenames: false
- id: lint
name: lint
entry: make lint
diff --git a/Makefile b/Makefile
index 0f97dae..377ff6d 100644
--- a/Makefile
+++ b/Makefile
@@ -77,6 +77,13 @@ p-gen:
p-del:
rm -rf leetcode/$(PROBLEM)
+# Convert all notebooks to .py files and delete .ipynb for better version control
+nb-to-py:
+ @echo "Converting all .ipynb files in leetcode/ to .py files..."
+ @find leetcode -name "*.ipynb" -exec poetry run jupytext --to py:percent {} \;
+ @find leetcode -name "*.ipynb" -delete
+ @echo "Conversion complete. All .ipynb files converted to .py and deleted."
+
# Generate All Problems - useful for people who fork this repo
gen-all-problems:
@echo "This will DELETE all existing problems and regenerate from JSON templates."
diff --git a/leetcode/accounts_merge/playground.ipynb b/leetcode/accounts_merge/playground.ipynb
deleted file mode 100644
index f0dcd43..0000000
--- a/leetcode/accounts_merge/playground.ipynb
+++ /dev/null
@@ -1,102 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_accounts_merge, run_accounts_merge\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "accounts = [\n",
- " [\"John\", \"johnsmith@mail.com\", \"john_newyork@mail.com\"],\n",
- " [\"John\", \"johnsmith@mail.com\", \"john00@mail.com\"],\n",
- " [\"Mary\", \"mary@mail.com\"],\n",
- " [\"John\", \"johnnybravo@mail.com\"],\n",
- "]\n",
- "expected = [\n",
- " [\"John\", \"john00@mail.com\", \"john_newyork@mail.com\", \"johnsmith@mail.com\"],\n",
- " [\"Mary\", \"mary@mail.com\"],\n",
- " [\"John\", \"johnnybravo@mail.com\"],\n",
- "]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[['John', 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'],\n",
- " ['Mary', 'mary@mail.com'],\n",
- " ['John', 'johnnybravo@mail.com']]"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_accounts_merge(Solution, accounts)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_accounts_merge(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/accounts_merge/playground.py b/leetcode/accounts_merge/playground.py
new file mode 100644
index 0000000..d2ee36c
--- /dev/null
+++ b/leetcode/accounts_merge/playground.py
@@ -0,0 +1,38 @@
+# ---
+# jupyter:
+# jupytext:
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_accounts_merge, run_accounts_merge
+from solution import Solution
+
+# %%
+# Example test case
+accounts = [
+ ["John", "johnsmith@mail.com", "john_newyork@mail.com"],
+ ["John", "johnsmith@mail.com", "john00@mail.com"],
+ ["Mary", "mary@mail.com"],
+ ["John", "johnnybravo@mail.com"],
+]
+expected = [
+ ["John", "john00@mail.com", "john_newyork@mail.com", "johnsmith@mail.com"],
+ ["Mary", "mary@mail.com"],
+ ["John", "johnnybravo@mail.com"],
+]
+
+# %%
+result = run_accounts_merge(Solution, accounts)
+result
+
+# %%
+assert_accounts_merge(result, expected)
diff --git a/leetcode/add_binary/playground.ipynb b/leetcode/add_binary/playground.ipynb
deleted file mode 100644
index 0b2a93d..0000000
--- a/leetcode/add_binary/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_add_binary, run_add_binary\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "a = \"11\"\n",
- "b = \"1\"\n",
- "expected = \"100\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_add_binary(Solution, a, b)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_add_binary(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/playground.py b/leetcode/add_binary/playground.py
new file mode 100644
index 0000000..41e3fdd
--- /dev/null
+++ b/leetcode/add_binary/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_add_binary, run_add_binary
+from solution import Solution
+
+# %%
+# Example test case
+a = "11"
+b = "1"
+expected = "100"
+
+# %%
+result = run_add_binary(Solution, a, b)
+result
+
+# %%
+assert_add_binary(result, expected)
diff --git a/leetcode/balanced_binary_tree/playground.ipynb b/leetcode/balanced_binary_tree/playground.ipynb
deleted file mode 100644
index e115cdb..0000000
--- a/leetcode/balanced_binary_tree/playground.ipynb
+++ /dev/null
@@ -1,183 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_is_balanced, run_is_balanced\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list: list[int | None] = [3, 9, 20, None, None, 15, 7]\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_is_balanced(Solution, root_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "c01db53b",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "\n",
- "\n",
- "\n"
- ],
- "text/plain": [
- "TreeNode([3, 9, 20, None, None, 15, 7])"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "root = TreeNode.from_list(root_list)\n",
- "root"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_is_balanced(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/balanced_binary_tree/playground.py b/leetcode/balanced_binary_tree/playground.py
new file mode 100644
index 0000000..900c979
--- /dev/null
+++ b/leetcode/balanced_binary_tree/playground.py
@@ -0,0 +1,35 @@
+# ---
+# jupyter:
+# jupytext:
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_is_balanced, run_is_balanced
+from solution import Solution
+
+from leetcode_py import TreeNode
+
+# %%
+# Example test case
+root_list: list[int | None] = [3, 9, 20, None, None, 15, 7]
+expected = True
+
+# %%
+result = run_is_balanced(Solution, root_list)
+result
+
+# %%
+root = TreeNode.from_list(root_list)
+root
+
+# %%
+assert_is_balanced(result, expected)
diff --git a/leetcode/basic_calculator/playground.ipynb b/leetcode/basic_calculator/playground.ipynb
deleted file mode 100644
index d7681b7..0000000
--- a/leetcode/basic_calculator/playground.ipynb
+++ /dev/null
@@ -1,91 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_calculate, run_calculate\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"(1+(4+5+2)-3)+(6+8)\"\n",
- "expected = 23"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "23"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_calculate(Solution, s)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_calculate(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/basic_calculator/playground.py b/leetcode/basic_calculator/playground.py
new file mode 100644
index 0000000..261975f
--- /dev/null
+++ b/leetcode/basic_calculator/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_calculate, run_calculate
+from solution import Solution
+
+# %%
+# Example test case
+s = "(1+(4+5+2)-3)+(6+8)"
+expected = 23
+
+# %%
+result = run_calculate(Solution, s)
+result
+
+# %%
+assert_calculate(result, expected)
diff --git a/leetcode/best_time_to_buy_and_sell_stock/playground.ipynb b/leetcode/best_time_to_buy_and_sell_stock/playground.ipynb
deleted file mode 100644
index 81034bf..0000000
--- a/leetcode/best_time_to_buy_and_sell_stock/playground.ipynb
+++ /dev/null
@@ -1,91 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_max_profit, run_max_profit\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "prices = [7, 1, 5, 3, 6, 4]\n",
- "expected = 5"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "5"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_max_profit(Solution, prices)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_max_profit(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/best_time_to_buy_and_sell_stock/playground.py b/leetcode/best_time_to_buy_and_sell_stock/playground.py
new file mode 100644
index 0000000..e643984
--- /dev/null
+++ b/leetcode/best_time_to_buy_and_sell_stock/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_max_profit, run_max_profit
+from solution import Solution
+
+# %%
+# Example test case
+prices = [7, 1, 5, 3, 6, 4]
+expected = 5
+
+# %%
+result = run_max_profit(Solution, prices)
+result
+
+# %%
+assert_max_profit(result, expected)
diff --git a/leetcode/binary_search/playground.ipynb b/leetcode/binary_search/playground.ipynb
deleted file mode 100644
index 9c1a608..0000000
--- a/leetcode/binary_search/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_search, run_search\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [-1, 0, 3, 5, 9, 12]\n",
- "target = 9\n",
- "expected = 4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_search(Solution, nums, target)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_search(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/binary_search/playground.py b/leetcode/binary_search/playground.py
new file mode 100644
index 0000000..02af2a1
--- /dev/null
+++ b/leetcode/binary_search/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_search, run_search
+from solution import Solution
+
+# %%
+# Example test case
+nums = [-1, 0, 3, 5, 9, 12]
+target = 9
+expected = 4
+
+# %%
+result = run_search(Solution, nums, target)
+result
+
+# %%
+assert_search(result, expected)
diff --git a/leetcode/binary_tree_level_order_traversal/playground.ipynb b/leetcode/binary_tree_level_order_traversal/playground.ipynb
deleted file mode 100644
index 9c98b39..0000000
--- a/leetcode/binary_tree_level_order_traversal/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_level_order, run_level_order\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list: list[int | None] = [3, 9, 20, None, None, 15, 7]\n",
- "expected = [[3], [9, 20], [15, 7]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_level_order(Solution, root_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_level_order(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/binary_tree_level_order_traversal/playground.py b/leetcode/binary_tree_level_order_traversal/playground.py
new file mode 100644
index 0000000..42a84cd
--- /dev/null
+++ b/leetcode/binary_tree_level_order_traversal/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_level_order, run_level_order
+from solution import Solution
+
+# %%
+# Example test case
+root_list: list[int | None] = [3, 9, 20, None, None, 15, 7]
+expected = [[3], [9, 20], [15, 7]]
+
+# %%
+result = run_level_order(Solution, root_list)
+result
+
+# %%
+assert_level_order(result, expected)
diff --git a/leetcode/binary_tree_right_side_view/playground.ipynb b/leetcode/binary_tree_right_side_view/playground.ipynb
deleted file mode 100644
index 9187c4f..0000000
--- a/leetcode/binary_tree_right_side_view/playground.ipynb
+++ /dev/null
@@ -1,183 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_right_side_view, run_right_side_view\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list: list[int | None] = [1, 2, 3, None, 5, None, 4]\n",
- "expected = [1, 3, 4]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "6ba11550",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "\n",
- "\n",
- "\n"
- ],
- "text/plain": [
- "TreeNode([1, 2, 3, None, 5, None, 4])"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "root = TreeNode.from_list(root_list)\n",
- "root"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[1, 3, 4]"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_right_side_view(Solution, root_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_right_side_view(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/binary_tree_right_side_view/playground.py b/leetcode/binary_tree_right_side_view/playground.py
new file mode 100644
index 0000000..bbef9b5
--- /dev/null
+++ b/leetcode/binary_tree_right_side_view/playground.py
@@ -0,0 +1,36 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_right_side_view, run_right_side_view
+from solution import Solution
+
+from leetcode_py import TreeNode
+
+# %%
+# Example test case
+root_list: list[int | None] = [1, 2, 3, None, 5, None, 4]
+expected = [1, 3, 4]
+
+# %%
+root = TreeNode.from_list(root_list)
+root
+
+# %%
+result = run_right_side_view(Solution, root_list)
+result
+
+# %%
+assert_right_side_view(result, expected)
diff --git a/leetcode/binary_tree_right_side_view/test_solution.py b/leetcode/binary_tree_right_side_view/test_solution.py
index 2a1ca50..871ecef 100644
--- a/leetcode/binary_tree_right_side_view/test_solution.py
+++ b/leetcode/binary_tree_right_side_view/test_solution.py
@@ -3,7 +3,7 @@
from leetcode_py.test_utils import logged_test
from .helpers import assert_right_side_view, run_right_side_view
-from .solution import Solution
+from .solution import Solution, SolutionBFS, SolutionDFS
class TestBinaryTreeRightSideView:
@@ -11,6 +11,7 @@ def setup_method(self):
self.solution = Solution()
@logged_test
+ @pytest.mark.parametrize("solution_class", [Solution, SolutionDFS, SolutionBFS])
@pytest.mark.parametrize(
"root_list, expected",
[
@@ -30,6 +31,8 @@ def setup_method(self):
([10, 5, 15, None, 6, 12, 20], [10, 15, 20]),
],
)
- def test_right_side_view(self, root_list: list[int | None], expected: list[int]):
- result = run_right_side_view(Solution, root_list)
+ def test_right_side_view(
+ self, solution_class: type, root_list: list[int | None], expected: list[int]
+ ):
+ result = run_right_side_view(solution_class, root_list)
assert_right_side_view(result, expected)
diff --git a/leetcode/climbing_stairs/playground.ipynb b/leetcode/climbing_stairs/playground.ipynb
deleted file mode 100644
index 6fd5d25..0000000
--- a/leetcode/climbing_stairs/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_climb_stairs, run_climb_stairs\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "n = 3\n",
- "expected = 3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_climb_stairs(Solution, n)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_climb_stairs(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/climbing_stairs/playground.py b/leetcode/climbing_stairs/playground.py
new file mode 100644
index 0000000..51601a5
--- /dev/null
+++ b/leetcode/climbing_stairs/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_climb_stairs, run_climb_stairs
+from solution import Solution
+
+# %%
+# Example test case
+n = 3
+expected = 3
+
+# %%
+result = run_climb_stairs(Solution, n)
+result
+
+# %%
+assert_climb_stairs(result, expected)
diff --git a/leetcode/clone_graph/playground.ipynb b/leetcode/clone_graph/playground.ipynb
deleted file mode 100644
index bb2a422..0000000
--- a/leetcode/clone_graph/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_clone_graph, run_clone_graph\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import GraphNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "adj_list = [[2, 4], [1, 3], [2, 4], [1, 3]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_clone_graph(Solution, adj_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_clone_graph(result, adj_list)"
- ]
- }
- ],
- "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/clone_graph/playground.py b/leetcode/clone_graph/playground.py
new file mode 100644
index 0000000..509f051
--- /dev/null
+++ b/leetcode/clone_graph/playground.py
@@ -0,0 +1,29 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_clone_graph, run_clone_graph
+from solution import Solution
+
+# %%
+# Example test case
+adj_list = [[2, 4], [1, 3], [2, 4], [1, 3]]
+
+# %%
+result = run_clone_graph(Solution, adj_list)
+result
+
+# %%
+assert_clone_graph(result, adj_list)
diff --git a/leetcode/coin_change/playground.ipynb b/leetcode/coin_change/playground.ipynb
deleted file mode 100644
index 580d39c..0000000
--- a/leetcode/coin_change/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_coin_change, run_coin_change\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "coins = [1, 2, 5]\n",
- "amount = 11\n",
- "expected = 3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_coin_change(Solution, coins, amount)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_coin_change(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/coin_change/playground.py b/leetcode/coin_change/playground.py
new file mode 100644
index 0000000..99c925d
--- /dev/null
+++ b/leetcode/coin_change/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_coin_change, run_coin_change
+from solution import Solution
+
+# %%
+# Example test case
+coins = [1, 2, 5]
+amount = 11
+expected = 3
+
+# %%
+result = run_coin_change(Solution, coins, amount)
+result
+
+# %%
+assert_coin_change(result, expected)
diff --git a/leetcode/combination_sum/playground.ipynb b/leetcode/combination_sum/playground.ipynb
deleted file mode 100644
index ac0711f..0000000
--- a/leetcode/combination_sum/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_combination_sum, run_combination_sum\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "candidates = [2, 3, 6, 7]\n",
- "target = 7\n",
- "expected = [[2, 2, 3], [7]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_combination_sum(Solution, candidates, target)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_combination_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/combination_sum/playground.py b/leetcode/combination_sum/playground.py
new file mode 100644
index 0000000..c971550
--- /dev/null
+++ b/leetcode/combination_sum/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_combination_sum, run_combination_sum
+from solution import Solution
+
+# %%
+# Example test case
+candidates = [2, 3, 6, 7]
+target = 7
+expected = [[2, 2, 3], [7]]
+
+# %%
+result = run_combination_sum(Solution, candidates, target)
+result
+
+# %%
+assert_combination_sum(result, expected)
diff --git a/leetcode/container_with_most_water/playground.ipynb b/leetcode/container_with_most_water/playground.ipynb
deleted file mode 100644
index a95df0a..0000000
--- a/leetcode/container_with_most_water/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_max_area, run_max_area\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "height = [1, 8, 6, 2, 5, 4, 8, 3, 7]\n",
- "expected = 49"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_max_area(Solution, height)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_max_area(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/container_with_most_water/playground.py b/leetcode/container_with_most_water/playground.py
new file mode 100644
index 0000000..6d9f266
--- /dev/null
+++ b/leetcode/container_with_most_water/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_max_area, run_max_area
+from solution import Solution
+
+# %%
+# Example test case
+height = [1, 8, 6, 2, 5, 4, 8, 3, 7]
+expected = 49
+
+# %%
+result = run_max_area(Solution, height)
+result
+
+# %%
+assert_max_area(result, expected)
diff --git a/leetcode/contains_duplicate/playground.ipynb b/leetcode/contains_duplicate/playground.ipynb
deleted file mode 100644
index f43d0de..0000000
--- a/leetcode/contains_duplicate/playground.ipynb
+++ /dev/null
@@ -1,91 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_contains_duplicate, run_contains_duplicate\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [1, 2, 3, 1]\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_contains_duplicate(Solution, nums)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_contains_duplicate(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/contains_duplicate/playground.py b/leetcode/contains_duplicate/playground.py
new file mode 100644
index 0000000..84b6064
--- /dev/null
+++ b/leetcode/contains_duplicate/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_contains_duplicate, run_contains_duplicate
+from solution import Solution
+
+# %%
+# Example test case
+nums = [1, 2, 3, 1]
+expected = True
+
+# %%
+result = run_contains_duplicate(Solution, nums)
+result
+
+# %%
+assert_contains_duplicate(result, expected)
diff --git a/leetcode/course_schedule/playground.ipynb b/leetcode/course_schedule/playground.ipynb
deleted file mode 100644
index 2dfeb00..0000000
--- a/leetcode/course_schedule/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_can_finish, run_can_finish\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "num_courses = 2\n",
- "prerequisites = [[1, 0]]\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_can_finish(Solution, num_courses, prerequisites)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_can_finish(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/course_schedule/playground.py b/leetcode/course_schedule/playground.py
new file mode 100644
index 0000000..f1e4aef
--- /dev/null
+++ b/leetcode/course_schedule/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_can_finish, run_can_finish
+from solution import Solution
+
+# %%
+# Example test case
+num_courses = 2
+prerequisites = [[1, 0]]
+expected = True
+
+# %%
+result = run_can_finish(Solution, num_courses, prerequisites)
+result
+
+# %%
+assert_can_finish(result, expected)
diff --git a/leetcode/diameter_of_binary_tree/playground.ipynb b/leetcode/diameter_of_binary_tree/playground.ipynb
deleted file mode 100644
index d401bcf..0000000
--- a/leetcode/diameter_of_binary_tree/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_diameter_of_binary_tree, run_diameter_of_binary_tree\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list: list[int | None] = [1, 2, 3, 4, 5]\n",
- "expected = 3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_diameter_of_binary_tree(Solution, root_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_diameter_of_binary_tree(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/diameter_of_binary_tree/playground.py b/leetcode/diameter_of_binary_tree/playground.py
new file mode 100644
index 0000000..afd819a
--- /dev/null
+++ b/leetcode/diameter_of_binary_tree/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_diameter_of_binary_tree, run_diameter_of_binary_tree
+from solution import Solution
+
+# %%
+# Example test case
+root_list: list[int | None] = [1, 2, 3, 4, 5]
+expected = 3
+
+# %%
+result = run_diameter_of_binary_tree(Solution, root_list)
+result
+
+# %%
+assert_diameter_of_binary_tree(result, expected)
diff --git a/leetcode/evaluate_reverse_polish_notation/playground.ipynb b/leetcode/evaluate_reverse_polish_notation/playground.ipynb
deleted file mode 100644
index 01fd8b8..0000000
--- a/leetcode/evaluate_reverse_polish_notation/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_eval_rpn, run_eval_rpn\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "tokens = [\"2\", \"1\", \"+\", \"3\", \"*\"]\n",
- "expected = 9"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_eval_rpn(Solution, tokens)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_eval_rpn(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/evaluate_reverse_polish_notation/playground.py b/leetcode/evaluate_reverse_polish_notation/playground.py
new file mode 100644
index 0000000..8ecfa9f
--- /dev/null
+++ b/leetcode/evaluate_reverse_polish_notation/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_eval_rpn, run_eval_rpn
+from solution import Solution
+
+# %%
+# Example test case
+tokens = ["2", "1", "+", "3", "*"]
+expected = 9
+
+# %%
+result = run_eval_rpn(Solution, tokens)
+result
+
+# %%
+assert_eval_rpn(result, expected)
diff --git a/leetcode/find_median_from_data_stream/playground.ipynb b/leetcode/find_median_from_data_stream/playground.ipynb
deleted file mode 100644
index 3a72e85..0000000
--- a/leetcode/find_median_from_data_stream/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_median_finder, run_median_finder\n",
- "from solution import MedianFinder"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "operations = [\"MedianFinder\", \"addNum\", \"addNum\", \"findMedian\", \"addNum\", \"findMedian\"]\n",
- "inputs = [[], [1], [2], [], [3], []]\n",
- "expected = [None, None, None, 1.5, None, 2.0]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result, mf = run_median_finder(MedianFinder, operations, inputs)\n",
- "print(result)\n",
- "mf"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_median_finder(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/find_median_from_data_stream/playground.py b/leetcode/find_median_from_data_stream/playground.py
new file mode 100644
index 0000000..351a75a
--- /dev/null
+++ b/leetcode/find_median_from_data_stream/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_median_finder, run_median_finder
+from solution import MedianFinder
+
+# %%
+# Example test case
+operations = ["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"]
+inputs = [[], [1], [2], [], [3], []]
+expected = [None, None, None, 1.5, None, 2.0]
+
+# %%
+result, mf = run_median_finder(MedianFinder, operations, inputs)
+print(result)
+mf
+
+# %%
+assert_median_finder(result, expected)
diff --git a/leetcode/first_bad_version/playground.ipynb b/leetcode/first_bad_version/playground.ipynb
deleted file mode 100644
index eff1efe..0000000
--- a/leetcode/first_bad_version/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_first_bad_version, run_first_bad_version\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "n = 5\n",
- "bad = 4\n",
- "expected = 4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_first_bad_version(Solution, n, bad)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_first_bad_version(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/first_bad_version/playground.py b/leetcode/first_bad_version/playground.py
new file mode 100644
index 0000000..34af8a1
--- /dev/null
+++ b/leetcode/first_bad_version/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_first_bad_version, run_first_bad_version
+from solution import Solution
+
+# %%
+# Example test case
+n = 5
+bad = 4
+expected = 4
+
+# %%
+result = run_first_bad_version(Solution, n, bad)
+result
+
+# %%
+assert_first_bad_version(result, expected)
diff --git a/leetcode/flood_fill/playground.ipynb b/leetcode/flood_fill/playground.ipynb
deleted file mode 100644
index 583f7a1..0000000
--- a/leetcode/flood_fill/playground.ipynb
+++ /dev/null
@@ -1,71 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_flood_fill, run_flood_fill\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "image = [[1, 1, 1], [1, 1, 0], [1, 0, 1]]\n",
- "sr = 1\n",
- "sc = 1\n",
- "color = 2\n",
- "expected = [[2, 2, 2], [2, 2, 0], [2, 0, 1]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_flood_fill(Solution, image, sr, sc, color)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_flood_fill(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/flood_fill/playground.py b/leetcode/flood_fill/playground.py
new file mode 100644
index 0000000..674fb9c
--- /dev/null
+++ b/leetcode/flood_fill/playground.py
@@ -0,0 +1,33 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_flood_fill, run_flood_fill
+from solution import Solution
+
+# %%
+# Example test case
+image = [[1, 1, 1], [1, 1, 0], [1, 0, 1]]
+sr = 1
+sc = 1
+color = 2
+expected = [[2, 2, 2], [2, 2, 0], [2, 0, 1]]
+
+# %%
+result = run_flood_fill(Solution, image, sr, sc, color)
+result
+
+# %%
+assert_flood_fill(result, expected)
diff --git a/leetcode/implement_queue_using_stacks/playground.ipynb b/leetcode/implement_queue_using_stacks/playground.ipynb
deleted file mode 100644
index 735a590..0000000
--- a/leetcode/implement_queue_using_stacks/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_my_queue, run_my_queue\n",
- "from solution import MyQueue"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "operations = [\"MyQueue\", \"push\", \"push\", \"peek\", \"pop\", \"empty\"]\n",
- "inputs = [[], [1], [2], [], [], []]\n",
- "expected = [None, None, None, 1, 1, False]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result, queue = run_my_queue(MyQueue, operations, inputs)\n",
- "print(result)\n",
- "queue"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_my_queue(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/implement_queue_using_stacks/playground.py b/leetcode/implement_queue_using_stacks/playground.py
new file mode 100644
index 0000000..834b6b8
--- /dev/null
+++ b/leetcode/implement_queue_using_stacks/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_my_queue, run_my_queue
+from solution import MyQueue
+
+# %%
+# Example test case
+operations = ["MyQueue", "push", "push", "peek", "pop", "empty"]
+inputs = [[], [1], [2], [], [], []]
+expected = [None, None, None, 1, 1, False]
+
+# %%
+result, queue = run_my_queue(MyQueue, operations, inputs)
+print(result)
+queue
+
+# %%
+assert_my_queue(result, expected)
diff --git a/leetcode/implement_trie_prefix_tree/playground.ipynb b/leetcode/implement_trie_prefix_tree/playground.ipynb
deleted file mode 100644
index c509af4..0000000
--- a/leetcode/implement_trie_prefix_tree/playground.ipynb
+++ /dev/null
@@ -1,204 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_trie_operations, run_trie_operations\n",
- "from solution import Trie"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "operations = [\"Trie\", \"insert\", \"search\", \"search\", \"starts_with\", \"insert\", \"search\"]\n",
- "inputs = [[], [\"apple\"], [\"apple\"], [\"app\"], [\"app\"], [\"app\"], [\"app\"]]\n",
- "expected = [None, None, True, False, True, None, True]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[None, None, True, False, True, None, True]\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "\n",
- "\n",
- "\n"
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result, trie = run_trie_operations(Trie, operations, inputs)\n",
- "print(result)\n",
- "trie"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_trie_operations(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/implement_trie_prefix_tree/playground.py b/leetcode/implement_trie_prefix_tree/playground.py
new file mode 100644
index 0000000..815d6f6
--- /dev/null
+++ b/leetcode/implement_trie_prefix_tree/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_trie_operations, run_trie_operations
+from solution import Trie
+
+# %%
+# Example test case
+operations = ["Trie", "insert", "search", "search", "starts_with", "insert", "search"]
+inputs = [[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
+expected = [None, None, True, False, True, None, True]
+
+# %%
+result, trie = run_trie_operations(Trie, operations, inputs)
+print(result)
+trie
+
+# %%
+assert_trie_operations(result, expected)
diff --git a/leetcode/insert_interval/playground.ipynb b/leetcode/insert_interval/playground.ipynb
deleted file mode 100644
index 0e8d78f..0000000
--- a/leetcode/insert_interval/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_insert, run_insert\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "intervals = [[1, 3], [6, 9]]\n",
- "new_interval = [2, 5]\n",
- "expected = [[1, 5], [6, 9]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_insert(Solution, intervals, new_interval)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_insert(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/insert_interval/playground.py b/leetcode/insert_interval/playground.py
new file mode 100644
index 0000000..d895d17
--- /dev/null
+++ b/leetcode/insert_interval/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_insert, run_insert
+from solution import Solution
+
+# %%
+# Example test case
+intervals = [[1, 3], [6, 9]]
+new_interval = [2, 5]
+expected = [[1, 5], [6, 9]]
+
+# %%
+result = run_insert(Solution, intervals, new_interval)
+result
+
+# %%
+assert_insert(result, expected)
diff --git a/leetcode/invert_binary_tree/playground.ipynb b/leetcode/invert_binary_tree/playground.ipynb
deleted file mode 100644
index ba35a6c..0000000
--- a/leetcode/invert_binary_tree/playground.ipynb
+++ /dev/null
@@ -1,185 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_invert_tree, run_invert_tree\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list: list[int | None] = [4, 2, 7, 1, 3, 6, 9]\n",
- "expected_list: list[int | None] = [4, 7, 2, 9, 6, 3, 1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "\n",
- "\n",
- "\n"
- ],
- "text/plain": [
- "TreeNode([4, 7, 2, 9, 6, 3, 1])"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_invert_tree(Solution, root_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_invert_tree(result, expected_list)"
- ]
- }
- ],
- "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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/invert_binary_tree/playground.py b/leetcode/invert_binary_tree/playground.py
new file mode 100644
index 0000000..2805ae6
--- /dev/null
+++ b/leetcode/invert_binary_tree/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_invert_tree, run_invert_tree
+from solution import Solution
+
+# %%
+# Example test case
+root_list: list[int | None] = [4, 2, 7, 1, 3, 6, 9]
+expected_list: list[int | None] = [4, 7, 2, 9, 6, 3, 1]
+
+# %%
+result = run_invert_tree(Solution, root_list)
+result
+
+# %%
+assert_invert_tree(result, expected_list)
diff --git a/leetcode/invert_binary_tree/test_solution.py b/leetcode/invert_binary_tree/test_solution.py
index f20e784..9e40afb 100644
--- a/leetcode/invert_binary_tree/test_solution.py
+++ b/leetcode/invert_binary_tree/test_solution.py
@@ -3,7 +3,7 @@
from leetcode_py.test_utils import logged_test
from .helpers import assert_invert_tree, run_invert_tree
-from .solution import Solution
+from .solution import Solution, SolutionBFS, SolutionDFS
class TestInvertBinaryTree:
@@ -11,6 +11,7 @@ def setup_method(self):
self.solution = Solution()
@logged_test
+ @pytest.mark.parametrize("solution_class", [Solution, SolutionDFS, SolutionBFS])
@pytest.mark.parametrize(
"root_list, expected_list",
[
@@ -31,6 +32,8 @@ def setup_method(self):
([1, 2, 3, None, 4, None, 5], [1, 3, 2, 5, None, 4]),
],
)
- def test_invert_tree(self, root_list: list[int | None], expected_list: list[int | None]):
- result = run_invert_tree(Solution, root_list)
+ def test_invert_tree(
+ self, solution_class: type, root_list: list[int | None], expected_list: list[int | None]
+ ):
+ result = run_invert_tree(solution_class, root_list)
assert_invert_tree(result, expected_list)
diff --git a/leetcode/k_closest_points_to_origin/playground.ipynb b/leetcode/k_closest_points_to_origin/playground.ipynb
deleted file mode 100644
index fce66ec..0000000
--- a/leetcode/k_closest_points_to_origin/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_k_closest, run_k_closest\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "points = [[1, 3], [-2, 2]]\n",
- "k = 1\n",
- "expected = [[-2, 2]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_k_closest(Solution, points, k)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_k_closest(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/k_closest_points_to_origin/playground.py b/leetcode/k_closest_points_to_origin/playground.py
new file mode 100644
index 0000000..5efc6f0
--- /dev/null
+++ b/leetcode/k_closest_points_to_origin/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_k_closest, run_k_closest
+from solution import Solution
+
+# %%
+# Example test case
+points = [[1, 3], [-2, 2]]
+k = 1
+expected = [[-2, 2]]
+
+# %%
+result = run_k_closest(Solution, points, k)
+result
+
+# %%
+assert_k_closest(result, expected)
diff --git a/leetcode/kth_smallest_element_in_a_bst/playground.ipynb b/leetcode/kth_smallest_element_in_a_bst/playground.ipynb
deleted file mode 100644
index b65acaf..0000000
--- a/leetcode/kth_smallest_element_in_a_bst/playground.ipynb
+++ /dev/null
@@ -1,71 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_kth_smallest, run_kth_smallest\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list = [3, 1, 4, None, 2]\n",
- "k = 1\n",
- "expected = 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_kth_smallest(Solution, root_list, k)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_kth_smallest(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/kth_smallest_element_in_a_bst/playground.py b/leetcode/kth_smallest_element_in_a_bst/playground.py
new file mode 100644
index 0000000..6cff3f7
--- /dev/null
+++ b/leetcode/kth_smallest_element_in_a_bst/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_kth_smallest, run_kth_smallest
+from solution import Solution
+
+# %%
+# Example test case
+root_list = [3, 1, 4, None, 2]
+k = 1
+expected = 1
+
+# %%
+result = run_kth_smallest(Solution, root_list, k)
+result
+
+# %%
+assert_kth_smallest(result, expected)
diff --git a/leetcode/largest_rectangle_in_histogram/playground.ipynb b/leetcode/largest_rectangle_in_histogram/playground.ipynb
deleted file mode 100644
index 8470983..0000000
--- a/leetcode/largest_rectangle_in_histogram/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_largest_rectangle_area, run_largest_rectangle_area\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "heights = [2, 1, 5, 6, 2, 3]\n",
- "expected = 10"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_largest_rectangle_area(Solution, heights)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_largest_rectangle_area(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/largest_rectangle_in_histogram/playground.py b/leetcode/largest_rectangle_in_histogram/playground.py
new file mode 100644
index 0000000..16761db
--- /dev/null
+++ b/leetcode/largest_rectangle_in_histogram/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_largest_rectangle_area, run_largest_rectangle_area
+from solution import Solution
+
+# %%
+# Example test case
+heights = [2, 1, 5, 6, 2, 3]
+expected = 10
+
+# %%
+result = run_largest_rectangle_area(Solution, heights)
+result
+
+# %%
+assert_largest_rectangle_area(result, expected)
diff --git a/leetcode/linked_list_cycle/playground.ipynb b/leetcode/linked_list_cycle/playground.ipynb
deleted file mode 100644
index f4adc95..0000000
--- a/leetcode/linked_list_cycle/playground.ipynb
+++ /dev/null
@@ -1,177 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_has_cycle, create_cycle_list, run_has_cycle\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "values = [3, 2, 0, -4]\n",
- "pos = 1\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "66f97343",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "\n",
- "\n",
- "\n"
- ],
- "text/plain": [
- "ListNode([3, 2, 0, -4])"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "head = create_cycle_list(values, pos)\n",
- "head"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_has_cycle(Solution, values, pos)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_has_cycle(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/linked_list_cycle/playground.py b/leetcode/linked_list_cycle/playground.py
new file mode 100644
index 0000000..b19e7f6
--- /dev/null
+++ b/leetcode/linked_list_cycle/playground.py
@@ -0,0 +1,35 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_has_cycle, create_cycle_list, run_has_cycle
+from solution import Solution
+
+# %%
+# Example test case
+values = [3, 2, 0, -4]
+pos = 1
+expected = True
+
+# %%
+head = create_cycle_list(values, pos)
+head
+
+# %%
+result = run_has_cycle(Solution, values, pos)
+result
+
+# %%
+assert_has_cycle(result, expected)
diff --git a/leetcode/longest_palindrome/playground.ipynb b/leetcode/longest_palindrome/playground.ipynb
deleted file mode 100644
index 31ff59e..0000000
--- a/leetcode/longest_palindrome/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_longest_palindrome, run_longest_palindrome\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"abccccdd\"\n",
- "expected = 7"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_longest_palindrome(Solution, s)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_longest_palindrome(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/longest_palindrome/playground.py b/leetcode/longest_palindrome/playground.py
new file mode 100644
index 0000000..d84ed13
--- /dev/null
+++ b/leetcode/longest_palindrome/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_longest_palindrome, run_longest_palindrome
+from solution import Solution
+
+# %%
+# Example test case
+s = "abccccdd"
+expected = 7
+
+# %%
+result = run_longest_palindrome(Solution, s)
+result
+
+# %%
+assert_longest_palindrome(result, expected)
diff --git a/leetcode/longest_palindromic_substring/playground.ipynb b/leetcode/longest_palindromic_substring/playground.ipynb
deleted file mode 100644
index be01046..0000000
--- a/leetcode/longest_palindromic_substring/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_longest_palindrome, run_longest_palindrome\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"babad\"\n",
- "expected = {\"bab\", \"aba\"}"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_longest_palindrome(Solution, s)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_longest_palindrome(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/longest_palindromic_substring/playground.py b/leetcode/longest_palindromic_substring/playground.py
new file mode 100644
index 0000000..ee1069b
--- /dev/null
+++ b/leetcode/longest_palindromic_substring/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_longest_palindrome, run_longest_palindrome
+from solution import Solution
+
+# %%
+# Example test case
+s = "babad"
+expected = {"bab", "aba"}
+
+# %%
+result = run_longest_palindrome(Solution, s)
+result
+
+# %%
+assert_longest_palindrome(result, expected)
diff --git a/leetcode/longest_palindromic_substring/test_solution.py b/leetcode/longest_palindromic_substring/test_solution.py
index 832e8fa..0cd1994 100644
--- a/leetcode/longest_palindromic_substring/test_solution.py
+++ b/leetcode/longest_palindromic_substring/test_solution.py
@@ -3,7 +3,7 @@
from leetcode_py.test_utils import logged_test
from .helpers import assert_longest_palindrome, run_longest_palindrome
-from .solution import Solution
+from .solution import Solution, SolutionManacher
class TestLongestPalindromicSubstring:
@@ -11,6 +11,7 @@ def setup_method(self):
self.solution = Solution()
@logged_test
+ @pytest.mark.parametrize("solution_class", [Solution, SolutionManacher])
@pytest.mark.parametrize(
"s, expected",
[
@@ -28,6 +29,6 @@ def setup_method(self):
("abcba", {"abcba"}),
],
)
- def test_longest_palindrome(self, s: str, expected: set[str]):
- result = run_longest_palindrome(Solution, s)
+ def test_longest_palindrome(self, solution_class: type, s: str, expected: set[str]):
+ result = run_longest_palindrome(solution_class, s)
assert_longest_palindrome(result, expected)
diff --git a/leetcode/longest_substring_without_repeating_characters/playground.ipynb b/leetcode/longest_substring_without_repeating_characters/playground.ipynb
deleted file mode 100644
index 0c23372..0000000
--- a/leetcode/longest_substring_without_repeating_characters/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_length_of_longest_substring, run_length_of_longest_substring\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"abcabcbb\"\n",
- "expected = 3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_length_of_longest_substring(Solution, s)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_length_of_longest_substring(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/longest_substring_without_repeating_characters/playground.py b/leetcode/longest_substring_without_repeating_characters/playground.py
new file mode 100644
index 0000000..e2b9bf4
--- /dev/null
+++ b/leetcode/longest_substring_without_repeating_characters/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_length_of_longest_substring, run_length_of_longest_substring
+from solution import Solution
+
+# %%
+# Example test case
+s = "abcabcbb"
+expected = 3
+
+# %%
+result = run_length_of_longest_substring(Solution, s)
+result
+
+# %%
+assert_length_of_longest_substring(result, expected)
diff --git a/leetcode/lowest_common_ancestor_of_a_binary_search_tree/playground.ipynb b/leetcode/lowest_common_ancestor_of_a_binary_search_tree/playground.ipynb
deleted file mode 100644
index 6f5c85e..0000000
--- a/leetcode/lowest_common_ancestor_of_a_binary_search_tree/playground.ipynb
+++ /dev/null
@@ -1,72 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_lowest_common_ancestor, run_lowest_common_ancestor\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list = [6, 2, 8, 0, 4, 7, 9, None, None, 3, 5]\n",
- "p_val = 2\n",
- "q_val = 8\n",
- "expected_val = 6"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_lowest_common_ancestor(Solution, root_list, p_val, q_val)\n",
- "result.val if result else None"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_lowest_common_ancestor(result, expected_val)"
- ]
- }
- ],
- "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/lowest_common_ancestor_of_a_binary_search_tree/playground.py b/leetcode/lowest_common_ancestor_of_a_binary_search_tree/playground.py
new file mode 100644
index 0000000..1e7eb79
--- /dev/null
+++ b/leetcode/lowest_common_ancestor_of_a_binary_search_tree/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_lowest_common_ancestor, run_lowest_common_ancestor
+from solution import Solution
+
+# %%
+# Example test case
+root_list = [6, 2, 8, 0, 4, 7, 9, None, None, 3, 5]
+p_val = 2
+q_val = 8
+expected_val = 6
+
+# %%
+result = run_lowest_common_ancestor(Solution, root_list, p_val, q_val)
+result.val if result else None
+
+# %%
+assert_lowest_common_ancestor(result, expected_val)
diff --git a/leetcode/lowest_common_ancestor_of_a_binary_tree/playground.ipynb b/leetcode/lowest_common_ancestor_of_a_binary_tree/playground.ipynb
deleted file mode 100644
index 0251030..0000000
--- a/leetcode/lowest_common_ancestor_of_a_binary_tree/playground.ipynb
+++ /dev/null
@@ -1,72 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_lowest_common_ancestor, run_lowest_common_ancestor\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list = [3, 5, 1, 6, 2, 0, 8, None, None, 7, 4]\n",
- "p_val = 5\n",
- "q_val = 1\n",
- "expected_val = 3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_lowest_common_ancestor(Solution, root_list, p_val, q_val)\n",
- "result.val"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_lowest_common_ancestor(result, expected_val)"
- ]
- }
- ],
- "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/lowest_common_ancestor_of_a_binary_tree/playground.py b/leetcode/lowest_common_ancestor_of_a_binary_tree/playground.py
new file mode 100644
index 0000000..39884fc
--- /dev/null
+++ b/leetcode/lowest_common_ancestor_of_a_binary_tree/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_lowest_common_ancestor, run_lowest_common_ancestor
+from solution import Solution
+
+# %%
+# Example test case
+root_list = [3, 5, 1, 6, 2, 0, 8, None, None, 7, 4]
+p_val = 5
+q_val = 1
+expected_val = 3
+
+# %%
+result = run_lowest_common_ancestor(Solution, root_list, p_val, q_val)
+result.val
+
+# %%
+assert_lowest_common_ancestor(result, expected_val)
diff --git a/leetcode/lru_cache/playground.ipynb b/leetcode/lru_cache/playground.ipynb
deleted file mode 100644
index 687c6f1..0000000
--- a/leetcode/lru_cache/playground.ipynb
+++ /dev/null
@@ -1,100 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_lru_cache, run_lru_cache\n",
- "from solution import LRUCache"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "operations = [\"LRUCache\", \"put\", \"put\", \"get\", \"put\", \"get\", \"put\", \"get\", \"get\", \"get\"]\n",
- "inputs = [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]\n",
- "expected = [None, None, None, 1, None, -1, None, -1, 3, 4]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[None, None, None, 1, None, -1, None, -1, 3, 4]\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "OrderedDict([(3, 3), (4, 4)])"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result, cache = run_lru_cache(LRUCache, operations, inputs)\n",
- "print(result)\n",
- "cache.cache"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_lru_cache(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/lru_cache/playground.py b/leetcode/lru_cache/playground.py
new file mode 100644
index 0000000..6269d30
--- /dev/null
+++ b/leetcode/lru_cache/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_lru_cache, run_lru_cache
+from solution import LRUCache
+
+# %%
+# Example test case
+operations = ["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
+inputs = [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
+expected = [None, None, None, 1, None, -1, None, -1, 3, 4]
+
+# %%
+result, cache = run_lru_cache(LRUCache, operations, inputs)
+print(result)
+cache.cache
+
+# %%
+assert_lru_cache(result, expected)
diff --git a/leetcode/lru_cache/test_solution.py b/leetcode/lru_cache/test_solution.py
index 0fcaa3d..db70723 100644
--- a/leetcode/lru_cache/test_solution.py
+++ b/leetcode/lru_cache/test_solution.py
@@ -3,12 +3,13 @@
from leetcode_py.test_utils import logged_test
from .helpers import assert_lru_cache, run_lru_cache
-from .solution import LRUCache
+from .solution import LRUCache, LRUCacheWithDoublyList
class TestLRUCache:
@logged_test
+ @pytest.mark.parametrize("solution_class", [LRUCache, LRUCacheWithDoublyList])
@pytest.mark.parametrize(
"operations, inputs, expected",
[
@@ -66,6 +67,12 @@ class TestLRUCache:
),
],
)
- def test_lru_cache(self, operations: list[str], inputs: list[list[int]], expected: list[int | None]):
- result, _ = run_lru_cache(LRUCache, operations, inputs)
+ def test_lru_cache(
+ self,
+ solution_class: type,
+ operations: list[str],
+ inputs: list[list[int]],
+ expected: list[int | None],
+ ):
+ result, _ = run_lru_cache(solution_class, operations, inputs)
assert_lru_cache(result, expected)
diff --git a/leetcode/majority_element/playground.ipynb b/leetcode/majority_element/playground.ipynb
deleted file mode 100644
index 969279e..0000000
--- a/leetcode/majority_element/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_majority_element, run_majority_element\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [3, 2, 3]\n",
- "expected = 3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_majority_element(Solution, nums)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_majority_element(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/majority_element/playground.py b/leetcode/majority_element/playground.py
new file mode 100644
index 0000000..ac2bcd3
--- /dev/null
+++ b/leetcode/majority_element/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_majority_element, run_majority_element
+from solution import Solution
+
+# %%
+# Example test case
+nums = [3, 2, 3]
+expected = 3
+
+# %%
+result = run_majority_element(Solution, nums)
+result
+
+# %%
+assert_majority_element(result, expected)
diff --git a/leetcode/maximum_depth_of_binary_tree/playground.ipynb b/leetcode/maximum_depth_of_binary_tree/playground.ipynb
deleted file mode 100644
index 53406b7..0000000
--- a/leetcode/maximum_depth_of_binary_tree/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_max_depth, run_max_depth\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list = [3, 9, 20, None, None, 15, 7]\n",
- "expected = 3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_max_depth(Solution, root_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_max_depth(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/maximum_depth_of_binary_tree/playground.py b/leetcode/maximum_depth_of_binary_tree/playground.py
new file mode 100644
index 0000000..e2f6ebf
--- /dev/null
+++ b/leetcode/maximum_depth_of_binary_tree/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_max_depth, run_max_depth
+from solution import Solution
+
+# %%
+# Example test case
+root_list = [3, 9, 20, None, None, 15, 7]
+expected = 3
+
+# %%
+result = run_max_depth(Solution, root_list)
+result
+
+# %%
+assert_max_depth(result, expected)
diff --git a/leetcode/maximum_profit_in_job_scheduling/playground.ipynb b/leetcode/maximum_profit_in_job_scheduling/playground.ipynb
deleted file mode 100644
index cf2e659..0000000
--- a/leetcode/maximum_profit_in_job_scheduling/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_job_scheduling, run_job_scheduling\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "start_time = [1, 2, 3, 3]\n",
- "end_time = [3, 4, 5, 6]\n",
- "profit = [50, 10, 40, 70]\n",
- "expected = 120"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_job_scheduling(Solution, start_time, end_time, profit)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_job_scheduling(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/maximum_profit_in_job_scheduling/playground.py b/leetcode/maximum_profit_in_job_scheduling/playground.py
new file mode 100644
index 0000000..777d927
--- /dev/null
+++ b/leetcode/maximum_profit_in_job_scheduling/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_job_scheduling, run_job_scheduling
+from solution import Solution
+
+# %%
+# Example test case
+start_time = [1, 2, 3, 3]
+end_time = [3, 4, 5, 6]
+profit = [50, 10, 40, 70]
+expected = 120
+
+# %%
+result = run_job_scheduling(Solution, start_time, end_time, profit)
+result
+
+# %%
+assert_job_scheduling(result, expected)
diff --git a/leetcode/maximum_subarray/playground.ipynb b/leetcode/maximum_subarray/playground.ipynb
deleted file mode 100644
index bd4f64e..0000000
--- a/leetcode/maximum_subarray/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_max_sub_array, run_max_sub_array\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]\n",
- "expected = 6"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_max_sub_array(Solution, nums)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_max_sub_array(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/maximum_subarray/playground.py b/leetcode/maximum_subarray/playground.py
new file mode 100644
index 0000000..4c514a9
--- /dev/null
+++ b/leetcode/maximum_subarray/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_max_sub_array, run_max_sub_array
+from solution import Solution
+
+# %%
+# Example test case
+nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
+expected = 6
+
+# %%
+result = run_max_sub_array(Solution, nums)
+result
+
+# %%
+assert_max_sub_array(result, expected)
diff --git a/leetcode/merge_intervals/playground.ipynb b/leetcode/merge_intervals/playground.ipynb
deleted file mode 100644
index f5c7c1e..0000000
--- a/leetcode/merge_intervals/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_merge, run_merge\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "intervals = [[1, 3], [2, 6], [8, 10], [15, 18]]\n",
- "expected = [[1, 6], [8, 10], [15, 18]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_merge(Solution, intervals)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_merge(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/merge_intervals/playground.py b/leetcode/merge_intervals/playground.py
new file mode 100644
index 0000000..0c3c6b0
--- /dev/null
+++ b/leetcode/merge_intervals/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_merge, run_merge
+from solution import Solution
+
+# %%
+# Example test case
+intervals = [[1, 3], [2, 6], [8, 10], [15, 18]]
+expected = [[1, 6], [8, 10], [15, 18]]
+
+# %%
+result = run_merge(Solution, intervals)
+result
+
+# %%
+assert_merge(result, expected)
diff --git a/leetcode/merge_k_sorted_lists/playground.ipynb b/leetcode/merge_k_sorted_lists/playground.ipynb
deleted file mode 100644
index 44dff96..0000000
--- a/leetcode/merge_k_sorted_lists/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_merge_k_lists, run_merge_k_lists\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import ListNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "lists_data = [[1, 4, 5], [1, 3, 4], [2, 6]]\n",
- "expected_data = [1, 1, 2, 3, 4, 4, 5, 6]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_merge_k_lists(Solution, lists_data)\n",
- "ListNode[int].to_list(result) if result else []"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_merge_k_lists(result, expected_data)"
- ]
- }
- ],
- "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/merge_k_sorted_lists/playground.py b/leetcode/merge_k_sorted_lists/playground.py
new file mode 100644
index 0000000..f30a2ad
--- /dev/null
+++ b/leetcode/merge_k_sorted_lists/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_merge_k_lists, run_merge_k_lists
+from solution import Solution
+
+from leetcode_py import ListNode
+
+# %%
+# Example test case
+lists_data = [[1, 4, 5], [1, 3, 4], [2, 6]]
+expected_data = [1, 1, 2, 3, 4, 4, 5, 6]
+
+# %%
+result = run_merge_k_lists(Solution, lists_data)
+ListNode[int].to_list(result) if result else []
+
+# %%
+assert_merge_k_lists(result, expected_data)
diff --git a/leetcode/merge_two_sorted_lists/playground.ipynb b/leetcode/merge_two_sorted_lists/playground.ipynb
deleted file mode 100644
index 0ec2f71..0000000
--- a/leetcode/merge_two_sorted_lists/playground.ipynb
+++ /dev/null
@@ -1,71 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_merge_two_lists, run_merge_two_lists\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import ListNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "list1_vals = [1, 2, 4]\n",
- "list2_vals = [1, 3, 4]\n",
- "expected_vals = [1, 1, 2, 3, 4, 4]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_merge_two_lists(Solution, list1_vals, list2_vals)\n",
- "ListNode[int].to_list(result) if result else []"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_merge_two_lists(result, expected_vals)"
- ]
- }
- ],
- "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/merge_two_sorted_lists/playground.py b/leetcode/merge_two_sorted_lists/playground.py
new file mode 100644
index 0000000..2d47603
--- /dev/null
+++ b/leetcode/merge_two_sorted_lists/playground.py
@@ -0,0 +1,33 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_merge_two_lists, run_merge_two_lists
+from solution import Solution
+
+from leetcode_py import ListNode
+
+# %%
+# Example test case
+list1_vals = [1, 2, 4]
+list2_vals = [1, 3, 4]
+expected_vals = [1, 1, 2, 3, 4, 4]
+
+# %%
+result = run_merge_two_lists(Solution, list1_vals, list2_vals)
+ListNode[int].to_list(result) if result else []
+
+# %%
+assert_merge_two_lists(result, expected_vals)
diff --git a/leetcode/middle_of_the_linked_list/playground.ipynb b/leetcode/middle_of_the_linked_list/playground.ipynb
deleted file mode 100644
index d078f51..0000000
--- a/leetcode/middle_of_the_linked_list/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_middle_node, run_middle_node\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import ListNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "head_list = [1, 2, 3, 4, 5]\n",
- "expected_list = [3, 4, 5]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_middle_node(Solution, head_list)\n",
- "ListNode[int].to_list(result) if result else []"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_middle_node(result, expected_list)"
- ]
- }
- ],
- "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/middle_of_the_linked_list/playground.py b/leetcode/middle_of_the_linked_list/playground.py
new file mode 100644
index 0000000..a81e5a1
--- /dev/null
+++ b/leetcode/middle_of_the_linked_list/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_middle_node, run_middle_node
+from solution import Solution
+
+from leetcode_py import ListNode
+
+# %%
+# Example test case
+head_list = [1, 2, 3, 4, 5]
+expected_list = [3, 4, 5]
+
+# %%
+result = run_middle_node(Solution, head_list)
+ListNode[int].to_list(result) if result else []
+
+# %%
+assert_middle_node(result, expected_list)
diff --git a/leetcode/min_stack/playground.ipynb b/leetcode/min_stack/playground.ipynb
deleted file mode 100644
index 0d24cc7..0000000
--- a/leetcode/min_stack/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_min_stack_operations, run_min_stack_operations\n",
- "from solution import MinStack"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "operations = [\"MinStack\", \"push\", \"push\", \"push\", \"getMin\", \"pop\", \"top\", \"getMin\"]\n",
- "inputs = [[], [-2], [0], [-3], [], [], [], []]\n",
- "expected = [None, None, None, None, -3, None, 0, -2]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_min_stack_operations(MinStack, operations, inputs)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_min_stack_operations(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/min_stack/playground.py b/leetcode/min_stack/playground.py
new file mode 100644
index 0000000..a331ae1
--- /dev/null
+++ b/leetcode/min_stack/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_min_stack_operations, run_min_stack_operations
+from solution import MinStack
+
+# %%
+# Example test case
+operations = ["MinStack", "push", "push", "push", "getMin", "pop", "top", "getMin"]
+inputs = [[], [-2], [0], [-3], [], [], [], []]
+expected = [None, None, None, None, -3, None, 0, -2]
+
+# %%
+result = run_min_stack_operations(MinStack, operations, inputs)
+result
+
+# %%
+assert_min_stack_operations(result, expected)
diff --git a/leetcode/minimum_height_trees/playground.ipynb b/leetcode/minimum_height_trees/playground.ipynb
deleted file mode 100644
index 8cf7734..0000000
--- a/leetcode/minimum_height_trees/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_find_min_height_trees, run_find_min_height_trees\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "n = 4\n",
- "edges = [[1, 0], [1, 2], [1, 3]]\n",
- "expected = [1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_find_min_height_trees(Solution, n, edges)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_find_min_height_trees(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/minimum_height_trees/playground.py b/leetcode/minimum_height_trees/playground.py
new file mode 100644
index 0000000..32fdfbd
--- /dev/null
+++ b/leetcode/minimum_height_trees/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_find_min_height_trees, run_find_min_height_trees
+from solution import Solution
+
+# %%
+# Example test case
+n = 4
+edges = [[1, 0], [1, 2], [1, 3]]
+expected = [1]
+
+# %%
+result = run_find_min_height_trees(Solution, n, edges)
+result
+
+# %%
+assert_find_min_height_trees(result, expected)
diff --git a/leetcode/minimum_window_substring/playground.ipynb b/leetcode/minimum_window_substring/playground.ipynb
deleted file mode 100644
index c35e737..0000000
--- a/leetcode/minimum_window_substring/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_min_window, run_min_window\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"ADOBECODEBANC\"\n",
- "t = \"ABC\"\n",
- "expected = \"BANC\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_min_window(Solution, s, t)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_min_window(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/minimum_window_substring/playground.py b/leetcode/minimum_window_substring/playground.py
new file mode 100644
index 0000000..89b19b0
--- /dev/null
+++ b/leetcode/minimum_window_substring/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_min_window, run_min_window
+from solution import Solution
+
+# %%
+# Example test case
+s = "ADOBECODEBANC"
+t = "ABC"
+expected = "BANC"
+
+# %%
+result = run_min_window(Solution, s, t)
+result
+
+# %%
+assert_min_window(result, expected)
diff --git a/leetcode/number_of_islands/playground.ipynb b/leetcode/number_of_islands/playground.ipynb
deleted file mode 100644
index 57ebc3f..0000000
--- a/leetcode/number_of_islands/playground.ipynb
+++ /dev/null
@@ -1,73 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_num_islands, run_num_islands\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "grid = [\n",
- " [\"1\", \"1\", \"1\", \"1\", \"0\"],\n",
- " [\"1\", \"1\", \"0\", \"1\", \"0\"],\n",
- " [\"1\", \"1\", \"0\", \"0\", \"0\"],\n",
- " [\"0\", \"0\", \"0\", \"0\", \"0\"],\n",
- "]\n",
- "expected = 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_num_islands(Solution, grid)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_num_islands(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/number_of_islands/playground.py b/leetcode/number_of_islands/playground.py
new file mode 100644
index 0000000..8f12ebb
--- /dev/null
+++ b/leetcode/number_of_islands/playground.py
@@ -0,0 +1,35 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_num_islands, run_num_islands
+from solution import Solution
+
+# %%
+# Example test case
+grid = [
+ ["1", "1", "1", "1", "0"],
+ ["1", "1", "0", "1", "0"],
+ ["1", "1", "0", "0", "0"],
+ ["0", "0", "0", "0", "0"],
+]
+expected = 1
+
+# %%
+result = run_num_islands(Solution, grid)
+result
+
+# %%
+assert_num_islands(result, expected)
diff --git a/leetcode/partition_equal_subset_sum/playground.ipynb b/leetcode/partition_equal_subset_sum/playground.ipynb
deleted file mode 100644
index 5597f66..0000000
--- a/leetcode/partition_equal_subset_sum/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_can_partition, run_can_partition\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [1, 5, 11, 5]\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_can_partition(Solution, nums)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_can_partition(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/partition_equal_subset_sum/playground.py b/leetcode/partition_equal_subset_sum/playground.py
new file mode 100644
index 0000000..9bf8361
--- /dev/null
+++ b/leetcode/partition_equal_subset_sum/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_can_partition, run_can_partition
+from solution import Solution
+
+# %%
+# Example test case
+nums = [1, 5, 11, 5]
+expected = True
+
+# %%
+result = run_can_partition(Solution, nums)
+result
+
+# %%
+assert_can_partition(result, expected)
diff --git a/leetcode/partition_equal_subset_sum/test_solution.py b/leetcode/partition_equal_subset_sum/test_solution.py
index e826127..a480df5 100644
--- a/leetcode/partition_equal_subset_sum/test_solution.py
+++ b/leetcode/partition_equal_subset_sum/test_solution.py
@@ -3,7 +3,7 @@
from leetcode_py.test_utils import logged_test
from .helpers import assert_can_partition, run_can_partition
-from .solution import Solution
+from .solution import Solution, SolutionBitset
class TestPartitionEqualSubsetSum:
@@ -11,6 +11,7 @@ def setup_method(self):
self.solution = Solution()
@logged_test
+ @pytest.mark.parametrize("solution_class", [Solution, SolutionBitset])
@pytest.mark.parametrize(
"nums, expected",
[
@@ -31,6 +32,6 @@ def setup_method(self):
([4, 4, 4, 4, 4, 4], True),
],
)
- def test_can_partition(self, nums: list[int], expected: bool):
- result = run_can_partition(Solution, nums)
+ def test_can_partition(self, solution_class: type, nums: list[int], expected: bool):
+ result = run_can_partition(solution_class, nums)
assert_can_partition(result, expected)
diff --git a/leetcode/permutations/playground.ipynb b/leetcode/permutations/playground.ipynb
deleted file mode 100644
index 3df2f29..0000000
--- a/leetcode/permutations/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_permute, run_permute\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [1, 2, 3]\n",
- "expected = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_permute(Solution, nums)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_permute(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/permutations/playground.py b/leetcode/permutations/playground.py
new file mode 100644
index 0000000..07de7dd
--- /dev/null
+++ b/leetcode/permutations/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_permute, run_permute
+from solution import Solution
+
+# %%
+# Example test case
+nums = [1, 2, 3]
+expected = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
+
+# %%
+result = run_permute(Solution, nums)
+result
+
+# %%
+assert_permute(result, expected)
diff --git a/leetcode/product_of_array_except_self/playground.ipynb b/leetcode/product_of_array_except_self/playground.ipynb
deleted file mode 100644
index c96f1f3..0000000
--- a/leetcode/product_of_array_except_self/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_product_except_self, run_product_except_self\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [1, 2, 3, 4]\n",
- "expected = [24, 12, 8, 6]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_product_except_self(Solution, nums)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_product_except_self(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/product_of_array_except_self/playground.py b/leetcode/product_of_array_except_self/playground.py
new file mode 100644
index 0000000..f8a43ad
--- /dev/null
+++ b/leetcode/product_of_array_except_self/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_product_except_self, run_product_except_self
+from solution import Solution
+
+# %%
+# Example test case
+nums = [1, 2, 3, 4]
+expected = [24, 12, 8, 6]
+
+# %%
+result = run_product_except_self(Solution, nums)
+result
+
+# %%
+assert_product_except_self(result, expected)
diff --git a/leetcode/ransom_note/playground.ipynb b/leetcode/ransom_note/playground.ipynb
deleted file mode 100644
index 5982636..0000000
--- a/leetcode/ransom_note/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_can_construct, run_can_construct\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "ransom_note = \"aa\"\n",
- "magazine = \"aab\"\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_can_construct(Solution, ransom_note, magazine)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_can_construct(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/ransom_note/playground.py b/leetcode/ransom_note/playground.py
new file mode 100644
index 0000000..86cbb15
--- /dev/null
+++ b/leetcode/ransom_note/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_can_construct, run_can_construct
+from solution import Solution
+
+# %%
+# Example test case
+ransom_note = "aa"
+magazine = "aab"
+expected = True
+
+# %%
+result = run_can_construct(Solution, ransom_note, magazine)
+result
+
+# %%
+assert_can_construct(result, expected)
diff --git a/leetcode/reverse_linked_list/playground.ipynb b/leetcode/reverse_linked_list/playground.ipynb
deleted file mode 100644
index b6a4171..0000000
--- a/leetcode/reverse_linked_list/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_reverse_list, run_reverse_list\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import ListNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "head_list = [1, 2, 3, 4, 5]\n",
- "expected_list = [5, 4, 3, 2, 1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_reverse_list(Solution, head_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_reverse_list(result, expected_list)"
- ]
- }
- ],
- "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/reverse_linked_list/playground.py b/leetcode/reverse_linked_list/playground.py
new file mode 100644
index 0000000..375048c
--- /dev/null
+++ b/leetcode/reverse_linked_list/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_reverse_list, run_reverse_list
+from solution import Solution
+
+# %%
+# Example test case
+head_list = [1, 2, 3, 4, 5]
+expected_list = [5, 4, 3, 2, 1]
+
+# %%
+result = run_reverse_list(Solution, head_list)
+result
+
+# %%
+assert_reverse_list(result, expected_list)
diff --git a/leetcode/reverse_linked_list_ii/playground.ipynb b/leetcode/reverse_linked_list_ii/playground.ipynb
deleted file mode 100644
index 0cd88a4..0000000
--- a/leetcode/reverse_linked_list_ii/playground.ipynb
+++ /dev/null
@@ -1,71 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_reverse_between, run_reverse_between\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import ListNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "head_list = [1, 2, 3, 4, 5]\n",
- "left, right = 2, 4\n",
- "expected_list = [1, 4, 3, 2, 5]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_reverse_between(Solution, head_list, left, right)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_reverse_between(result, expected_list)"
- ]
- }
- ],
- "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/reverse_linked_list_ii/playground.py b/leetcode/reverse_linked_list_ii/playground.py
new file mode 100644
index 0000000..0ee9f36
--- /dev/null
+++ b/leetcode/reverse_linked_list_ii/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_reverse_between, run_reverse_between
+from solution import Solution
+
+# %%
+# Example test case
+head_list = [1, 2, 3, 4, 5]
+left, right = 2, 4
+expected_list = [1, 4, 3, 2, 5]
+
+# %%
+result = run_reverse_between(Solution, head_list, left, right)
+result
+
+# %%
+assert_reverse_between(result, expected_list)
diff --git a/leetcode/rotting_oranges/playground.ipynb b/leetcode/rotting_oranges/playground.ipynb
deleted file mode 100644
index fde0cf1..0000000
--- a/leetcode/rotting_oranges/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_oranges_rotting, run_oranges_rotting\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "grid = [[2, 1, 1], [1, 1, 0], [0, 1, 1]]\n",
- "expected = 4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_oranges_rotting(Solution, grid)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_oranges_rotting(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/rotting_oranges/playground.py b/leetcode/rotting_oranges/playground.py
new file mode 100644
index 0000000..7f1f44e
--- /dev/null
+++ b/leetcode/rotting_oranges/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_oranges_rotting, run_oranges_rotting
+from solution import Solution
+
+# %%
+# Example test case
+grid = [[2, 1, 1], [1, 1, 0], [0, 1, 1]]
+expected = 4
+
+# %%
+result = run_oranges_rotting(Solution, grid)
+result
+
+# %%
+assert_oranges_rotting(result, expected)
diff --git a/leetcode/search_in_rotated_sorted_array/playground.ipynb b/leetcode/search_in_rotated_sorted_array/playground.ipynb
deleted file mode 100644
index 6dadf29..0000000
--- a/leetcode/search_in_rotated_sorted_array/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_search, run_search\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [4, 5, 6, 7, 0, 1, 2]\n",
- "target = 0\n",
- "expected = 4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_search(Solution, nums, target)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_search(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/search_in_rotated_sorted_array/playground.py b/leetcode/search_in_rotated_sorted_array/playground.py
new file mode 100644
index 0000000..1c72b5a
--- /dev/null
+++ b/leetcode/search_in_rotated_sorted_array/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_search, run_search
+from solution import Solution
+
+# %%
+# Example test case
+nums = [4, 5, 6, 7, 0, 1, 2]
+target = 0
+expected = 4
+
+# %%
+result = run_search(Solution, nums, target)
+result
+
+# %%
+assert_search(result, expected)
diff --git a/leetcode/serialize_and_deserialize_binary_tree/playground.ipynb b/leetcode/serialize_and_deserialize_binary_tree/playground.ipynb
deleted file mode 100644
index a1b0bf6..0000000
--- a/leetcode/serialize_and_deserialize_binary_tree/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_serialize_deserialize, run_serialize_deserialize\n",
- "from solution import Codec\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list = [1, 2, 3, None, None, 4, 5]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_serialize_deserialize(Codec, root_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_serialize_deserialize(result, root_list)"
- ]
- }
- ],
- "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/serialize_and_deserialize_binary_tree/playground.py b/leetcode/serialize_and_deserialize_binary_tree/playground.py
new file mode 100644
index 0000000..06cf1af
--- /dev/null
+++ b/leetcode/serialize_and_deserialize_binary_tree/playground.py
@@ -0,0 +1,29 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_serialize_deserialize, run_serialize_deserialize
+from solution import Codec
+
+# %%
+# Example test case
+root_list = [1, 2, 3, None, None, 4, 5]
+
+# %%
+result = run_serialize_deserialize(Codec, root_list)
+result
+
+# %%
+assert_serialize_deserialize(result, root_list)
diff --git a/leetcode/sort_colors/playground.ipynb b/leetcode/sort_colors/playground.ipynb
deleted file mode 100644
index b2f099f..0000000
--- a/leetcode/sort_colors/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_sort_colors, run_sort_colors\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [2, 0, 2, 1, 1, 0]\n",
- "expected = [0, 0, 1, 1, 2, 2]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_sort_colors(Solution, nums)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_sort_colors(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/sort_colors/playground.py b/leetcode/sort_colors/playground.py
new file mode 100644
index 0000000..9b2c154
--- /dev/null
+++ b/leetcode/sort_colors/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_sort_colors, run_sort_colors
+from solution import Solution
+
+# %%
+# Example test case
+nums = [2, 0, 2, 1, 1, 0]
+expected = [0, 0, 1, 1, 2, 2]
+
+# %%
+result = run_sort_colors(Solution, nums)
+result
+
+# %%
+assert_sort_colors(result, expected)
diff --git a/leetcode/spiral_matrix/playground.ipynb b/leetcode/spiral_matrix/playground.ipynb
deleted file mode 100644
index 0668a7e..0000000
--- a/leetcode/spiral_matrix/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_spiral_order, run_spiral_order\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]\n",
- "expected = [1, 2, 3, 6, 9, 8, 7, 4, 5]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_spiral_order(Solution, matrix)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_spiral_order(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/spiral_matrix/playground.py b/leetcode/spiral_matrix/playground.py
new file mode 100644
index 0000000..07f54ab
--- /dev/null
+++ b/leetcode/spiral_matrix/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_spiral_order, run_spiral_order
+from solution import Solution
+
+# %%
+# Example test case
+matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
+expected = [1, 2, 3, 6, 9, 8, 7, 4, 5]
+
+# %%
+result = run_spiral_order(Solution, matrix)
+result
+
+# %%
+assert_spiral_order(result, expected)
diff --git a/leetcode/string_to_integer_atoi/playground.ipynb b/leetcode/string_to_integer_atoi/playground.ipynb
deleted file mode 100644
index 82ecfb7..0000000
--- a/leetcode/string_to_integer_atoi/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_my_atoi, run_my_atoi\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"42\"\n",
- "expected = 42"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_my_atoi(Solution, s)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_my_atoi(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/string_to_integer_atoi/playground.py b/leetcode/string_to_integer_atoi/playground.py
new file mode 100644
index 0000000..c0656aa
--- /dev/null
+++ b/leetcode/string_to_integer_atoi/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_my_atoi, run_my_atoi
+from solution import Solution
+
+# %%
+# Example test case
+s = "42"
+expected = 42
+
+# %%
+result = run_my_atoi(Solution, s)
+result
+
+# %%
+assert_my_atoi(result, expected)
diff --git a/leetcode/task_scheduler/playground.ipynb b/leetcode/task_scheduler/playground.ipynb
deleted file mode 100644
index 3ad7d83..0000000
--- a/leetcode/task_scheduler/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_least_interval, run_least_interval\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "tasks = [\"A\", \"A\", \"A\", \"B\", \"B\", \"B\"]\n",
- "n = 2\n",
- "expected = 8"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_least_interval(Solution, tasks, n)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_least_interval(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/task_scheduler/playground.py b/leetcode/task_scheduler/playground.py
new file mode 100644
index 0000000..e0bcc11
--- /dev/null
+++ b/leetcode/task_scheduler/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_least_interval, run_least_interval
+from solution import Solution
+
+# %%
+# Example test case
+tasks = ["A", "A", "A", "B", "B", "B"]
+n = 2
+expected = 8
+
+# %%
+result = run_least_interval(Solution, tasks, n)
+result
+
+# %%
+assert_least_interval(result, expected)
diff --git a/leetcode/three_sum/playground.ipynb b/leetcode/three_sum/playground.ipynb
deleted file mode 100644
index ddbc41b..0000000
--- a/leetcode/three_sum/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_three_sum, run_three_sum\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [-1, 0, 1, 2, -1, -4]\n",
- "expected = [[-1, -1, 2], [-1, 0, 1]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_three_sum(Solution, nums)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_three_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/three_sum/playground.py b/leetcode/three_sum/playground.py
new file mode 100644
index 0000000..818263e
--- /dev/null
+++ b/leetcode/three_sum/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_three_sum, run_three_sum
+from solution import Solution
+
+# %%
+# Example test case
+nums = [-1, 0, 1, 2, -1, -4]
+expected = [[-1, -1, 2], [-1, 0, 1]]
+
+# %%
+result = run_three_sum(Solution, nums)
+result
+
+# %%
+assert_three_sum(result, expected)
diff --git a/leetcode/time_based_key_value_store/playground.ipynb b/leetcode/time_based_key_value_store/playground.ipynb
deleted file mode 100644
index 28f407a..0000000
--- a/leetcode/time_based_key_value_store/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_time_map_operations, run_time_map_operations\n",
- "from solution import TimeMap"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "operations = [\"TimeMap\", \"set\", \"get\", \"get\", \"set\", \"get\", \"get\"]\n",
- "inputs = [[], [\"foo\", \"bar\", 1], [\"foo\", 1], [\"foo\", 3], [\"foo\", \"bar2\", 4], [\"foo\", 4], [\"foo\", 5]]\n",
- "expected = [None, None, \"bar\", \"bar\", None, \"bar2\", \"bar2\"]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_time_map_operations(TimeMap, operations, inputs)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_time_map_operations(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/time_based_key_value_store/playground.py b/leetcode/time_based_key_value_store/playground.py
new file mode 100644
index 0000000..ead5892
--- /dev/null
+++ b/leetcode/time_based_key_value_store/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_time_map_operations, run_time_map_operations
+from solution import TimeMap
+
+# %%
+# Example test case
+operations = ["TimeMap", "set", "get", "get", "set", "get", "get"]
+inputs = [[], ["foo", "bar", 1], ["foo", 1], ["foo", 3], ["foo", "bar2", 4], ["foo", 4], ["foo", 5]]
+expected = [None, None, "bar", "bar", None, "bar2", "bar2"]
+
+# %%
+result = run_time_map_operations(TimeMap, operations, inputs)
+result
+
+# %%
+assert_time_map_operations(result, expected)
diff --git a/leetcode/trapping_rain_water/playground.ipynb b/leetcode/trapping_rain_water/playground.ipynb
deleted file mode 100644
index b4db37d..0000000
--- a/leetcode/trapping_rain_water/playground.ipynb
+++ /dev/null
@@ -1,91 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_trap, run_trap\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]\n",
- "expected = 6"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "6"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_trap(Solution, height)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_trap(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/trapping_rain_water/playground.py b/leetcode/trapping_rain_water/playground.py
new file mode 100644
index 0000000..749b303
--- /dev/null
+++ b/leetcode/trapping_rain_water/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_trap, run_trap
+from solution import Solution
+
+# %%
+# Example test case
+height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]
+expected = 6
+
+# %%
+result = run_trap(Solution, height)
+result
+
+# %%
+assert_trap(result, expected)
diff --git a/leetcode/two_sum/playground.ipynb b/leetcode/two_sum/playground.ipynb
deleted file mode 100644
index 1a6ec8b..0000000
--- a/leetcode/two_sum/playground.ipynb
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_two_sum, run_two_sum\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "nums = [2, 7, 11, 15]\n",
- "target = 9\n",
- "expected = [0, 1]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[0, 1]"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_two_sum(Solution, nums, target)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/two_sum/playground.py b/leetcode/two_sum/playground.py
new file mode 100644
index 0000000..79ef5d4
--- /dev/null
+++ b/leetcode/two_sum/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_two_sum, run_two_sum
+from solution import Solution
+
+# %%
+# Example test case
+nums = [2, 7, 11, 15]
+target = 9
+expected = [0, 1]
+
+# %%
+result = run_two_sum(Solution, nums, target)
+result
+
+# %%
+assert_two_sum(result, expected)
diff --git a/leetcode/valid_anagram/playground.ipynb b/leetcode/valid_anagram/playground.ipynb
deleted file mode 100644
index c178ebe..0000000
--- a/leetcode/valid_anagram/playground.ipynb
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_is_anagram, run_is_anagram\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"anagram\"\n",
- "t = \"nagaram\"\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_is_anagram(Solution, s, t)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_is_anagram(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/valid_anagram/playground.py b/leetcode/valid_anagram/playground.py
new file mode 100644
index 0000000..46bfe1d
--- /dev/null
+++ b/leetcode/valid_anagram/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_is_anagram, run_is_anagram
+from solution import Solution
+
+# %%
+# Example test case
+s = "anagram"
+t = "nagaram"
+expected = True
+
+# %%
+result = run_is_anagram(Solution, s, t)
+result
+
+# %%
+assert_is_anagram(result, expected)
diff --git a/leetcode/valid_palindrome/playground.ipynb b/leetcode/valid_palindrome/playground.ipynb
deleted file mode 100644
index c4c6bbc..0000000
--- a/leetcode/valid_palindrome/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_is_palindrome, run_is_palindrome\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"A man, a plan, a canal: Panama\"\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_is_palindrome(Solution, s)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_is_palindrome(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/valid_palindrome/playground.py b/leetcode/valid_palindrome/playground.py
new file mode 100644
index 0000000..64924c5
--- /dev/null
+++ b/leetcode/valid_palindrome/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_is_palindrome, run_is_palindrome
+from solution import Solution
+
+# %%
+# Example test case
+s = "A man, a plan, a canal: Panama"
+expected = True
+
+# %%
+result = run_is_palindrome(Solution, s)
+result
+
+# %%
+assert_is_palindrome(result, expected)
diff --git a/leetcode/valid_parentheses/playground.ipynb b/leetcode/valid_parentheses/playground.ipynb
deleted file mode 100644
index e5324f0..0000000
--- a/leetcode/valid_parentheses/playground.ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_is_valid, run_is_valid\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"()\"\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_is_valid(Solution, s)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_is_valid(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/valid_parentheses/playground.py b/leetcode/valid_parentheses/playground.py
new file mode 100644
index 0000000..7c64862
--- /dev/null
+++ b/leetcode/valid_parentheses/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_is_valid, run_is_valid
+from solution import Solution
+
+# %%
+# Example test case
+s = "()"
+expected = True
+
+# %%
+result = run_is_valid(Solution, s)
+result
+
+# %%
+assert_is_valid(result, expected)
diff --git a/leetcode/validate_binary_search_tree/playground.ipynb b/leetcode/validate_binary_search_tree/playground.ipynb
deleted file mode 100644
index a53e0f9..0000000
--- a/leetcode/validate_binary_search_tree/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_is_valid_bst, run_is_valid_bst\n",
- "from solution import Solution\n",
- "\n",
- "from leetcode_py import TreeNode"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "root_list = [2, 1, 3]\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_is_valid_bst(Solution, root_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_is_valid_bst(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/validate_binary_search_tree/playground.py b/leetcode/validate_binary_search_tree/playground.py
new file mode 100644
index 0000000..bd7fd3c
--- /dev/null
+++ b/leetcode/validate_binary_search_tree/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_is_valid_bst, run_is_valid_bst
+from solution import Solution
+
+# %%
+# Example test case
+root_list = [2, 1, 3]
+expected = True
+
+# %%
+result = run_is_valid_bst(Solution, root_list)
+result
+
+# %%
+assert_is_valid_bst(result, expected)
diff --git a/leetcode/validate_binary_search_tree/test_solution.py b/leetcode/validate_binary_search_tree/test_solution.py
index 8e5eca0..2491911 100644
--- a/leetcode/validate_binary_search_tree/test_solution.py
+++ b/leetcode/validate_binary_search_tree/test_solution.py
@@ -3,7 +3,7 @@
from leetcode_py.test_utils import logged_test
from .helpers import assert_is_valid_bst, run_is_valid_bst
-from .solution import Solution
+from .solution import Solution, SolutionBFS, SolutionDFS
class TestValidateBinarySearchTree:
@@ -11,6 +11,7 @@ def setup_method(self):
self.solution = Solution()
@logged_test
+ @pytest.mark.parametrize("solution_class", [Solution, SolutionDFS, SolutionBFS])
@pytest.mark.parametrize(
"root_list, expected",
[
@@ -28,6 +29,6 @@ def setup_method(self):
([3, 1, 5, 0, 2, 4, 6], True),
],
)
- def test_is_valid_bst(self, root_list: list[int | None], expected: bool):
- result = run_is_valid_bst(Solution, root_list)
+ def test_is_valid_bst(self, solution_class: type, root_list: list[int | None], expected: bool):
+ result = run_is_valid_bst(solution_class, root_list)
assert_is_valid_bst(result, expected)
diff --git a/leetcode/word_break/playground.ipynb b/leetcode/word_break/playground.ipynb
deleted file mode 100644
index b606647..0000000
--- a/leetcode/word_break/playground.ipynb
+++ /dev/null
@@ -1,69 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_word_break, run_word_break\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "s = \"leetcode\"\n",
- "word_dict = [\"leet\", \"code\"]\n",
- "expected = True"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_word_break(Solution, s, word_dict)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_word_break(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/word_break/playground.py b/leetcode/word_break/playground.py
new file mode 100644
index 0000000..4ee7af7
--- /dev/null
+++ b/leetcode/word_break/playground.py
@@ -0,0 +1,31 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_word_break, run_word_break
+from solution import Solution
+
+# %%
+# Example test case
+s = "leetcode"
+word_dict = ["leet", "code"]
+expected = True
+
+# %%
+result = run_word_break(Solution, s, word_dict)
+result
+
+# %%
+assert_word_break(result, expected)
diff --git a/leetcode/word_ladder/playground.ipynb b/leetcode/word_ladder/playground.ipynb
deleted file mode 100644
index 863eedf..0000000
--- a/leetcode/word_ladder/playground.ipynb
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_ladder_length, run_ladder_length\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "begin_word = \"hit\"\n",
- "end_word = \"cog\"\n",
- "word_list = [\"hot\", \"dot\", \"dog\", \"lot\", \"log\", \"cog\"]\n",
- "expected = 5"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "run",
- "metadata": {},
- "outputs": [],
- "source": [
- "result = run_ladder_length(Solution, begin_word, end_word, word_list)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "assert",
- "metadata": {},
- "outputs": [],
- "source": [
- "assert_ladder_length(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/word_ladder/playground.py b/leetcode/word_ladder/playground.py
new file mode 100644
index 0000000..a1dabdc
--- /dev/null
+++ b/leetcode/word_ladder/playground.py
@@ -0,0 +1,32 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_ladder_length, run_ladder_length
+from solution import Solution
+
+# %%
+# Example test case
+begin_word = "hit"
+end_word = "cog"
+word_list = ["hot", "dot", "dog", "lot", "log", "cog"]
+expected = 5
+
+# %%
+result = run_ladder_length(Solution, begin_word, end_word, word_list)
+result
+
+# %%
+assert_ladder_length(result, expected)
diff --git a/leetcode/zero_one_matrix/playground.ipynb b/leetcode/zero_one_matrix/playground.ipynb
deleted file mode 100644
index 6b3b709..0000000
--- a/leetcode/zero_one_matrix/playground.ipynb
+++ /dev/null
@@ -1,91 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "imports",
- "metadata": {},
- "outputs": [],
- "source": [
- "from helpers import assert_update_matrix, run_update_matrix\n",
- "from solution import Solution"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "setup",
- "metadata": {},
- "outputs": [],
- "source": [
- "# Example test case\n",
- "mat = [[0, 0, 0], [0, 1, 0], [1, 1, 1]]\n",
- "expected = [[0, 0, 0], [0, 1, 0], [1, 2, 1]]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "run",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "[[0, 0, 0], [0, 1, 0], [1, 2, 1]]"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "result = run_update_matrix(Solution, mat)\n",
- "result"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "assert",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "assert_update_matrix(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": "python",
- "pygments_lexer": "ipython3",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/leetcode/zero_one_matrix/playground.py b/leetcode/zero_one_matrix/playground.py
new file mode 100644
index 0000000..a727bed
--- /dev/null
+++ b/leetcode/zero_one_matrix/playground.py
@@ -0,0 +1,30 @@
+# ---
+# jupyter:
+# jupytext:
+# formats: ipynb,py:percent
+# text_representation:
+# extension: .py
+# format_name: percent
+# format_version: '1.3'
+# jupytext_version: 1.17.3
+# kernelspec:
+# display_name: leetcode-py-py3.13
+# language: python
+# name: python3
+# ---
+
+# %%
+from helpers import assert_update_matrix, run_update_matrix
+from solution import Solution
+
+# %%
+# Example test case
+mat = [[0, 0, 0], [0, 1, 0], [1, 1, 1]]
+expected = [[0, 0, 0], [0, 1, 0], [1, 2, 1]]
+
+# %%
+result = run_update_matrix(Solution, mat)
+result
+
+# %%
+assert_update_matrix(result, expected)
diff --git a/poetry.lock b/poetry.lock
index 54bb124..9f49b72 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -61,6 +61,26 @@ files = [
astroid = ["astroid (>=2,<4)"]
test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"]
+[[package]]
+name = "attrs"
+version = "25.3.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.8"
+groups = ["dev"]
+files = [
+ {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"},
+ {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"},
+]
+
+[package.extras]
+benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
+cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
+dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
+docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"]
+tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"]
+tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""]
+
[[package]]
name = "autopep8"
version = "2.3.2"
@@ -600,6 +620,21 @@ files = [
[package.extras]
tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich ; python_version >= \"3.11\""]
+[[package]]
+name = "fastjsonschema"
+version = "2.21.2"
+description = "Fastest Python implementation of JSON schema"
+optional = false
+python-versions = "*"
+groups = ["dev"]
+files = [
+ {file = "fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463"},
+ {file = "fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de"},
+]
+
+[package.extras]
+devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"]
+
[[package]]
name = "filelock"
version = "3.19.1"
@@ -806,6 +841,43 @@ MarkupSafe = ">=2.0"
[package.extras]
i18n = ["Babel (>=2.7)"]
+[[package]]
+name = "jsonschema"
+version = "4.25.1"
+description = "An implementation of JSON Schema validation for Python"
+optional = false
+python-versions = ">=3.9"
+groups = ["dev"]
+files = [
+ {file = "jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63"},
+ {file = "jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+jsonschema-specifications = ">=2023.03.6"
+referencing = ">=0.28.4"
+rpds-py = ">=0.7.1"
+
+[package.extras]
+format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
+format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"]
+
+[[package]]
+name = "jsonschema-specifications"
+version = "2025.9.1"
+description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry"
+optional = false
+python-versions = ">=3.9"
+groups = ["dev"]
+files = [
+ {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"},
+ {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"},
+]
+
+[package.dependencies]
+referencing = ">=0.31.0"
+
[[package]]
name = "jupyter-client"
version = "8.6.3"
@@ -850,6 +922,35 @@ traitlets = ">=5.3"
docs = ["intersphinx-registry", "myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-spelling", "traitlets"]
test = ["ipykernel", "pre-commit", "pytest (<9)", "pytest-cov", "pytest-timeout"]
+[[package]]
+name = "jupytext"
+version = "1.17.3"
+description = "Jupyter notebooks as Markdown documents, Julia, Python or R scripts"
+optional = false
+python-versions = ">=3.9"
+groups = ["dev"]
+files = [
+ {file = "jupytext-1.17.3-py3-none-any.whl", hash = "sha256:09b0a94cd904416e823a5ba9f41bd181031215b6fc682d2b5c18e68354feb17c"},
+ {file = "jupytext-1.17.3.tar.gz", hash = "sha256:8b6dae76d63c95cad47b493c38f0d9c74491fb621dcd0980abfcac4c8f168679"},
+]
+
+[package.dependencies]
+markdown-it-py = ">=1.0"
+mdit-py-plugins = "*"
+nbformat = "*"
+packaging = "*"
+pyyaml = "*"
+
+[package.extras]
+dev = ["autopep8", "black", "flake8", "gitpython", "ipykernel", "isort", "jupyter-fs[fs] (>=1.0)", "jupyter-server (!=2.11)", "nbconvert", "pre-commit", "pytest", "pytest-asyncio", "pytest-cov (>=2.6.1)", "pytest-randomly", "pytest-xdist", "sphinx", "sphinx-gallery (>=0.8)"]
+docs = ["myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"]
+test = ["pytest", "pytest-asyncio", "pytest-randomly", "pytest-xdist"]
+test-cov = ["black", "ipykernel", "jupyter-server (!=2.11)", "nbconvert", "pytest", "pytest-asyncio", "pytest-cov (>=2.6.1)", "pytest-randomly", "pytest-xdist"]
+test-external = ["autopep8", "black", "flake8", "gitpython", "ipykernel", "isort", "jupyter-fs[fs] (>=1.0)", "jupyter-server (!=2.11)", "nbconvert", "pre-commit", "pytest", "pytest-asyncio", "pytest-randomly", "pytest-xdist", "sphinx", "sphinx-gallery (>=0.8)"]
+test-functional = ["black", "pytest", "pytest-asyncio", "pytest-randomly", "pytest-xdist"]
+test-integration = ["black", "ipykernel", "jupyter-server (!=2.11)", "nbconvert", "pytest", "pytest-asyncio", "pytest-randomly", "pytest-xdist"]
+test-ui = ["bash-kernel"]
+
[[package]]
name = "loguru"
version = "0.7.3"
@@ -979,6 +1080,26 @@ files = [
[package.dependencies]
traitlets = "*"
+[[package]]
+name = "mdit-py-plugins"
+version = "0.5.0"
+description = "Collection of plugins for markdown-it-py"
+optional = false
+python-versions = ">=3.10"
+groups = ["dev"]
+files = [
+ {file = "mdit_py_plugins-0.5.0-py3-none-any.whl", hash = "sha256:07a08422fc1936a5d26d146759e9155ea466e842f5ab2f7d2266dd084c8dab1f"},
+ {file = "mdit_py_plugins-0.5.0.tar.gz", hash = "sha256:f4918cb50119f50446560513a8e311d574ff6aaed72606ddae6d35716fe809c6"},
+]
+
+[package.dependencies]
+markdown-it-py = ">=2.0.0,<5.0.0"
+
+[package.extras]
+code-style = ["pre-commit"]
+rtd = ["myst-parser", "sphinx-book-theme"]
+testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
+
[[package]]
name = "mdurl"
version = "0.1.2"
@@ -1063,6 +1184,28 @@ files = [
{file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"},
]
+[[package]]
+name = "nbformat"
+version = "5.10.4"
+description = "The Jupyter Notebook format"
+optional = false
+python-versions = ">=3.8"
+groups = ["dev"]
+files = [
+ {file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"},
+ {file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"},
+]
+
+[package.dependencies]
+fastjsonschema = ">=2.15"
+jsonschema = ">=2.6"
+jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0"
+traitlets = ">=5.1"
+
+[package.extras]
+docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"]
+test = ["pep440", "pre-commit", "pytest", "testpath"]
+
[[package]]
name = "nbqa"
version = "1.9.1"
@@ -1597,6 +1740,22 @@ files = [
[package.dependencies]
cffi = {version = "*", markers = "implementation_name == \"pypy\""}
+[[package]]
+name = "referencing"
+version = "0.36.2"
+description = "JSON Referencing + Python"
+optional = false
+python-versions = ">=3.9"
+groups = ["dev"]
+files = [
+ {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"},
+ {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+rpds-py = ">=0.7.0"
+
[[package]]
name = "requests"
version = "2.32.5"
@@ -1638,6 +1797,171 @@ pygments = ">=2.13.0,<3.0.0"
[package.extras]
jupyter = ["ipywidgets (>=7.5.1,<9)"]
+[[package]]
+name = "rpds-py"
+version = "0.27.1"
+description = "Python bindings to Rust's persistent data structures (rpds)"
+optional = false
+python-versions = ">=3.9"
+groups = ["dev"]
+files = [
+ {file = "rpds_py-0.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef"},
+ {file = "rpds_py-0.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9024de74731df54546fab0bfbcdb49fae19159ecaecfc8f37c18d2c7e2c0bd61"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31d3ebadefcd73b73928ed0b2fd696f7fefda8629229f81929ac9c1854d0cffb"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2e7f8f169d775dd9092a1743768d771f1d1300453ddfe6325ae3ab5332b4657"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d905d16f77eb6ab2e324e09bfa277b4c8e5e6b8a78a3e7ff8f3cdf773b4c013"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50c946f048209e6362e22576baea09193809f87687a95a8db24e5fbdb307b93a"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:3deab27804d65cd8289eb814c2c0e807c4b9d9916c9225e363cb0cf875eb67c1"},
+ {file = "rpds_py-0.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b61097f7488de4be8244c89915da8ed212832ccf1e7c7753a25a394bf9b1f10"},
+ {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a3f29aba6e2d7d90528d3c792555a93497fe6538aa65eb675b44505be747808"},
+ {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd6cd0485b7d347304067153a6dc1d73f7d4fd995a396ef32a24d24b8ac63ac8"},
+ {file = "rpds_py-0.27.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f4461bf931108c9fa226ffb0e257c1b18dc2d44cd72b125bec50ee0ab1248a9"},
+ {file = "rpds_py-0.27.1-cp310-cp310-win32.whl", hash = "sha256:ee5422d7fb21f6a00c1901bf6559c49fee13a5159d0288320737bbf6585bd3e4"},
+ {file = "rpds_py-0.27.1-cp310-cp310-win_amd64.whl", hash = "sha256:3e039aabf6d5f83c745d5f9a0a381d031e9ed871967c0a5c38d201aca41f3ba1"},
+ {file = "rpds_py-0.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881"},
+ {file = "rpds_py-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:abfa1171a9952d2e0002aba2ad3780820b00cc3d9c98c6630f2e93271501f66c"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b507d19f817ebaca79574b16eb2ae412e5c0835542c93fe9983f1e432aca195"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168b025f8fd8d8d10957405f3fdcef3dc20f5982d398f90851f4abc58c566c52"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb56c6210ef77caa58e16e8c17d35c63fe3f5b60fd9ba9d424470c3400bcf9ed"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:d252f2d8ca0195faa707f8eb9368955760880b2b42a8ee16d382bf5dd807f89a"},
+ {file = "rpds_py-0.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6e5e54da1e74b91dbc7996b56640f79b195d5925c2b78efaa8c5d53e1d88edde"},
+ {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ffce0481cc6e95e5b3f0a47ee17ffbd234399e6d532f394c8dce320c3b089c21"},
+ {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a205fdfe55c90c2cd8e540ca9ceba65cbe6629b443bc05db1f590a3db8189ff9"},
+ {file = "rpds_py-0.27.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:689fb5200a749db0415b092972e8eba85847c23885c8543a8b0f5c009b1a5948"},
+ {file = "rpds_py-0.27.1-cp311-cp311-win32.whl", hash = "sha256:3182af66048c00a075010bc7f4860f33913528a4b6fc09094a6e7598e462fe39"},
+ {file = "rpds_py-0.27.1-cp311-cp311-win_amd64.whl", hash = "sha256:b4938466c6b257b2f5c4ff98acd8128ec36b5059e5c8f8372d79316b1c36bb15"},
+ {file = "rpds_py-0.27.1-cp311-cp311-win_arm64.whl", hash = "sha256:2f57af9b4d0793e53266ee4325535a31ba48e2f875da81a9177c9926dfa60746"},
+ {file = "rpds_py-0.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ae2775c1973e3c30316892737b91f9283f9908e3cc7625b9331271eaaed7dc90"},
+ {file = "rpds_py-0.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2643400120f55c8a96f7c9d858f7be0c88d383cd4653ae2cf0d0c88f668073e5"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16323f674c089b0360674a4abd28d5042947d54ba620f72514d69be4ff64845e"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a1f4814b65eacac94a00fc9a526e3fdafd78e439469644032032d0d63de4881"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ba32c16b064267b22f1850a34051121d423b6f7338a12b9459550eb2096e7ec"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5c20f33fd10485b80f65e800bbe5f6785af510b9f4056c5a3c612ebc83ba6cb"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:466bfe65bd932da36ff279ddd92de56b042f2266d752719beb97b08526268ec5"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:41e532bbdcb57c92ba3be62c42e9f096431b4cf478da9bc3bc6ce5c38ab7ba7a"},
+ {file = "rpds_py-0.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f149826d742b406579466283769a8ea448eed82a789af0ed17b0cd5770433444"},
+ {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:80c60cfb5310677bd67cb1e85a1e8eb52e12529545441b43e6f14d90b878775a"},
+ {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7ee6521b9baf06085f62ba9c7a3e5becffbc32480d2f1b351559c001c38ce4c1"},
+ {file = "rpds_py-0.27.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a512c8263249a9d68cac08b05dd59d2b3f2061d99b322813cbcc14c3c7421998"},
+ {file = "rpds_py-0.27.1-cp312-cp312-win32.whl", hash = "sha256:819064fa048ba01b6dadc5116f3ac48610435ac9a0058bbde98e569f9e785c39"},
+ {file = "rpds_py-0.27.1-cp312-cp312-win_amd64.whl", hash = "sha256:d9199717881f13c32c4046a15f024971a3b78ad4ea029e8da6b86e5aa9cf4594"},
+ {file = "rpds_py-0.27.1-cp312-cp312-win_arm64.whl", hash = "sha256:33aa65b97826a0e885ef6e278fbd934e98cdcfed80b63946025f01e2f5b29502"},
+ {file = "rpds_py-0.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:e4b9fcfbc021633863a37e92571d6f91851fa656f0180246e84cbd8b3f6b329b"},
+ {file = "rpds_py-0.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1441811a96eadca93c517d08df75de45e5ffe68aa3089924f963c782c4b898cf"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55266dafa22e672f5a4f65019015f90336ed31c6383bd53f5e7826d21a0e0b83"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d78827d7ac08627ea2c8e02c9e5b41180ea5ea1f747e9db0915e3adf36b62dcf"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae92443798a40a92dc5f0b01d8a7c93adde0c4dc965310a29ae7c64d72b9fad2"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c46c9dd2403b66a2a3b9720ec4b74d4ab49d4fabf9f03dfdce2d42af913fe8d0"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2efe4eb1d01b7f5f1939f4ef30ecea6c6b3521eec451fb93191bf84b2a522418"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:15d3b4d83582d10c601f481eca29c3f138d44c92187d197aff663a269197c02d"},
+ {file = "rpds_py-0.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4ed2e16abbc982a169d30d1a420274a709949e2cbdef119fe2ec9d870b42f274"},
+ {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a75f305c9b013289121ec0f1181931975df78738cdf650093e6b86d74aa7d8dd"},
+ {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:67ce7620704745881a3d4b0ada80ab4d99df390838839921f99e63c474f82cf2"},
+ {file = "rpds_py-0.27.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9d992ac10eb86d9b6f369647b6a3f412fc0075cfd5d799530e84d335e440a002"},
+ {file = "rpds_py-0.27.1-cp313-cp313-win32.whl", hash = "sha256:4f75e4bd8ab8db624e02c8e2fc4063021b58becdbe6df793a8111d9343aec1e3"},
+ {file = "rpds_py-0.27.1-cp313-cp313-win_amd64.whl", hash = "sha256:f9025faafc62ed0b75a53e541895ca272815bec18abe2249ff6501c8f2e12b83"},
+ {file = "rpds_py-0.27.1-cp313-cp313-win_arm64.whl", hash = "sha256:ed10dc32829e7d222b7d3b93136d25a406ba9788f6a7ebf6809092da1f4d279d"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:92022bbbad0d4426e616815b16bc4127f83c9a74940e1ccf3cfe0b387aba0228"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:47162fdab9407ec3f160805ac3e154df042e577dd53341745fc7fb3f625e6d92"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb89bec23fddc489e5d78b550a7b773557c9ab58b7946154a10a6f7a214a48b2"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e48af21883ded2b3e9eb48cb7880ad8598b31ab752ff3be6457001d78f416723"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f5b7bd8e219ed50299e58551a410b64daafb5017d54bbe822e003856f06a802"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08f1e20bccf73b08d12d804d6e1c22ca5530e71659e6673bce31a6bb71c1e73f"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dc5dceeaefcc96dc192e3a80bbe1d6c410c469e97bdd47494a7d930987f18b2"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:d76f9cc8665acdc0c9177043746775aa7babbf479b5520b78ae4002d889f5c21"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134fae0e36022edad8290a6661edf40c023562964efea0cc0ec7f5d392d2aaef"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:eb11a4f1b2b63337cfd3b4d110af778a59aae51c81d195768e353d8b52f88081"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:13e608ac9f50a0ed4faec0e90ece76ae33b34c0e8656e3dceb9a7db994c692cd"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dd2135527aa40f061350c3f8f89da2644de26cd73e4de458e79606384f4f68e7"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-win32.whl", hash = "sha256:3020724ade63fe320a972e2ffd93b5623227e684315adce194941167fee02688"},
+ {file = "rpds_py-0.27.1-cp313-cp313t-win_amd64.whl", hash = "sha256:8ee50c3e41739886606388ba3ab3ee2aae9f35fb23f833091833255a31740797"},
+ {file = "rpds_py-0.27.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:acb9aafccaae278f449d9c713b64a9e68662e7799dbd5859e2c6b3c67b56d334"},
+ {file = "rpds_py-0.27.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b7fb801aa7f845ddf601c49630deeeccde7ce10065561d92729bfe81bd21fb33"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe0dd05afb46597b9a2e11c351e5e4283c741237e7f617ffb3252780cca9336a"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b6dfb0e058adb12d8b1d1b25f686e94ffa65d9995a5157afe99743bf7369d62b"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed090ccd235f6fa8bb5861684567f0a83e04f52dfc2e5c05f2e4b1309fcf85e7"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf876e79763eecf3e7356f157540d6a093cef395b65514f17a356f62af6cc136"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12ed005216a51b1d6e2b02a7bd31885fe317e45897de81d86dcce7d74618ffff"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:ee4308f409a40e50593c7e3bb8cbe0b4d4c66d1674a316324f0c2f5383b486f9"},
+ {file = "rpds_py-0.27.1-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b08d152555acf1f455154d498ca855618c1378ec810646fcd7c76416ac6dc60"},
+ {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:dce51c828941973a5684d458214d3a36fcd28da3e1875d659388f4f9f12cc33e"},
+ {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:c1476d6f29eb81aa4151c9a31219b03f1f798dc43d8af1250a870735516a1212"},
+ {file = "rpds_py-0.27.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3ce0cac322b0d69b63c9cdb895ee1b65805ec9ffad37639f291dd79467bee675"},
+ {file = "rpds_py-0.27.1-cp314-cp314-win32.whl", hash = "sha256:dfbfac137d2a3d0725758cd141f878bf4329ba25e34979797c89474a89a8a3a3"},
+ {file = "rpds_py-0.27.1-cp314-cp314-win_amd64.whl", hash = "sha256:a6e57b0abfe7cc513450fcf529eb486b6e4d3f8aee83e92eb5f1ef848218d456"},
+ {file = "rpds_py-0.27.1-cp314-cp314-win_arm64.whl", hash = "sha256:faf8d146f3d476abfee026c4ae3bdd9ca14236ae4e4c310cbd1cf75ba33d24a3"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:ba81d2b56b6d4911ce735aad0a1d4495e808b8ee4dc58715998741a26874e7c2"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:84f7d509870098de0e864cad0102711c1e24e9b1a50ee713b65928adb22269e4"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9e960fc78fecd1100539f14132425e1d5fe44ecb9239f8f27f079962021523e"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:62f85b665cedab1a503747617393573995dac4600ff51869d69ad2f39eb5e817"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fed467af29776f6556250c9ed85ea5a4dd121ab56a5f8b206e3e7a4c551e48ec"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2729615f9d430af0ae6b36cf042cb55c0936408d543fb691e1a9e36648fd35a"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b207d881a9aef7ba753d69c123a35d96ca7cb808056998f6b9e8747321f03b8"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:639fd5efec029f99b79ae47e5d7e00ad8a773da899b6309f6786ecaf22948c48"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fecc80cb2a90e28af8a9b366edacf33d7a91cbfe4c2c4544ea1246e949cfebeb"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:42a89282d711711d0a62d6f57d81aa43a1368686c45bc1c46b7f079d55692734"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:cf9931f14223de59551ab9d38ed18d92f14f055a5f78c1d8ad6493f735021bbb"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-win32.whl", hash = "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a"},
+ {file = "rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772"},
+ {file = "rpds_py-0.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c918c65ec2e42c2a78d19f18c553d77319119bf43aa9e2edf7fb78d624355527"},
+ {file = "rpds_py-0.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fea2b1a922c47c51fd07d656324531adc787e415c8b116530a1d29c0516c62d"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbf94c58e8e0cd6b6f38d8de67acae41b3a515c26169366ab58bdca4a6883bb8"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c2a8fed130ce946d5c585eddc7c8eeef0051f58ac80a8ee43bd17835c144c2cc"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:037a2361db72ee98d829bc2c5b7cc55598ae0a5e0ec1823a56ea99374cfd73c1"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5281ed1cc1d49882f9997981c88df1a22e140ab41df19071222f7e5fc4e72125"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fd50659a069c15eef8aa3d64bbef0d69fd27bb4a50c9ab4f17f83a16cbf8905"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:c4b676c4ae3921649a15d28ed10025548e9b561ded473aa413af749503c6737e"},
+ {file = "rpds_py-0.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:079bc583a26db831a985c5257797b2b5d3affb0386e7ff886256762f82113b5e"},
+ {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4e44099bd522cba71a2c6b97f68e19f40e7d85399de899d66cdb67b32d7cb786"},
+ {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e202e6d4188e53c6661af813b46c37ca2c45e497fc558bacc1a7630ec2695aec"},
+ {file = "rpds_py-0.27.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f41f814b8eaa48768d1bb551591f6ba45f87ac76899453e8ccd41dba1289b04b"},
+ {file = "rpds_py-0.27.1-cp39-cp39-win32.whl", hash = "sha256:9e71f5a087ead99563c11fdaceee83ee982fd39cf67601f4fd66cb386336ee52"},
+ {file = "rpds_py-0.27.1-cp39-cp39-win_amd64.whl", hash = "sha256:71108900c9c3c8590697244b9519017a400d9ba26a36c48381b3f64743a44aab"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7ba22cb9693df986033b91ae1d7a979bc399237d45fccf875b76f62bb9e52ddf"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b640501be9288c77738b5492b3fd3abc4ba95c50c2e41273c8a1459f08298d3"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb08b65b93e0c6dd70aac7f7890a9c0938d5ec71d5cb32d45cf844fb8ae47636"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d7ff07d696a7a38152ebdb8212ca9e5baab56656749f3d6004b34ab726b550b8"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb7c72262deae25366e3b6c0c0ba46007967aea15d1eea746e44ddba8ec58dcc"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b002cab05d6339716b03a4a3a2ce26737f6231d7b523f339fa061d53368c9d8"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23f6b69d1c26c4704fec01311963a41d7de3ee0570a84ebde4d544e5a1859ffc"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:530064db9146b247351f2a0250b8f00b289accea4596a033e94be2389977de71"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b90b0496570bd6b0321724a330d8b545827c4df2034b6ddfc5f5275f55da2ad"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879b0e14a2da6a1102a3fc8af580fc1ead37e6d6692a781bd8c83da37429b5ab"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:0d807710df3b5faa66c731afa162ea29717ab3be17bdc15f90f2d9f183da4059"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3adc388fc3afb6540aec081fa59e6e0d3908722771aa1e37ffe22b220a436f0b"},
+ {file = "rpds_py-0.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c796c0c1cc68cb08b0284db4229f5af76168172670c74908fdbd4b7d7f515819"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3c64d07e95606ec402a0a1c511fe003873fa6af630bda59bac77fac8b4318ebc"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93a2ed40de81bcff59aabebb626562d48332f3d028ca2036f1d23cbb52750be4"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:387ce8c44ae94e0ec50532d9cb0edce17311024c9794eb196b90e1058aadeb66"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aaf94f812c95b5e60ebaf8bfb1898a7d7cb9c1af5744d4a67fa47796e0465d4e"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:4848ca84d6ded9b58e474dfdbad4b8bfb450344c0551ddc8d958bf4b36aa837c"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bde09cbcf2248b73c7c323be49b280180ff39fadcfe04e7b6f54a678d02a7cf"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:94c44ee01fd21c9058f124d2d4f0c9dc7634bec93cd4b38eefc385dabe71acbf"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:df8b74962e35c9249425d90144e721eed198e6555a0e22a563d29fe4486b51f6"},
+ {file = "rpds_py-0.27.1-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dc23e6820e3b40847e2f4a7726462ba0cf53089512abe9ee16318c366494c17a"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa8933159edc50be265ed22b401125c9eebff3171f570258854dbce3ecd55475"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a50431bf02583e21bf273c71b89d710e7a710ad5e39c725b14e685610555926f"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78af06ddc7fe5cc0e967085a9115accee665fb912c22a3f54bad70cc65b05fe6"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70d0738ef8fee13c003b100c2fbd667ec4f133468109b3472d249231108283a3"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2f6fd8a1cea5bbe599b6e78a6e5ee08db434fc8ffea51ff201c8765679698b3"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8177002868d1426305bb5de1e138161c2ec9eb2d939be38291d7c431c4712df8"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:008b839781d6c9bf3b6a8984d1d8e56f0ec46dc56df61fd669c49b58ae800400"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:a55b9132bb1ade6c734ddd2759c8dc132aa63687d259e725221f106b83a0e485"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a46fdec0083a26415f11d5f236b79fa1291c32aaa4a17684d82f7017a1f818b1"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:8a63b640a7845f2bdd232eb0d0a4a2dd939bcdd6c57e6bb134526487f3160ec5"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:7e32721e5d4922deaaf963469d795d5bde6093207c52fec719bd22e5d1bedbc4"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:2c426b99a068601b5f4623573df7a7c3d72e87533a2dd2253353a03e7502566c"},
+ {file = "rpds_py-0.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4fc9b7fe29478824361ead6e14e4f5aed570d477e06088826537e202d25fe859"},
+ {file = "rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8"},
+]
+
[[package]]
name = "ruff"
version = "0.12.12"
@@ -1927,4 +2251,4 @@ dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"]
[metadata]
lock-version = "2.1"
python-versions = "^3.13"
-content-hash = "01523761e407eb4721a6ac25255a75913ec9eb170901cd8ad47a4dc31857fef4"
+content-hash = "9049da9f95908d67870adae3eb3a34cf3f62f9d7008f82d36958cc7dabfc4ab2"
diff --git a/pyproject.toml b/pyproject.toml
index 4dfd014..7306c4a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,6 +20,7 @@ cookiecutter = "^2.6.0"
graphviz = "^0.21"
ipykernel = "^6.30.1"
isort = "^6.0.1"
+jupytext = "^1.16.6"
mypy = "^1.17.1"
nbqa = "^1.9.1"
pre-commit = "^4.3.0"
diff --git a/scripts/shared b/scripts/shared
index d6e9580..0216476 160000
--- a/scripts/shared
+++ b/scripts/shared
@@ -1 +1 @@
-Subproject commit d6e9580673bd0b1b6908add1fc721ad6e3489f7f
+Subproject commit 021647623d9d0304e3e1004e34c766b987f79a25
diff --git a/sonar-project.properties b/sonar-project.properties
index cb6e2c2..bdfd507 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -8,7 +8,7 @@ sonar.projectVersion=1.0
sonar.sources=leetcode,leetcode_py
sonar.tests=leetcode
sonar.test.inclusions=**/tests.py
-sonar.exclusions=**/conftest.py,**/.templates/**,**/__pycache__/**,**/.venv/**
+sonar.exclusions=**/conftest.py,**/.templates/**,**/__pycache__/**,**/.venv/**,**/playground.py
# Python specific settings
sonar.python.version=3.13