Skip to content

Commit 19bb990

Browse files
Merge branch 'TheAlgorithms:master' into master
2 parents 3a07610 + 40f65e8 commit 19bb990

File tree

60 files changed

+826
-157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+826
-157
lines changed

.github/workflows/build.yml

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,24 @@ jobs:
1212
- uses: actions/checkout@v4
1313
- uses: actions/setup-python@v5
1414
with:
15-
python-version: 3.12
15+
python-version: 3.13
1616
allow-prereleases: true
1717
- uses: actions/cache@v4
1818
with:
1919
path: ~/.cache/pip
2020
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
2121
- name: Install dependencies
2222
run: |
23-
python -m pip install --upgrade pip setuptools six wheel
23+
python -m pip install --upgrade pip setuptools wheel
2424
python -m pip install pytest-cov -r requirements.txt
2525
- name: Run tests
2626
# TODO: #8818 Re-enable quantum tests
2727
run: pytest
2828
--ignore=quantum/q_fourier_transform.py
29+
--ignore=computer_vision/cnn_classification.py
30+
--ignore=dynamic_programming/k_means_clustering_tensorflow.py
31+
--ignore=machine_learning/lstm/lstm_prediction.py
32+
--ignore=neural_network/input_data.py
2933
--ignore=project_euler/
3034
--ignore=scripts/validate_solutions.py
3135
--cov-report=term-missing:skip-covered

.pre-commit-config.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ repos:
1616
- id: auto-walrus
1717

1818
- repo: https://github.com/astral-sh/ruff-pre-commit
19-
rev: v0.6.7
19+
rev: v0.6.8
2020
hooks:
2121
- id: ruff
2222
- id: ruff-format
@@ -42,7 +42,7 @@ repos:
4242
pass_filenames: false
4343

4444
- repo: https://github.com/abravalheri/validate-pyproject
45-
rev: v0.19
45+
rev: v0.20.2
4646
hooks:
4747
- id: validate-pyproject
4848

DIRECTORY.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
* [Rat In Maze](backtracking/rat_in_maze.py)
2323
* [Sudoku](backtracking/sudoku.py)
2424
* [Sum Of Subsets](backtracking/sum_of_subsets.py)
25+
* [Word Ladder](backtracking/word_ladder.py)
2526
* [Word Search](backtracking/word_search.py)
2627

2728
## Bit Manipulation
@@ -291,6 +292,13 @@
291292
* [Stack With Doubly Linked List](data_structures/stacks/stack_with_doubly_linked_list.py)
292293
* [Stack With Singly Linked List](data_structures/stacks/stack_with_singly_linked_list.py)
293294
* [Stock Span Problem](data_structures/stacks/stock_span_problem.py)
295+
* Suffix Tree
296+
* Example
297+
* [Example Usage](data_structures/suffix_tree/example/example_usage.py)
298+
* [Suffix Tree](data_structures/suffix_tree/suffix_tree.py)
299+
* [Suffix Tree Node](data_structures/suffix_tree/suffix_tree_node.py)
300+
* Tests
301+
* [Test Suffix Tree](data_structures/suffix_tree/tests/test_suffix_tree.py)
294302
* Trie
295303
* [Radix Tree](data_structures/trie/radix_tree.py)
296304
* [Trie](data_structures/trie/trie.py)
@@ -1336,7 +1344,6 @@
13361344
* [Get Ip Geolocation](web_programming/get_ip_geolocation.py)
13371345
* [Get Top Billionaires](web_programming/get_top_billionaires.py)
13381346
* [Get Top Hn Posts](web_programming/get_top_hn_posts.py)
1339-
* [Get User Tweets](web_programming/get_user_tweets.py)
13401347
* [Giphy](web_programming/giphy.py)
13411348
* [Instagram Crawler](web_programming/instagram_crawler.py)
13421349
* [Instagram Pic](web_programming/instagram_pic.py)

