Skip to content

Commit af37248

Browse files
Merge pull request #5 from codewithme-py/feat/add-two-numbers-0002
added new automatization structure && problem solution & test 0002
2 parents acdeb77 + 2482aec commit af37248

15 files changed

Lines changed: 253 additions & 22 deletions

.pre-commit-config.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
repos:
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
rev: v0.9.4
4+
hooks:
5+
- id: ruff
6+
args: [--fix, --exit-non-zero-on-fix]
7+
8+
- repo: local
9+
hooks:
10+
- id: pytest
11+
name: pytest
12+
entry: pytest
13+
language: system
14+
pass_filenames: false
15+
always_run: true
16+
args: [tests/]

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.PHONY: problem
2+
problem:
3+
@if [ -z '$(filter-out problem,$(MAKECMDGOALS))']; then \
4+
echo 'Usage: make problem <problem_number>'; \
5+
exit 1; \
6+
fi
7+
@python scripts/create_problem.py $(filter-out problem,$(MAKECMDGOALS))

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ My clean, typed, and tested solutions to LeetCode problems (Python 3.10+).
3535

3636
### 💡 Что получает клонировавший:
3737
- ✅ Все решения на **Python ^3.10** с type hints
38-
- ✅ Тесты для каждой задачи (`pytest`)
39-
- ✅ Автоматическая проверка стиля (`ruff`)
38+
- ✅ Пре-коммит-хук для запуска тестов (`pytest`) & (`ruff`)
4039
- ✅ Автоматическое создание /feat ветки, файлов проблемы и теста
4140
- ✅ Генерация файлов с контентом: условие задачи, сниппеты кода и примеры тестов (fetch from LeetCode API)
4241
- ✅ Автообновляемый `README.md` с прогрессом и ссылками
@@ -53,11 +52,12 @@ My clean, typed, and tested solutions to LeetCode problems (Python 3.10+).
5352

5453
This repo provides a production-grade setup for LeetCode practice:
5554
- Typed, tested Python 3.10+ solutions
55+
- Pre-commit hook for running tests (`pytest`) & (`ruff`)
5656
- Automated README generation with progress bars
5757
- Automated creation of /feat branch, problem and test files
5858
- Automated generation of files with content: problem statement, code snippets, and test examples (fetch from LeetCode API)
5959
- Smart cache management: automatic weekly refresh or on-demand
60-
- Preconfigured CI (tests + linter) and CD (auto-update)
60+
- Preconfigured CI and CD (auto-update)
6161
- No manual work — just solve, commit, PR
6262

6363
⚠️ For proper README generation, internet access is required (to query LeetCode 'API' on first run).
@@ -78,7 +78,7 @@ cd LeetCode_solutions
7878

