Skip to content

Commit 6d2cb8e

Browse files
Merge branch 'TheAlgorithms:master' into master
2 parents 2ea4bf0 + 9e0c357 commit 6d2cb8e

File tree

12 files changed

+302
-39
lines changed

12 files changed

+302
-39
lines changed

Diff for: DIRECTORY.md

+2
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,8 @@
990990
* [Sol1](project_euler/problem_174/sol1.py)
991991
* Problem 180
992992
* [Sol1](project_euler/problem_180/sol1.py)
993+
* Problem 187
994+
* [Sol1](project_euler/problem_187/sol1.py)
993995
* Problem 188
994996
* [Sol1](project_euler/problem_188/sol1.py)
995997
* Problem 191

Diff for: arithmetic_analysis/lu_decomposition.py

+65-26
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,101 @@
1-
"""Lower-Upper (LU) Decomposition.
1+
"""
2+
Lower–upper (LU) decomposition factors a matrix as a product of a lower
3+
triangular matrix and an upper triangular matrix. A square matrix has an LU
4+
decomposition under the following conditions:
5+
- If the matrix is invertible, then it has an LU decomposition if and only
6+
if all of its leading principal minors are non-zero (see
7+
https://en.wikipedia.org/wiki/Minor_(linear_algebra) for an explanation of
8+
leading principal minors of a matrix).
9+
- If the matrix is singular (i.e., not invertible) and it has a rank of k
10+
(i.e., it has k linearly independent columns), then it has an LU
11+
decomposition if its first k leading principal minors are non-zero.
12+
13+
This algorithm will simply attempt to perform LU decomposition on any square
14+
matrix and raise an error if no such decomposition exists.
215
3-
Reference:
4-
- https://en.wikipedia.org/wiki/LU_decomposition
16+
Reference: https://en.wikipedia.org/wiki/LU_decomposition
517
"""
618
from __future__ import annotations
719

820
import numpy as np
9-
from numpy import float64
10-
from numpy.typing import ArrayLike
11-
1221

13-
def lower_upper_decomposition(
14-
table: ArrayLike[float64],
15-
) -> tuple[ArrayLike[float64], ArrayLike[float64]]:
16-
"""Lower-Upper (LU) Decomposition
17-
18-
Example:
1922

