Skip to content

Commit 6f061da

Browse files
authored
Merge branch 'TheAlgorithms:master' into master
2 parents bda9834 + fcf82a1 commit 6f061da

File tree

4 files changed

+170
-1
lines changed

4 files changed

+170
-1
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ We want your work to be readable by others; therefore, we encourage you to note
9696

9797
```bash
9898
python3 -m pip install ruff # only required the first time
99-
ruff .
99+
ruff check
100100
```
101101

102102
- Original code submission require docstrings or comments to describe your work.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from collections.abc import Iterator
2+
3+
4+
def lexical_order(max_number: int) -> Iterator[int]:
5+
"""
6+
Generate numbers in lexical order from 1 to max_number.
7+
8+
>>> " ".join(map(str, lexical_order(13)))
9+
'1 10 11 12 13 2 3 4 5 6 7 8 9'
10+
>>> list(lexical_order(1))
11+
[1]
12+
>>> " ".join(map(str, lexical_order(20)))
13+
'1 10 11 12 13 14 15 16 17 18 19 2 20 3 4 5 6 7 8 9'
14+
>>> " ".join(map(str, lexical_order(25)))
15+
'1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 23 24 25 3 4 5 6 7 8 9'
16+
>>> list(lexical_order(12))
17+
[1, 10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9]
18+
"""
19+
20+
stack = [1]
21+
22+
while stack:
23+
num = stack.pop()
24+
if num > max_number:
25+
continue
26+
27+
yield num
28+
if (num % 10) != 9:
29+
stack.append(num + 1)
30+
31+
stack.append(num * 10)
32+
33+
34+
if __name__ == "__main__":
35+
from doctest import testmod
36+
37+
testmod()
38+
print(f"Numbers from 1 to 25 in lexical order: {list(lexical_order(26))}")

dynamic_programming/longest_common_subsequence.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@ def longest_common_subsequence(x: str, y: str):
2828
(2, 'ph')
2929
>>> longest_common_subsequence("computer", "food")
3030
(1, 'o')
31+
>>> longest_common_subsequence("", "abc") # One string is empty
32+
(0, '')
33+
>>> longest_common_subsequence("abc", "") # Other string is empty
34+
(0, '')
35+
>>> longest_common_subsequence("", "") # Both strings are empty
36+
(0, '')
37+
>>> longest_common_subsequence("abc", "def") # No common subsequence
38+
(0, '')
39+
>>> longest_common_subsequence("abc", "abc") # Identical strings
40+
(3, 'abc')
41+
>>> longest_common_subsequence("a", "a") # Single character match
42+
(1, 'a')
43+
>>> longest_common_subsequence("a", "b") # Single character no match
44+
(0, '')
45+
>>> longest_common_subsequence("abcdef", "ace") # Interleaved subsequence
46+
(3, 'ace')
47+
>>> longest_common_subsequence("ABCD", "ACBD") # No repeated characters
48+
(3, 'ABD')
3149
"""
3250
# find the length of strings
3351

searches/exponential_search.py

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Pure Python implementation of exponential search algorithm
5+
6+
For more information, see the Wikipedia page:
7+
https://en.wikipedia.org/wiki/Exponential_search
8+
9+
For doctests run the following command:
10+
python3 -m doctest -v exponential_search.py
11+
12+
For manual testing run:
13+
python3 exponential_search.py
14+
"""
15+
16+
from __future__ import annotations
17+
18+
19+
def binary_search_by_recursion(
20+
sorted_collection: list[int], item: int, left: int = 0, right: int = -1
21+
) -> int:
22+
"""Pure implementation of binary search algorithm in Python using recursion
23+
24+
Be careful: the collection must be ascending sorted otherwise, the result will be
25+
unpredictable.
26+
27+
:param sorted_collection: some ascending sorted collection with comparable items
28+
:param item: item value to search
29+
:param left: starting index for the search
30+
:param right: ending index for the search
31+
:return: index of the found item or -1 if the item is not found
32+
33+
Examples:
34+
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 0, 0, 4)
35+
0
36+
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 15, 0, 4)
37+
4
38+
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 5, 0, 4)
39+
1
40+
>>> binary_search_by_recursion([0, 5, 7, 10, 15], 6, 0, 4)
41+
-1
42+
"""
43+
if right < 0:
44+
right = len(sorted_collection) - 1
45+
if list(sorted_collection) != sorted(sorted_collection):
46+
raise ValueError("sorted_collection must be sorted in ascending order")
47+
if right < left:
48+
return -1
49+
50+
midpoint = left + (right - left) // 2
51+
52+
if sorted_collection[midpoint] == item:
53+
return midpoint
54+
elif sorted_collection[midpoint] > item:
55+
return binary_search_by_recursion(sorted_collection, item, left, midpoint - 1)
56+
else:
57+
return binary_search_by_recursion(sorted_collection, item, midpoint + 1, right)
58+
59+
60+
def exponential_search(sorted_collection: list[int], item: int) -> int:
61+
"""
62+
Pure implementation of an exponential search algorithm in Python.
63+
For more information, refer to:
64+
https://en.wikipedia.org/wiki/Exponential_search
65+
66+
Be careful: the collection must be ascending sorted, otherwise the result will be
67+
unpredictable.
68+
69+
:param sorted_collection: some ascending sorted collection with comparable items
70+
:param item: item value to search
71+
:return: index of the found item or -1 if the item is not found
72+
73+
The time complexity of this algorithm is O(log i) where i is the index of the item.
74+
75+
Examples:
76+
>>> exponential_search([0, 5, 7, 10, 15], 0)
77+
0
78+
>>> exponential_search([0, 5, 7, 10, 15], 15)
79+
4
80+
>>> exponential_search([0, 5, 7, 10, 15], 5)
81+
1
82+
>>> exponential_search([0, 5, 7, 10, 15], 6)
83+
-1
84+
"""
85+
if list(sorted_collection) != sorted(sorted_collection):
86+
raise ValueError("sorted_collection must be sorted in ascending order")
87+
88+
if sorted_collection[0] == item:
89+
return 0
90+
91+
bound = 1
92+
while bound < len(sorted_collection) and sorted_collection[bound] < item:
93+
bound *= 2
94+
95+
left = bound // 2
96+
right = min(bound, len(sorted_collection) - 1)
97+
return binary_search_by_recursion(sorted_collection, item, left, right)
98+
99+
100+
if __name__ == "__main__":
101+
import doctest
102+
103+
doctest.testmod()
104+
105+
# Manual testing
106+
user_input = input("Enter numbers separated by commas: ").strip()
107+
collection = sorted(int(item) for item in user_input.split(","))
108+
target = int(input("Enter a number to search for: "))
109+
result = exponential_search(sorted_collection=collection, item=target)
110+
if result == -1:
111+
print(f"{target} was not found in {collection}.")
112+
else:
113+
print(f"{target} was found at index {result} in {collection}.")

0 commit comments

Comments
 (0)