backtracking/word_break.py

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
Word Break Problem is a well-known problem in computer science.
3+
Given a string and a dictionary of words, the task is to determine if
4+
the string can be segmented into a sequence of one or more dictionary words.
5+
6+
Wikipedia: https://en.wikipedia.org/wiki/Word_break_problem
7+
"""
8+
9+
10+
def backtrack(input_string: str, word_dict: set[str], start: int) -> bool:
11+
"""
12+
Helper function that uses backtracking to determine if a valid
13+
word segmentation is possible starting from index 'start'.
14+
15+
Parameters:
16+
input_string (str): The input string to be segmented.
17+
word_dict (set[str]): A set of valid dictionary words.
18+
start (int): The starting index of the substring to be checked.
19+
20+
Returns:
21+
bool: True if a valid segmentation is possible, otherwise False.
22+
23+
Example:
24+
>>> backtrack("leetcode", {"leet", "code"}, 0)
25+
True
26+
27+
>>> backtrack("applepenapple", {"apple", "pen"}, 0)
28+
True
29+
30+
>>> backtrack("catsandog", {"cats", "dog", "sand", "and", "cat"}, 0)
31+
False
32+
"""
33+
34+
# Base case: if the starting index has reached the end of the string
35+
if start == len(input_string):
36+
return True
37+
38+
# Try every possible substring from 'start' to 'end'
39+
for end in range(start + 1, len(input_string) + 1):
40+
if input_string[start:end] in word_dict and backtrack(
41+
input_string, word_dict, end
42+
):
43+
return True
44+
45+
return False
46+
47+
48+
def word_break(input_string: str, word_dict: set[str]) -> bool:
49+
"""
50+
Determines if the input string can be segmented into a sequence of
51+
valid dictionary words using backtracking.
52+
53+
Parameters:
54+
input_string (str): The input string to segment.
55+
word_dict (set[str]): The set of valid words.
56+
57+
Returns:
58+
bool: True if the string can be segmented into valid words, otherwise False.
59+
60+
Example:
61+
>>> word_break("leetcode", {"leet", "code"})
62+
True
63+
64+
>>> word_break("applepenapple", {"apple", "pen"})
65+
True
66+
67+
>>> word_break("catsandog", {"cats", "dog", "sand", "and", "cat"})
68+
False
69+
"""
70+
71+
return backtrack(input_string, word_dict, 0)

backtracking/word_ladder.py

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
Word Ladder is a classic problem in computer science.
3+
The problem is to transform a start word into an end word
4+
by changing one letter at a time.
5+
Each intermediate word must be a valid word from a given list of words.
6+
The goal is to find a transformation sequence
7+
from the start word to the end word.
8+
9+
Wikipedia: https://en.wikipedia.org/wiki/Word_ladder
10+
"""
11+
12+
import string
13+
14+
15+
def backtrack(
16+
current_word: str, path: list[str], end_word: str, word_set: set[str]
17+
) -> list[str]:
18+
"""
19+
Helper function to perform backtracking to find the transformation
20+
from the current_word to the end_word.
21+
22+
Parameters:
23+
current_word (str): The current word in the transformation sequence.
24+
path (list[str]): The list of transformations from begin_word to current_word.
25+
end_word (str): The target word for transformation.
26+
word_set (set[str]): The set of valid words for transformation.
27+
28+
Returns:
29+
list[str]: The list of transformations from begin_word to end_word.
30+
Returns an empty list if there is no valid
31+
transformation from current_word to end_word.
32+
33+
Example:
34+
>>> backtrack("hit", ["hit"], "cog", {"hot", "dot", "dog", "lot", "log", "cog"})
35+
['hit', 'hot', 'dot', 'lot', 'log', 'cog']
36+
37+
>>> backtrack("hit", ["hit"], "cog", {"hot", "dot", "dog", "lot", "log"})
38+
[]
39+
40+
>>> backtrack("lead", ["lead"], "gold", {"load", "goad", "gold", "lead", "lord"})
41+
['lead', 'lead', 'load', 'goad', 'gold']
42+
43+
>>> backtrack("game", ["game"], "code", {"came", "cage", "code", "cade", "gave"})
44+
['game', 'came', 'cade', 'code']
45+
"""
46+
47+
# Base case: If the current word is the end word, return the path
48+
if current_word == end_word:
49+
return path
50+
51+
# Try all possible single-letter transformations
52+
for i in range(len(current_word)):
53+
for c in string.ascii_lowercase: # Try changing each letter
54+
transformed_word = current_word[:i] + c + current_word[i + 1 :]
55+
if transformed_word in word_set:
56+
word_set.remove(transformed_word)
57+
# Recur with the new word added to the path
58+
result = backtrack(
59+
transformed_word, [*path, transformed_word], end_word, word_set
60+
)
61+
if result: # valid transformation found
62+
return result
63+
word_set.add(transformed_word) # backtrack
64+
65+
return [] # No valid transformation found
66+
67+
68+
def word_ladder(begin_word: str, end_word: str, word_set: set[str]) -> list[str]:
69+
"""
70+
Solve the Word Ladder problem using Backtracking and return
71+
the list of transformations from begin_word to end_word.
72+
73+
Parameters:
74+
begin_word (str): The word from which the transformation starts.
75+
end_word (str): The target word for transformation.
76+
word_list (list[str]): The list of valid words for transformation.
77+
78+
Returns:
79+
list[str]: The list of transformations from begin_word to end_word.
80+
Returns an empty list if there is no valid transformation.
81+
82+
Example:
83+
>>> word_ladder("hit", "cog", ["hot", "dot", "dog", "lot", "log", "cog"])
84+
['hit', 'hot', 'dot', 'lot', 'log', 'cog']
85+
86+
>>> word_ladder("hit", "cog", ["hot", "dot", "dog", "lot", "log"])
87+
[]
88+
89+
>>> word_ladder("lead", "gold", ["load", "goad", "gold", "lead", "lord"])
90+
['lead', 'lead', 'load', 'goad', 'gold']
91+
92+
>>> word_ladder("game", "code", ["came", "cage", "code", "cade", "gave"])
93+
['game', 'came', 'cade', 'code']
94+
"""
95+
96+
if end_word not in word_set: # no valid transformation possible
97+
return []
98+
99+
# Perform backtracking starting from the begin_word
100+
return backtrack(begin_word, [begin_word], end_word, word_set)