23+
def lower_upper_decomposition(table: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
24+
"""
25+
Perform LU decomposition on a given matrix and raises an error if the matrix
26+
isn't square or if no such decomposition exists
2027
>>> matrix = np.array([[2, -2, 1], [0, 1, 2], [5, 3, 1]])
21-
>>> outcome = lower_upper_decomposition(matrix)
22-
>>> outcome[0]
28+
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
29+
>>> lower_mat
2330
array([[1. , 0. , 0. ],
2431
[0. , 1. , 0. ],
2532
[2.5, 8. , 1. ]])
26-
>>> outcome[1]
33+
>>> upper_mat
2734
array([[ 2. , -2. , 1. ],
2835
[ 0. , 1. , 2. ],
2936
[ 0. , 0. , -17.5]])
3037
38+
>>> matrix = np.array([[4, 3], [6, 3]])
39+
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
40+
>>> lower_mat
41+
array([[1. , 0. ],
42+
[1.5, 1. ]])
43+
>>> upper_mat
44+
array([[ 4. , 3. ],
45+
[ 0. , -1.5]])
46+
47+
# Matrix is not square
3148
>>> matrix = np.array([[2, -2, 1], [0, 1, 2]])
32-
>>> lower_upper_decomposition(matrix)
49+
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
3350
Traceback (most recent call last):
3451
...
3552
ValueError: 'table' has to be of square shaped array but got a 2x3 array:
3653
[[ 2 -2 1]
3754
[ 0 1 2]]
55+
56+
# Matrix is invertible, but its first leading principal minor is 0
57+
>>> matrix = np.array([[0, 1], [1, 0]])
58+
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
59+
Traceback (most recent call last):
60+
...
61+
ArithmeticError: No LU decomposition exists
62+
63+
# Matrix is singular, but its first leading principal minor is 1
64+
>>> matrix = np.array([[1, 0], [1, 0]])
65+
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
66+
>>> lower_mat
67+
array([[1., 0.],
68+
[1., 1.]])
69+
>>> upper_mat
70+
array([[1., 0.],
71+
[0., 0.]])
72+
73+
# Matrix is singular, but its first leading principal minor is 0
74+
>>> matrix = np.array([[0, 1], [0, 1]])
75+
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
76+
Traceback (most recent call last):
77+
...
78+
ArithmeticError: No LU decomposition exists
3879
"""
39-
# Table that contains our data
40-
# Table has to be a square array so we need to check first
80+
# Ensure that table is a square array
4181
rows, columns = np.shape(table)
4282
if rows != columns:
4383
raise ValueError(
44-
f"'table' has to be of square shaped array but got a {rows}x{columns} "
45-
+ f"array:\n{table}"
84+
f"'table' has to be of square shaped array but got a "
85+
f"{rows}x{columns} array:\n{table}"
4686
)
87+
4788
lower = np.zeros((rows, columns))
4889
upper = np.zeros((rows, columns))
4990
for i in range(columns):
5091
for j in range(i):
51-
total = 0
52-
for k in range(j):
53-
total += lower[i][k] * upper[k][j]
92+
total = sum(lower[i][k] * upper[k][j] for k in range(j))
93+
if upper[j][j] == 0:
94+
raise ArithmeticError("No LU decomposition exists")
5495
lower[i][j] = (table[i][j] - total) / upper[j][j]
5596
lower[i][i] = 1
5697
for j in range(i, columns):
57-
total = 0
58-
for k in range(i):
59-
total += lower[i][k] * upper[k][j]
98+
total = sum(lower[i][k] * upper[k][j] for k in range(j))
6099
upper[i][j] = table[i][j] - total
61100
return lower, upper
62101

Diff for: computer_vision/cnn_classification.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
test_image = tf.keras.preprocessing.image.img_to_array(test_image)
9494
test_image = np.expand_dims(test_image, axis=0)
9595
result = classifier.predict(test_image)
96-
training_set.class_indices
96+
# training_set.class_indices
9797
if result[0][0] == 0:
9898
prediction = "Normal"
9999
if result[0][0] == 1:

Diff for: data_structures/linked_list/circular_linked_list.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def __iter__(self) -> Iterator[Any]:
2424
break
2525

2626
def __len__(self) -> int:
27-
return len(tuple(iter(self)))
27+
return sum(1 for _ in self)
2828

2929
def __repr__(self):
3030
return "->".join(str(item) for item in iter(self))

Diff for: data_structures/linked_list/doubly_linked_list.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def __len__(self):
5151
>>> len(linked_list) == 5
5252
True
5353
"""
54-
return len(tuple(iter(self)))
54+
return sum(1 for _ in self)
5555

5656
def insert_at_head(self, data):
5757
self.insert_at_nth(0, data)

Diff for: data_structures/linked_list/merge_two_lists.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def __len__(self) -> int:
4444
>>> len(SortedLinkedList(test_data_odd))
4545
8
4646
"""
47-
return len(tuple(iter(self)))
47+
return sum(1 for _ in self)
4848

4949
def __str__(self) -> str:
5050
"""

Diff for: data_structures/linked_list/singly_linked_list.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def __len__(self) -> int:
7272
>>> len(linked_list)
7373
0
7474
"""
75-
return len(tuple(iter(self)))
75+
return sum(1 for _ in self)
7676

7777
def __repr__(self) -> str:
7878
"""

Diff for: dynamic_programming/max_product_subarray.py

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
def max_product_subarray(numbers: list[int]) -> int:
2+
"""
3+
Returns the maximum product that can be obtained by multiplying a
4+
contiguous subarray of the given integer list `nums`.
5+
6+
Example:
7+
>>> max_product_subarray([2, 3, -2, 4])
8+
6
9+
>>> max_product_subarray((-2, 0, -1))
10+
0
11+
>>> max_product_subarray([2, 3, -2, 4, -1])
12+
48
13+
>>> max_product_subarray([-1])
14+
-1
15+
>>> max_product_subarray([0])
16+
0
17+
>>> max_product_subarray([])
18+
0
19+
>>> max_product_subarray("")
20+
0
21+
>>> max_product_subarray(None)
22+
0
23+
>>> max_product_subarray([2, 3, -2, 4.5, -1])
24+
Traceback (most recent call last):
25+
...
26+
ValueError: numbers must be an iterable of integers
27+
>>> max_product_subarray("ABC")
28+
Traceback (most recent call last):
29+
...
30+
ValueError: numbers must be an iterable of integers
31+
"""
32+
if not numbers:
33+
return 0
34+
35+
if not isinstance(numbers, (list, tuple)) or not all(
36+
isinstance(number, int) for number in numbers
37+
):
38+
raise ValueError("numbers must be an iterable of integers")
39+
40+
max_till_now = min_till_now = max_prod = numbers[0]
41+
42+
for i in range(1, len(numbers)):
43+
# update the maximum and minimum subarray products
44+
number = numbers[i]
45+
if number < 0:
46+
max_till_now, min_till_now = min_till_now, max_till_now
47+
max_till_now = max(number, max_till_now * number)
48+
min_till_now = min(number, min_till_now * number)
49+
50+
# update the maximum product found till now
51+
max_prod = max(max_prod, max_till_now)
52+
53+
return max_prod

Diff for: file_transfer/receive_file.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
if __name__ == "__main__":
2-
import socket # Import socket module
1+
import socket
2+
33

4-
sock = socket.socket() # Create a socket object
5-
host = socket.gethostname() # Get local machine name
4+
def main():
5+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
6+
host = socket.gethostname()
67
port = 12312
78

89
sock.connect((host, port))
@@ -13,11 +14,14 @@
1314
print("Receiving data...")
1415
while True:
1516
data = sock.recv(1024)
16-
print(f"{data = }")
1717
if not data:
1818
break
19-
out_file.write(data) # Write data to a file
19+
out_file.write(data)
2020

21-
print("Successfully got the file")
21+
print("Successfully received the file")
2222
sock.close()
2323
print("Connection closed")
24+
25+
26+
if __name__ == "__main__":
27+
main()

Diff for: project_euler/problem_187/__init__.py

Whitespace-only changes.

Diff for: project_euler/problem_187/sol1.py

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""
2+
Project Euler Problem 187: https://projecteuler.net/problem=187
3+
4+
A composite is a number containing at least two prime factors.
5+
For example, 15 = 3 x 5; 9 = 3 x 3; 12 = 2 x 2 x 3.
6+
7+
There are ten composites below thirty containing precisely two,
8+
not necessarily distinct, prime factors: 4, 6, 9, 10, 14, 15, 21, 22, 25, 26.
9+
10+
How many composite integers, n < 10^8, have precisely two,
11+
not necessarily distinct, prime factors?
12+
"""
13+
14+
from math import isqrt
15+
16+
17+
def calculate_prime_numbers(max_number: int) -> list[int]:
18+
"""
19+
Returns prime numbers below max_number
20+
21+
>>> calculate_prime_numbers(10)
22+
[2, 3, 5, 7]
23+
"""
24+
25+
is_prime = [True] * max_number
26+
for i in range(2, isqrt(max_number - 1) + 1):
27+
if is_prime[i]:
28+
for j in range(i**2, max_number, i):
29+
is_prime[j] = False
30+
31+
return [i for i in range(2, max_number) if is_prime[i]]
32+
33+
34+
def solution(max_number: int = 10**8) -> int:
35+
"""
36+
Returns the number of composite integers below max_number have precisely two,
37+
not necessarily distinct, prime factors
38+
39+
>>> solution(30)
40+
10
41+
"""
42+
43+
prime_numbers = calculate_prime_numbers(max_number // 2)
44+
45+
semiprimes_count = 0
46+
left = 0
47+
right = len(prime_numbers) - 1
48+
while left <= right:
49+
while prime_numbers[left] * prime_numbers[right] >= max_number:
50+
right -= 1
51+
semiprimes_count += right - left + 1
52+
left += 1
53+
54+
return semiprimes_count
55+
56+
57+
if __name__ == "__main__":
58+
print(f"{solution() = }")

0 commit comments

Comments
 (0)