Skip to content

Commit 713d680

Browse files
authored
Merge branch 'TheAlgorithms:master' into master
2 parents d9cc40a + f614ed7 commit 713d680

17 files changed

+326
-500
lines changed

.github/workflows/build.yml

+2-4
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,9 @@ jobs:
2222
python -m pip install --upgrade pip setuptools six wheel
2323
python -m pip install pytest-cov -r requirements.txt
2424
- name: Run tests
25-
# See: #6591 for re-enabling tests on Python v3.11
25+
# TODO: #8818 Re-enable quantum tests
2626
run: pytest
27-
--ignore=computer_vision/cnn_classification.py
28-
--ignore=machine_learning/lstm/lstm_prediction.py
29-
--ignore=quantum/
27+
--ignore=quantum/q_fourier_transform.py
3028
--ignore=project_euler/
3129
--ignore=scripts/validate_solutions.py
3230
--cov-report=term-missing:skip-covered

.pre-commit-config.yaml

+3-3
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.0.274
19+
rev: v0.0.277
2020
hooks:
2121
- id: ruff
2222

@@ -33,7 +33,7 @@ repos:
3333
- tomli
3434

3535
- repo: https://github.com/tox-dev/pyproject-fmt
36-
rev: "0.12.0"
36+
rev: "0.13.0"
3737
hooks:
3838
- id: pyproject-fmt
3939

@@ -51,7 +51,7 @@ repos:
5151
- id: validate-pyproject
5252

5353
- repo: https://github.com/pre-commit/mirrors-mypy
54-
rev: v1.3.0
54+
rev: v1.4.1
5555
hooks:
5656
- id: mypy
5757
args:

DIRECTORY.md

+3-7
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
* [Minmax](backtracking/minmax.py)
3030
* [N Queens](backtracking/n_queens.py)
3131
* [N Queens Math](backtracking/n_queens_math.py)
32+
* [Power Sum](backtracking/power_sum.py)
3233
* [Rat In Maze](backtracking/rat_in_maze.py)
3334
* [Sudoku](backtracking/sudoku.py)
3435
* [Sum Of Subsets](backtracking/sum_of_subsets.py)
@@ -292,7 +293,7 @@
292293
* [Inversions](divide_and_conquer/inversions.py)
293294
* [Kth Order Statistic](divide_and_conquer/kth_order_statistic.py)
294295
* [Max Difference Pair](divide_and_conquer/max_difference_pair.py)
295-
* [Max Subarray Sum](divide_and_conquer/max_subarray_sum.py)
296+
* [Max Subarray](divide_and_conquer/max_subarray.py)
296297
* [Mergesort](divide_and_conquer/mergesort.py)
297298
* [Peak](divide_and_conquer/peak.py)
298299
* [Power](divide_and_conquer/power.py)
@@ -323,8 +324,7 @@
323324
* [Matrix Chain Order](dynamic_programming/matrix_chain_order.py)
324325
* [Max Non Adjacent Sum](dynamic_programming/max_non_adjacent_sum.py)
325326
* [Max Product Subarray](dynamic_programming/max_product_subarray.py)
326-
* [Max Sub Array](dynamic_programming/max_sub_array.py)
327-
* [Max Sum Contiguous Subsequence](dynamic_programming/max_sum_contiguous_subsequence.py)
327+
* [Max Subarray Sum](dynamic_programming/max_subarray_sum.py)
328328
* [Min Distance Up Bottom](dynamic_programming/min_distance_up_bottom.py)
329329
* [Minimum Coin Change](dynamic_programming/minimum_coin_change.py)
330330
* [Minimum Cost Path](dynamic_programming/minimum_cost_path.py)
@@ -522,7 +522,6 @@
522522
* [Xgboost Regressor](machine_learning/xgboost_regressor.py)
523523

524524
## Maths
525-
* [3N Plus 1](maths/3n_plus_1.py)
526525
* [Abs](maths/abs.py)
527526
* [Add](maths/add.py)
528527
* [Addition Without Arithmetic](maths/addition_without_arithmetic.py)
@@ -591,12 +590,10 @@
591590
* [Is Square Free](maths/is_square_free.py)
592591
* [Jaccard Similarity](maths/jaccard_similarity.py)
593592
* [Juggler Sequence](maths/juggler_sequence.py)
594-
* [Kadanes](maths/kadanes.py)
595593
* [Karatsuba](maths/karatsuba.py)
596594
* [Krishnamurthy Number](maths/krishnamurthy_number.py)
597595
* [Kth Lexicographic Permutation](maths/kth_lexicographic_permutation.py)
598596
* [Largest Of Very Large Numbers](maths/largest_of_very_large_numbers.py)
599-
* [Largest Subarray Sum](maths/largest_subarray_sum.py)
600597
* [Least Common Multiple](maths/least_common_multiple.py)
601598
* [Line Length](maths/line_length.py)
602599
* [Liouville Lambda](maths/liouville_lambda.py)
@@ -733,7 +730,6 @@
733730
* [Linear Congruential Generator](other/linear_congruential_generator.py)
734731
* [Lru Cache](other/lru_cache.py)
735732
* [Magicdiamondpattern](other/magicdiamondpattern.py)
736-
* [Maximum Subarray](other/maximum_subarray.py)
737733
* [Maximum Subsequence](other/maximum_subsequence.py)
738734
* [Nested Brackets](other/nested_brackets.py)
739735
* [Number Container System](other/number_container_system.py)