computer_vision/haralick_descriptors.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def root_mean_square_error(original: np.ndarray, reference: np.ndarray) -> float
1919
>>> root_mean_square_error(np.array([1, 2, 3]), np.array([6, 4, 2]))
2020
3.1622776601683795
2121
"""
22-
return np.sqrt(((original - reference) ** 2).mean())
22+
return float(np.sqrt(((original - reference) ** 2).mean()))
2323

2424

2525
def normalize_image(
@@ -273,7 +273,7 @@ def haralick_descriptors(matrix: np.ndarray) -> list[float]:
273273
>>> morphological = opening_filter(binary)
274274
>>> mask_1 = binary_mask(gray, morphological)[0]
275275
>>> concurrency = matrix_concurrency(mask_1, (0, 1))
276-
>>> haralick_descriptors(concurrency)
276+
>>> [float(f) for f in haralick_descriptors(concurrency)]
277277
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
278278
"""
279279
# Function np.indices could be used for bigger input types,
@@ -335,7 +335,7 @@ def get_descriptors(
335335
return np.concatenate(descriptors, axis=None)
336336

337337

338-
def euclidean(point_1: np.ndarray, point_2: np.ndarray) -> np.float32:
338+
def euclidean(point_1: np.ndarray, point_2: np.ndarray) -> float:
339339
"""
340340
Simple method for calculating the euclidean distance between two points,
341341
with type np.ndarray.
@@ -346,7 +346,7 @@ def euclidean(point_1: np.ndarray, point_2: np.ndarray) -> np.float32:
346346
>>> euclidean(a, b)
347347
3.3166247903554
348348
"""
349-
return np.sqrt(np.sum(np.square(point_1 - point_2)))
349+
return float(np.sqrt(np.sum(np.square(point_1 - point_2))))
350350

351351

352352
def get_distances(descriptors: np.ndarray, base: int) -> list[tuple[int, float]]:

0 commit comments

Comments
 (0)