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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .amazonq/rules/problem-creation.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ When user requests a problem by **number** or **name/slug**, the assistant will:
- Images provide crucial visual context, especially for tree and graph problems
- Always verify images are included in `readme_examples` and accessible
4. **Create** JSON file in `leetcode_py/cli/resources/leetcode/json/problems/{problem_name}.json`
5. **Update** Makefile with `PROBLEM ?= {problem_name}`
6. **Generate** problem structure using `make p-gen`
7. **Verify** with `make p-lint` - fix template issues in JSON if possible, or manually fix generated files if template limitations
8. **Iterate** if JSON fixes: re-run `make p-gen PROBLEM={problem_name} FORCE=1` and `make p-lint` until passes to ensure reproducibility
5. **Update tags.json5** - If user specifies tags, manually add problem name to corresponding tag arrays in `leetcode_py/cli/resources/leetcode/json/tags.json5`
6. **Update** Makefile with `PROBLEM ?= {problem_name}`
7. **Generate** problem structure using `make p-gen`
8. **Verify** with `make p-lint` - fix template issues in JSON if possible, or manually fix generated files if template limitations
9. **Iterate** if JSON fixes: re-run `make p-gen PROBLEM={problem_name} FORCE=1` and `make p-lint` until passes to ensure reproducibility

## Scraping Commands

Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/ci-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,24 @@ on:
pull_request:
types: [opened, synchronize, reopened]

env:
TARGET_PYTHON_VERSION: "3.13"

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- name: Set up Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: "3.13"
python-version: ${{ matrix.python-version }}

- name: Install Poetry
uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1.4.1
Expand All @@ -30,7 +37,7 @@ jobs:
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: .venv
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}

- name: Install dependencies
run: |
Expand Down Expand Up @@ -67,11 +74,13 @@ jobs:
run: make test

- name: SonarQube Scan
if: matrix.python-version == env.TARGET_PYTHON_VERSION
uses: SonarSource/sonarqube-scan-action@1a6d90ebcb0e6a6b1d87e37ba693fe453195ae25 # v5.3.1
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

- name: Upload coverage reports to Codecov
if: matrix.python-version == env.TARGET_PYTHON_VERSION
uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
with:
fail_ci_if_error: true
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PYTHON_VERSION = 3.13
PROBLEM ?= find_all_anagrams_in_a_string
PROBLEM ?= daily_temperatures
FORCE ?= 0
COMMA := ,

Expand Down Expand Up @@ -42,6 +42,7 @@ define lint_target
endef

lint:
poetry run python scripts/sort_tags.py
poetry sort
npx prettier --write "**/*.{ts,tsx,css,json,yaml,yml,md}"
$(call lint_target,.)
Expand Down
2 changes: 1 addition & 1 deletion leetcode/accounts_merge/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_accounts_merge, run_accounts_merge
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/add_binary/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_add_binary, run_add_binary
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/balanced_binary_tree/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_is_balanced, run_is_balanced
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/basic_calculator/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_calculate, run_calculate
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/best_time_to_buy_and_sell_stock/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_max_profit, run_max_profit
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/binary_search/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_search, run_search
from .solution import Solution
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_level_order, run_level_order
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/binary_tree_right_side_view/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_right_side_view, run_right_side_view
from .solution import Solution, SolutionBFS, SolutionDFS
Expand Down
2 changes: 1 addition & 1 deletion leetcode/climbing_stairs/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_climb_stairs, run_climb_stairs
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/clone_graph/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_clone_graph, run_clone_graph
from .solution import Solution, SolutionBFS, SolutionDFS
Expand Down
2 changes: 1 addition & 1 deletion leetcode/coin_change/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_coin_change, run_coin_change
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/combination_sum/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_combination_sum, run_combination_sum
from .solution import Solution
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_build_tree, run_build_tree
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/container_with_most_water/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_max_area, run_max_area
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/contains_duplicate/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_contains_duplicate, run_contains_duplicate
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/course_schedule/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_can_finish, run_can_finish
from .solution import Solution
Expand Down
46 changes: 46 additions & 0 deletions leetcode/daily_temperatures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Daily Temperatures

**Difficulty:** Medium
**Topics:** Array, Stack, Monotonic Stack
**Tags:** grind