7979
#### 2. Создай и активируй виртуальное окружение
8080
```bash
81-
python -m venv .venv
81+
python3 -m venv .venv
8282
```
8383
Linux/Mac
8484
```bash
@@ -101,11 +101,11 @@ pytest && ruff check .
101101

102102
#### 5. Используй скрипт обновления README (опционально)
103103
```bash
104-
python scripts/update_readme.py
104+
python3 scripts/update_readme.py
105105
```
106106
Для принудительного обновления кэша задач используйте флаг `--force-refresh-cache`:
107107
```bash
108-
python scripts/update_readme.py --force-refresh-cache
108+
python3 scripts/update_readme.py --force-refresh-cache
109109
```
110110

111111
- Кэш задач обновляется автоматически раз в неделю (от даты изменения файла problems_cache.json). Для принудительного обновления кэша задач используйте флаг --force-refresh-cache:
@@ -118,7 +118,7 @@ python scripts/update_readme.py --force-refresh-cache
118118
#### 7. Используй скрипт → Решай новую задачу → делай push → PR → merge в main → CI/CD сделает всё остальное автоматически!
119119

120120
```bash
121-
python3 scripts/create_problem.py <номер_задачи>
121+
make problem <номер_задачи>
122122
```
123123

124124
1) Скрипт создает новую **/feat** ветку, а так же файлы решения и тестов минимизируя рутину

build/lib/solutions/__init__.py

Whitespace-only changes.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
try:
2+
ListNode
3+
except NameError:
4+
class ListNode:
5+
def __init__(self, val=0, next=None):
6+
self.val = val
7+
self.next = next
8+
9+
class Solution:
10+
def addTwoNumbers(
11+
self, l1: ListNode | None, l2: ListNode | None
12+
) -> ListNode | None:
13+
"""Add two numbers represented by linked lists."""
14+
dummy_head = ListNode(0)
15+
current = dummy_head
16+
carry = 0
17+
while l1 or l2 or carry:
18+
val1 = l1.val if l1 else 0
19+
val2 = l2.val if l2 else 0
20+
sum_val = val1 + val2 + carry
21+
carry = sum_val // 10
22+
current.next = ListNode(sum_val % 10)
23+
current = current.next
24+
if l1:
25+
l1 = l1.next
26+
if l2:
27+
l2 = l2.next
28+
return dummy_head.next
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Solution:
2+
def intToRoman(self, num: int) -> str:
3+
"""Convert integer to Roman numeral.
4+
Uses greedy algorithm with predefined value-symbol pairs including
5+
subtractive forms (IV, IX, XL, XC, CD, CM).
6+
Args:
7+
num: Integer in [1, 3999]
8+
Returns:
9+
Roman numeral string
10+
"""
11+
roman_pairs = [
12+
(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'),
13+
(90, 'XC'), (50, 'L'), (40, 'XL'), (10, 'X'),
14+
(9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')
15+
]
16+
result = []
17+
for value, symbol in roman_pairs:
18+
count, num = divmod(num, value)
19+
result.append(symbol * count)
20+
return ''.join(result)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Solution:
2+
def longestCommonPrefix(self, strs: list[str]) -> str:
3+
"""Find the longest common prefix string
4+
amongst an array of strings.
5+
"""
6+
if not strs:
7+
return ""
8+
9+
prefix = strs[0]
10+
for s in strs[1:]:
11+
while not s.startswith(prefix):
12+
prefix = prefix[:-1]
13+
if not prefix:
14+
return ""
15+
return prefix
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Solution:
2+
def isPalindrome(self, x: int) -> bool:
3+
"""Check if integer is a palindrome without string conversion.
4+
Negative numbers and trailing-zero numbers (except 0) are non-palindromic.
5+
Uses O(1) space by reversing half the number.
6+
Args:
7+
x: Integer in [-2^31, 2^31 - 1]
8+
Returns:
9+
True if x is palindrome, False otherwise
10+
"""
11+
if x < 0 or (x % 10 == 0 and x != 0):
12+
return False
13+
reversed_half = 0
14+
while x > reversed_half:
15+
reversed_half = reversed_half * 10 + (x % 10)
16+
x //= 10
17+
return x == reversed_half or x == reversed_half // 10
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class ListNode:
2+
def __init__(self, val: int = 0, next: 'ListNode | None' = None):
3+
self.val = val
4+
self.next = next
5+
6+
7+
class Solution:
8+
def deleteDuplicates(self, head: ListNode | None) -> ListNode | None:
9+
"""Remove all duplicates from a sorted linked list
10+
(keep only one occurrence).
11+
"""
12+
if not head:
13+
return None
14+
curr = head
15+
while curr.next:
16+
if curr.val == curr.next.val:
17+
curr.next = curr.next.next
18+
else:
19+
curr = curr.next
20+
return head
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class Solution:
2+
def romanToInt(self, s: str) -> int:
3+
"""Convert Roman numeral to integer.
4+
Handles subtractive notation (e.g. IV=4, IX=9).
5+
Assumes valid input per LeetCode constraints.
6+
Args:
7+
s: Roman numeral string (I, V, X, L, C, D, M)
8+
Returns:
9+
Integer value (1 to 3999)
10+
"""
11+
roman_values = {
12+
'I': 1,
13+
'V': 5,
14+
'X': 10,
15+
'L': 50,
16+
'C': 100,
17+
'D': 500,
18+
'M': 1000
19+
}
20+
total = 0
21+
for i in range(len(s)):
22+
if i + 1 < len(s) and roman_values[s[i]] < roman_values[s[i + 1]]:
23+
total -= roman_values[s[i]]
24+
else:
25+
total += roman_values[s[i]]
26+
return total

0 commit comments

Comments
 (0)