arithmetic_analysis/newton_raphson.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ def newton_raphson(
2525
"""
2626
x = a
2727
while True:
28-
x = Decimal(x) - (Decimal(eval(func)) / Decimal(eval(str(diff(func)))))
28+
x = Decimal(x) - (
29+
Decimal(eval(func)) / Decimal(eval(str(diff(func)))) # noqa: S307
30+
)
2931
# This number dictates the accuracy of the answer
30-
if abs(eval(func)) < precision:
32+
if abs(eval(func)) < precision: # noqa: S307
3133
return float(x)
3234

3335

backtracking/power_sum.py

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""
2+
Problem source: https://www.hackerrank.com/challenges/the-power-sum/problem
3+
Find the number of ways that a given integer X, can be expressed as the sum
4+
of the Nth powers of unique, natural numbers. For example, if X=13 and N=2.
5+
We have to find all combinations of unique squares adding up to 13.
6+
The only solution is 2^2+3^2. Constraints: 1<=X<=1000, 2<=N<=10.
7+
"""
8+
9+
from math import pow
10+
11+
12+
def backtrack(
13+
needed_sum: int,
14+
power: int,
15+
current_number: int,
16+
current_sum: int,
17+
solutions_count: int,
18+
) -> tuple[int, int]:
19+
"""
20+
>>> backtrack(13, 2, 1, 0, 0)
21+
(0, 1)
22+
>>> backtrack(100, 2, 1, 0, 0)
23+
(0, 3)
24+
>>> backtrack(100, 3, 1, 0, 0)
25+
(0, 1)
26+
>>> backtrack(800, 2, 1, 0, 0)
27+
(0, 561)
28+
>>> backtrack(1000, 10, 1, 0, 0)
29+
(0, 0)
30+
>>> backtrack(400, 2, 1, 0, 0)
31+
(0, 55)
32+
>>> backtrack(50, 1, 1, 0, 0)
33+
(0, 3658)
34+
"""
35+
if current_sum == needed_sum:
36+
# If the sum of the powers is equal to needed_sum, then we have a solution.
37+
solutions_count += 1
38+
return current_sum, solutions_count
39+
40+
i_to_n = int(pow(current_number, power))
41+
if current_sum + i_to_n <= needed_sum:
42+
# If the sum of the powers is less than needed_sum, then continue adding powers.
43+
current_sum += i_to_n
44+
current_sum, solutions_count = backtrack(
45+
needed_sum, power, current_number + 1, current_sum, solutions_count
46+
)
47+
current_sum -= i_to_n
48+
if i_to_n < needed_sum:
49+
# If the power of i is less than needed_sum, then try with the next power.
50+
current_sum, solutions_count = backtrack(
51+
needed_sum, power, current_number + 1, current_sum, solutions_count
52+
)
53+
return current_sum, solutions_count
54+
55+
56+
def solve(needed_sum: int, power: int) -> int:
57+
"""
58+
>>> solve(13, 2)
59+
1
60+
>>> solve(100, 2)
61+
3
62+
>>> solve(100, 3)
63+
1
64+
>>> solve(800, 2)
65+
561
66+
>>> solve(1000, 10)
67+
0
68+
>>> solve(400, 2)
69+
55
70+
>>> solve(50, 1)
71+
Traceback (most recent call last):
72+
...
73+
ValueError: Invalid input
74+
needed_sum must be between 1 and 1000, power between 2 and 10.
75+
>>> solve(-10, 5)
76+
Traceback (most recent call last):
77+
...
78+
ValueError: Invalid input
79+
needed_sum must be between 1 and 1000, power between 2 and 10.
80+
"""
81+
if not (1 <= needed_sum <= 1000 and 2 <= power <= 10):
82+
raise ValueError(
83+
"Invalid input\n"
84+
"needed_sum must be between 1 and 1000, power between 2 and 10."
85+
)
86+
87+
return backtrack(needed_sum, power, 1, 0, 0)[1] # Return the solutions_count
88+
89+
90+
if __name__ == "__main__":
91+
import doctest
92+
93+
doctest.testmod()

data_structures/queue/double_ended_queue.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class _Iterator:
5454
the current node of the iteration.
5555
"""
5656

57-
__slots__ = "_cur"
57+
__slots__ = ("_cur",)
5858

5959
def __init__(self, cur: Deque._Node | None) -> None:
6060
self._cur = cur

divide_and_conquer/max_subarray.py

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
"""
2+
The maximum subarray problem is the task of finding the continuous subarray that has the
3+
maximum sum within a given array of numbers. For example, given the array
4+
[-2, 1, -3, 4, -1, 2, 1, -5, 4], the contiguous subarray with the maximum sum is
5+
[4, -1, 2, 1], which has a sum of 6.
6+
7+
This divide-and-conquer algorithm finds the maximum subarray in O(n log n) time.
8+
"""
9+
from __future__ import annotations
10+
11+
import time
12+
from collections.abc import Sequence
13+
from random import randint
14+
15+
from matplotlib import pyplot as plt
16+
17+
18+
def max_subarray(
19+
arr: Sequence[float], low: int, high: int
20+
) -> tuple[int | None, int | None, float]:
21+
"""
22+
Solves the maximum subarray problem using divide and conquer.
23+
:param arr: the given array of numbers
24+
:param low: the start index
25+
:param high: the end index
26+
:return: the start index of the maximum subarray, the end index of the
27+
maximum subarray, and the maximum subarray sum
28+
29+
>>> nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
30+
>>> max_subarray(nums, 0, len(nums) - 1)
31+
(3, 6, 6)
32+
>>> nums = [2, 8, 9]
33+
>>> max_subarray(nums, 0, len(nums) - 1)
34+
(0, 2, 19)
35+
>>> nums = [0, 0]
36+
>>> max_subarray(nums, 0, len(nums) - 1)
37+
(0, 0, 0)
38+
>>> nums = [-1.0, 0.0, 1.0]
39+
>>> max_subarray(nums, 0, len(nums) - 1)
40+
(2, 2, 1.0)
41+
>>> nums = [-2, -3, -1, -4, -6]
42+
>>> max_subarray(nums, 0, len(nums) - 1)
43+
(2, 2, -1)
44+
>>> max_subarray([], 0, 0)
45+
(None, None, 0)
46+
"""
47+
if not arr:
48+
return None, None, 0
49+
if low == high:
50+
return low, high, arr[low]
51+
52+
mid = (low + high) // 2
53+
left_low, left_high, left_sum = max_subarray(arr, low, mid)
54+
right_low, right_high, right_sum = max_subarray(arr, mid + 1, high)
55+
cross_left, cross_right, cross_sum = max_cross_sum(arr, low, mid, high)
56+
if left_sum >= right_sum and left_sum >= cross_sum:
57+
return left_low, left_high, left_sum
58+
elif right_sum >= left_sum and right_sum >= cross_sum:
59+
return right_low, right_high, right_sum
60+
return cross_left, cross_right, cross_sum
61+
62+
63+
def max_cross_sum(
64+
arr: Sequence[float], low: int, mid: int, high: int
65+
) -> tuple[int, int, float]:
66+
left_sum, max_left = float("-inf"), -1
67+
right_sum, max_right = float("-inf"), -1
68+
69+
summ: int | float = 0
70+
for i in range(mid, low - 1, -1):
71+
summ += arr[i]
72+
if summ > left_sum:
73+
left_sum = summ
74+
max_left = i
75+
76+
summ = 0
77+
for i in range(mid + 1, high + 1):
78+
summ += arr[i]
79+
if summ > right_sum:
80+
right_sum = summ
81+
max_right = i
82+
83+
return max_left, max_right, (left_sum + right_sum)
84+
85+
86+
def time_max_subarray(input_size: int) -> float:
87+
arr = [randint(1, input_size) for _ in range(input_size)]
88+
start = time.time()
89+
max_subarray(arr, 0, input_size - 1)
90+
end = time.time()
91+
return end - start
92+
93+
94+
def plot_runtimes() -> None:
95+
input_sizes = [10, 100, 1000, 10000, 50000, 100000, 200000, 300000, 400000, 500000]
96+
runtimes = [time_max_subarray(input_size) for input_size in input_sizes]
97+
print("No of Inputs\t\tTime Taken")
98+
for input_size, runtime in zip(input_sizes, runtimes):
99+
print(input_size, "\t\t", runtime)
100+
plt.plot(input_sizes, runtimes)
101+
plt.xlabel("Number of Inputs")
102+
plt.ylabel("Time taken in seconds")
103+
plt.show()
104+
105+
106+
if __name__ == "__main__":
107+
"""
108+
A random simulation of this algorithm.
109+
"""
110+
from doctest import testmod
111+
112+
testmod()

0 commit comments

Comments
 (0)