Skip to content
Open
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
6 changes: 3 additions & 3 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
new_release_published: ${{ steps.set-outputs.outputs.published }}
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0

Expand All @@ -39,7 +39,7 @@ jobs:
- id: release
name: Release
if: steps.check-release.outputs.has_existing == 'false'
uses: cycjimmy/semantic-release-action@ba330626c4750c19d8299de843f05c7aa5574f62 # v5.0.2
uses: cycjimmy/semantic-release-action@b12c8f6015dc215fe37bc154d4ad456dd3833c90 # v6.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down Expand Up @@ -68,7 +68,7 @@ jobs:
id-token: write
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

- name: Set up Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
submodules: recursive
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-test-reproducibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest

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

- name: Set up Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
python-version: ["3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

- name: Run Trivy dependency scan
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1
Expand All @@ -26,7 +26,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0

Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ repos:
- id: check-added-large-files
args: ["--maxkb=20000"]
- repo: https://github.com/gitleaks/gitleaks
rev: v8.29.1
rev: v8.30.0
hooks:
- name: gitleaks
id: gitleaks
Expand Down
32 changes: 32 additions & 0 deletions leetcode/palindrome_partitioning/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Palindrome Partitioning

**Difficulty:** Medium
**Topics:** String, Dynamic Programming, Backtracking
**Tags:** grind-75

**LeetCode:** [Problem 131](https://leetcode.com/problems/palindrome-partitioning/description/)

## Problem Description

Given a string `s`, partition `s` such that every substring of the partition is a **palindrome**. Return _all possible palindrome partitioning of `s`_.

## Examples

### Example 1:

```
Input: s = "aab"
Output: [["a","a","b"],["aa","b"]]
```

### Example 2:

```
Input: s = "a"
Output: [["a"]]
```

## Constraints

- `1 <= s.length <= 16`
- `s` contains only lowercase English letters.
Empty file.
15 changes: 15 additions & 0 deletions leetcode/palindrome_partitioning/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
def run_partition(solution_class: type, s: str):
implementation = solution_class()
return implementation.partition(s)


def assert_partition(result: list[list[str]], expected: list[list[str]]) -> bool:
# Sort inner lists and outer list for comparison
# Note: Inner lists are partitions (lists of strings), order of partitions doesn't matter
# Order of strings within a partition DOES matter (it must reconstruct s)
# But wait, the problem says "partition s", so the order of substrings must match the order in s.
# So we only need to sort the outer list of partitions.
result_sorted = sorted(result)
expected_sorted = sorted(expected)
assert result_sorted == expected_sorted
return True
29 changes: 29 additions & 0 deletions leetcode/palindrome_partitioning/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.18.1
# kernelspec:
# display_name: leetcode-py-py3.13
# language: python
# name: python3
# ---

# %%
from helpers import assert_partition, run_partition
from solution import Solution

# %%
# Example test case
s = "aab"
expected = [["a", "a", "b"], ["aa", "b"]]

# %%
result = run_partition(Solution, s)
result

# %%
assert_partition(result, expected)
22 changes: 22 additions & 0 deletions leetcode/palindrome_partitioning/solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Solution:
# Time: O(N * 2^N)
# Space: O(N)
def partition(self, s: str) -> list[list[str]]:
result: list[list[str]] = []
self._backtrack(s, 0, [], result)
return result

def _backtrack(self, s: str, start: int, path: list[str], result: list[list[str]]) -> None:
if start == len(s):
result.append(path[:])
return

for end in range(start + 1, len(s) + 1):
substring = s[start:end]
if self._is_palindrome(substring):
path.append(substring)
self._backtrack(s, end, path, result)
path.pop()

def _is_palindrome(self, s: str) -> bool:
return s == s[::-1]
33 changes: 33 additions & 0 deletions leetcode/palindrome_partitioning/test_solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import pytest

from leetcode_py import logged_test

from .helpers import assert_partition, run_partition
from .solution import Solution


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

@logged_test
@pytest.mark.parametrize(
"s, expected",
[
("aab", [["a", "a", "b"], ["aa", "b"]]),
("a", [["a"]]),
("ab", [["a", "b"]]),
("aa", [["a", "a"], ["aa"]]),
("abc", [["a", "b", "c"]]),
("aba", [["a", "b", "a"], ["aba"]]),
("aaa", [["a", "a", "a"], ["a", "aa"], ["aa", "a"], ["aaa"]]),
("abba", [["a", "b", "b", "a"], ["a", "bb", "a"], ["abba"]]),
("zz", [["z", "z"], ["zz"]]),
("efe", [["e", "f", "e"], ["efe"]]),
("xyx", [["x", "y", "x"], ["xyx"]]),
("noon", [["n", "o", "o", "n"], ["n", "oo", "n"], ["noon"]]),
],
)
def test_partition(self, s: str, expected: list[list[str]]):
result = run_partition(Solution, s)
assert_partition(result, expected)
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"problem_name": "palindrome_partitioning",
"solution_class_name": "Solution",
"problem_number": "131",
"problem_title": "Palindrome Partitioning",
"difficulty": "Medium",
"topics": "String, Dynamic Programming, Backtracking",
"readme_description": "Given a string `s`, partition `s` such that every substring of the partition is a **palindrome**. Return *all possible palindrome partitioning of `s`*.",
"_readme_examples": {
"list": [
{
"content": "```\nInput: s = \"aab\"\nOutput: [[\"a\",\"a\",\"b\"],[\"aa\",\"b\"]]\n```"
},
{
"content": "```\nInput: s = \"a\"\nOutput: [[\"a\"]]\n```"
}
]
},
"readme_constraints": "- `1 <= s.length <= 16`\n- `s` contains only lowercase English letters.",
"readme_additional": "",
"helpers_imports": "",
"helpers_content": "",
"helpers_run_name": "partition",
"helpers_run_signature": "(solution_class: type, s: str)",
"helpers_run_body": " implementation = solution_class()\n return implementation.partition(s)",
"helpers_assert_name": "partition",
"helpers_assert_signature": "(result: list[list[str]], expected: list[list[str]]) -> bool",
"helpers_assert_body": " # Sort inner lists and outer list for comparison\n # Note: Inner lists are partitions (lists of strings), order of partitions doesn't matter\n # Order of strings within a partition DOES matter (it must reconstruct s)\n # But wait, the problem says \"partition s\", so the order of substrings must match the order in s.\n # So we only need to sort the outer list of partitions.\n result_sorted = sorted(result)\n expected_sorted = sorted(expected)\n assert result_sorted == expected_sorted\n return True",
"solution_imports": "",
"solution_contents": "",
"solution_class_content": "",
"test_imports": "import pytest\nfrom leetcode_py import logged_test\nfrom .helpers import assert_partition, run_partition\nfrom .solution import Solution",
"test_content": "",
"test_class_name": "PalindromePartitioning",
"test_class_content": " def setup_method(self):\n self.solution = Solution()",
"_solution_methods": {
"list": [
{
"name": "partition",
"signature": "(self, s: str) -> list[list[str]]",
"body": " # TODO: Implement partition\n return []"
}
]
},
"_test_helper_methods": {
"list": [
{
"name": "setup_method",
"parameters": "",
"body": "self.solution = Solution()"
}
]
},
"_test_methods": {
"list": [
{
"name": "test_partition",
"signature": "(self, s: str, expected: list[list[str]])",
"parametrize": "s, expected",
"test_cases": {
"list": [
"('aab', [['a', 'a', 'b'], ['aa', 'b']])",
"('a', [['a']])",
"('ab', [['a', 'b']])",
"('aa', [['a', 'a'], ['aa']])",
"('abc', [['a', 'b', 'c']])",
"('aba', [['a', 'b', 'a'], ['aba']])",
"('aaa', [['a', 'a', 'a'], ['a', 'aa'], ['aa', 'a'], ['aaa']])",
"('abba', [['a', 'b', 'b', 'a'], ['a', 'bb', 'a'], ['abba']])",
"('zz', [['z', 'z'], ['zz']])",
"('efe', [['e', 'f', 'e'], ['efe']])",
"('xyx', [['x', 'y', 'x'], ['xyx']])",
"('noon', [['n', 'o', 'o', 'n'], ['n', 'oo', 'n'], ['noon']])"
]
},
"body": " result = run_partition(Solution, s)\n assert_partition(result, expected)"
}
]
},
"playground_imports": "from helpers import run_partition, assert_partition\nfrom solution import Solution",
"playground_setup": "# Example test case\ns = 'aab'\nexpected = [['a', 'a', 'b'], ['aa', 'b']]",
"playground_run": "result = run_partition(Solution, s)\nresult",
"playground_assert": "assert_partition(result, expected)"
}
52 changes: 26 additions & 26 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion scripts/shared