**LeetCode:** [Problem 739](https://leetcode.com/problems/daily-temperatures/description/)

## Problem Description

Given an array of integers `temperatures` represents the daily temperatures, return an array `answer` such that `answer[i]` is the number of days you have to wait after the `ith` day to get a warmer temperature. If there is no future day for which this is possible, keep `answer[i] == 0` instead.

## Examples

### Example 1:

```
Input: temperatures = [73,74,75,71,69,72,76,73]
Output: [1,1,4,2,1,1,0,0]
```

**Explanation:**

- For input `[73,74,75,71,69,72,76,73]`, the output should be `[1,1,4,2,1,1,0,0]`.
- For example, the first temperature is 73. The next warmer temperature is 74, which is 1 day later, so we put 1.
- The second temperature is 74. The next warmer temperature is 75, which is 1 day later, so we put 1.
- The third temperature is 75. The next warmer temperature is 76, which is 4 days later, so we put 4.

### Example 2:

```
Input: temperatures = [30,40,50,60]
Output: [1,1,1,0]
```

### Example 3:

```
Input: temperatures = [30,60,90]
Output: [1,1,0]
```

## Constraints

- `1 <= temperatures.length <= 10^5`
- `30 <= temperatures[i] <= 100`
Empty file.
8 changes: 8 additions & 0 deletions leetcode/daily_temperatures/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
def run_daily_temperatures(solution_class: type, temperatures: list[int]):
implementation = solution_class()
return implementation.daily_temperatures(temperatures)


def assert_daily_temperatures(result: list[int], expected: list[int]) -> bool:
assert result == expected
return True
29 changes: 29 additions & 0 deletions leetcode/daily_temperatures/playground.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ---
# 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_daily_temperatures, run_daily_temperatures
from solution import Solution

# %%
# Example test case
temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
expected = [1, 1, 4, 2, 1, 1, 0, 0]

# %%
result = run_daily_temperatures(Solution, temperatures)
result

# %%
assert_daily_temperatures(result, expected)
15 changes: 15 additions & 0 deletions leetcode/daily_temperatures/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Solution:

# Time: O(n)
# Space: O(n)
def daily_temperatures(self, temperatures: list[int]) -> list[int]:
result = [0] * len(temperatures)
stack: list[int] = []

for i, temp in enumerate(temperatures):
while stack and temperatures[stack[-1]] < temp:
prev_index = stack.pop()
result[prev_index] = i - prev_index
stack.append(i)

return result
56 changes: 56 additions & 0 deletions leetcode/daily_temperatures/test_solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import pytest

from leetcode_py import logged_test

from .helpers import assert_daily_temperatures, run_daily_temperatures
from .solution import Solution


class TestDailyTemperatures:
def setup_method(self):
self.solution = Solution()

@logged_test
@pytest.mark.parametrize(
"temperatures, expected",
[
([73, 74, 75, 71, 69, 72, 76, 73], [1, 1, 4, 2, 1, 1, 0, 0]),
([30, 40, 50, 60], [1, 1, 1, 0]),
([30, 60, 90], [1, 1, 0]),
([89, 62, 70, 58, 47, 47, 46, 76, 100, 70], [8, 1, 5, 4, 3, 2, 1, 1, 0, 0]),
([55, 38, 53, 81, 61, 93, 97, 32, 43, 78], [3, 1, 1, 2, 1, 1, 0, 1, 1, 0]),
([34, 80, 80, 34, 34, 80, 80, 80, 80, 34], [1, 0, 0, 2, 1, 0, 0, 0, 0, 0]),
([73], [0]),
([100], [0]),
([30, 31, 32, 33, 34], [1, 1, 1, 1, 0]),
([90, 80, 70, 60, 50], [0, 0, 0, 0, 0]),
([50, 50, 50, 50], [0, 0, 0, 0]),
([30, 100, 30, 100], [1, 0, 1, 0]),
([75, 71, 69, 72, 76], [4, 2, 1, 1, 0]),
([40, 35, 32, 37, 50], [4, 2, 1, 1, 0]),
([30, 40, 50, 60, 70, 80, 90, 100], [1, 1, 1, 1, 1, 1, 1, 0]),
([30, 30], [0, 0]),
([100, 100], [0, 0]),
([30, 100], [1, 0]),
([100, 30], [0, 0]),
([30, 31, 100], [1, 1, 0]),
([30, 99, 100], [1, 1, 0]),
([50, 40, 60, 30, 70], [2, 1, 2, 1, 0]),
([60, 50, 70, 40, 80], [2, 1, 2, 1, 0]),
([40, 50, 60, 50, 40], [1, 1, 0, 0, 0]),
([30, 40, 50, 40, 30], [1, 1, 0, 0, 0]),
([60, 50, 40, 50, 60], [0, 3, 1, 1, 0]),
([70, 60, 50, 60, 70], [0, 3, 1, 1, 0]),
([45, 50, 40, 60, 55, 65], [1, 2, 1, 2, 1, 0]),
([35, 45, 30, 50, 40, 60], [1, 2, 1, 2, 1, 0]),
([30, 31, 32, 33, 34, 35, 36, 37, 38, 39], [1, 1, 1, 1, 1, 1, 1, 1, 1, 0]),
([50, 49, 48, 47, 46, 45, 44, 43, 42, 41], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
([40, 40, 50, 50, 60, 60], [2, 1, 2, 1, 0, 0]),
([60, 60, 50, 50, 40, 40], [0, 0, 0, 0, 0, 0]),
([30, 31, 30, 32], [1, 2, 1, 0]),
([99, 100, 99, 100], [1, 0, 1, 0]),
],
)
def test_daily_temperatures(self, temperatures: list[int], expected: list[int]):
result = run_daily_temperatures(Solution, temperatures)
assert_daily_temperatures(result, expected)
2 changes: 1 addition & 1 deletion leetcode/diagonal_traverse/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_find_diagonal_order, run_find_diagonal_order
from .solution import Solution, SolutionRowShift
Expand Down
2 changes: 1 addition & 1 deletion leetcode/diameter_of_binary_tree/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_diameter_of_binary_tree, run_diameter_of_binary_tree
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/evaluate_reverse_polish_notation/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_eval_rpn, run_eval_rpn
from .solution import Solution
Expand Down
2 changes: 1 addition & 1 deletion leetcode/find_all_anagrams_in_a_string/test_solution.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from leetcode_py.test_utils import logged_test
from leetcode_py import logged_test

from .helpers import assert_find_anagrams, run_find_anagrams
from .solution import Solution
Expand Down
Loading