mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-02-24 09:58:39 +00:00
Compare commits
No commits in common. "e4d90e2d5b92fdcff558f1848843dfbe20d81035" and "238fe8c494ab5be80c96441095d1c8958f95c04d" have entirely different histories.
e4d90e2d5b
...
238fe8c494
@ -990,8 +990,6 @@
|
||||
* [Sol1](project_euler/problem_174/sol1.py)
|
||||
* Problem 180
|
||||
* [Sol1](project_euler/problem_180/sol1.py)
|
||||
* Problem 187
|
||||
* [Sol1](project_euler/problem_187/sol1.py)
|
||||
* Problem 188
|
||||
* [Sol1](project_euler/problem_188/sol1.py)
|
||||
* Problem 191
|
||||
|
@ -1,101 +1,62 @@
|
||||
"""
|
||||
Lower–upper (LU) decomposition factors a matrix as a product of a lower
|
||||
triangular matrix and an upper triangular matrix. A square matrix has an LU
|
||||
decomposition under the following conditions:
|
||||
- If the matrix is invertible, then it has an LU decomposition if and only
|
||||
if all of its leading principal minors are non-zero (see
|
||||
https://en.wikipedia.org/wiki/Minor_(linear_algebra) for an explanation of
|
||||
leading principal minors of a matrix).
|
||||
- If the matrix is singular (i.e., not invertible) and it has a rank of k
|
||||
(i.e., it has k linearly independent columns), then it has an LU
|
||||
decomposition if its first k leading principal minors are non-zero.
|
||||
"""Lower-Upper (LU) Decomposition.
|
||||
|
||||
This algorithm will simply attempt to perform LU decomposition on any square
|
||||
matrix and raise an error if no such decomposition exists.
|
||||
|
||||
Reference: https://en.wikipedia.org/wiki/LU_decomposition
|
||||
Reference:
|
||||
- https://en.wikipedia.org/wiki/LU_decomposition
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
from numpy import float64
|
||||
from numpy.typing import ArrayLike
|
||||
|
||||
|
||||
def lower_upper_decomposition(table: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
||||
"""
|
||||
Perform LU decomposition on a given matrix and raises an error if the matrix
|
||||
isn't square or if no such decomposition exists
|
||||
def lower_upper_decomposition(
|
||||
table: ArrayLike[float64],
|
||||
) -> tuple[ArrayLike[float64], ArrayLike[float64]]:
|
||||
"""Lower-Upper (LU) Decomposition
|
||||
|
||||
Example:
|
||||
|
||||
>>> matrix = np.array([[2, -2, 1], [0, 1, 2], [5, 3, 1]])
|
||||
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||
>>> lower_mat
|
||||
>>> outcome = lower_upper_decomposition(matrix)
|
||||
>>> outcome[0]
|
||||
array([[1. , 0. , 0. ],
|
||||
[0. , 1. , 0. ],
|
||||
[2.5, 8. , 1. ]])
|
||||
>>> upper_mat
|
||||
>>> outcome[1]
|
||||
array([[ 2. , -2. , 1. ],
|
||||
[ 0. , 1. , 2. ],
|
||||
[ 0. , 0. , -17.5]])
|
||||
|
||||
>>> matrix = np.array([[4, 3], [6, 3]])
|
||||
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||
>>> lower_mat
|
||||
array([[1. , 0. ],
|
||||
[1.5, 1. ]])
|
||||
>>> upper_mat
|
||||
array([[ 4. , 3. ],
|
||||
[ 0. , -1.5]])
|
||||
|
||||
# Matrix is not square
|
||||
>>> matrix = np.array([[2, -2, 1], [0, 1, 2]])
|
||||
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||
>>> lower_upper_decomposition(matrix)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: 'table' has to be of square shaped array but got a 2x3 array:
|
||||
[[ 2 -2 1]
|
||||
[ 0 1 2]]
|
||||
|
||||
# Matrix is invertible, but its first leading principal minor is 0
|
||||
>>> matrix = np.array([[0, 1], [1, 0]])
|
||||
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ArithmeticError: No LU decomposition exists
|
||||
|
||||
# Matrix is singular, but its first leading principal minor is 1
|
||||
>>> matrix = np.array([[1, 0], [1, 0]])
|
||||
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||
>>> lower_mat
|
||||
array([[1., 0.],
|
||||
[1., 1.]])
|
||||
>>> upper_mat
|
||||
array([[1., 0.],
|
||||
[0., 0.]])
|
||||
|
||||
# Matrix is singular, but its first leading principal minor is 0
|
||||
>>> matrix = np.array([[0, 1], [0, 1]])
|
||||
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ArithmeticError: No LU decomposition exists
|
||||
"""
|
||||
# Ensure that table is a square array
|
||||
# Table that contains our data
|
||||
# Table has to be a square array so we need to check first
|
||||
rows, columns = np.shape(table)
|
||||
if rows != columns:
|
||||
raise ValueError(
|
||||
f"'table' has to be of square shaped array but got a "
|
||||
f"{rows}x{columns} array:\n{table}"
|
||||
f"'table' has to be of square shaped array but got a {rows}x{columns} "
|
||||
+ f"array:\n{table}"
|
||||
)
|
||||
|
||||
lower = np.zeros((rows, columns))
|
||||
upper = np.zeros((rows, columns))
|
||||
for i in range(columns):
|
||||
for j in range(i):
|
||||
total = sum(lower[i][k] * upper[k][j] for k in range(j))
|
||||
if upper[j][j] == 0:
|
||||
raise ArithmeticError("No LU decomposition exists")
|
||||
total = 0
|
||||
for k in range(j):
|
||||
total += lower[i][k] * upper[k][j]
|
||||
lower[i][j] = (table[i][j] - total) / upper[j][j]
|
||||
lower[i][i] = 1
|
||||
for j in range(i, columns):
|
||||
total = sum(lower[i][k] * upper[k][j] for k in range(j))
|
||||
total = 0
|
||||
for k in range(i):
|
||||
total += lower[i][k] * upper[k][j]
|
||||
upper[i][j] = table[i][j] - total
|
||||
return lower, upper
|
||||
|
||||
|
@ -24,7 +24,7 @@ class CircularLinkedList:
|
||||
break
|
||||
|
||||
def __len__(self) -> int:
|
||||
return sum(1 for _ in self)
|
||||
return len(tuple(iter(self)))
|
||||
|
||||
def __repr__(self):
|
||||
return "->".join(str(item) for item in iter(self))
|
||||
|
@ -51,7 +51,7 @@ class DoublyLinkedList:
|
||||
>>> len(linked_list) == 5
|
||||
True
|
||||
"""
|
||||
return sum(1 for _ in self)
|
||||
return len(tuple(iter(self)))
|
||||
|
||||
def insert_at_head(self, data):
|
||||
self.insert_at_nth(0, data)
|
||||
|
@ -44,7 +44,7 @@ class SortedLinkedList:
|
||||
>>> len(SortedLinkedList(test_data_odd))
|
||||
8
|
||||
"""
|
||||
return sum(1 for _ in self)
|
||||
return len(tuple(iter(self)))
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
|
@ -72,7 +72,7 @@ class LinkedList:
|
||||
>>> len(linked_list)
|
||||
0
|
||||
"""
|
||||
return sum(1 for _ in self)
|
||||
return len(tuple(iter(self)))
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
|
@ -1,58 +0,0 @@
|
||||
"""
|
||||
Project Euler Problem 187: https://projecteuler.net/problem=187
|
||||
|
||||
A composite is a number containing at least two prime factors.
|
||||
For example, 15 = 3 x 5; 9 = 3 x 3; 12 = 2 x 2 x 3.
|
||||
|
||||
There are ten composites below thirty containing precisely two,
|
||||
not necessarily distinct, prime factors: 4, 6, 9, 10, 14, 15, 21, 22, 25, 26.
|
||||
|
||||
How many composite integers, n < 10^8, have precisely two,
|
||||
not necessarily distinct, prime factors?
|
||||
"""
|
||||
|
||||
from math import isqrt
|
||||
|
||||
|
||||
def calculate_prime_numbers(max_number: int) -> list[int]:
|
||||
"""
|
||||
Returns prime numbers below max_number
|
||||
|
||||
>>> calculate_prime_numbers(10)
|
||||
[2, 3, 5, 7]
|
||||
"""
|
||||
|
||||
is_prime = [True] * max_number
|
||||
for i in range(2, isqrt(max_number - 1) + 1):
|
||||
if is_prime[i]:
|
||||
for j in range(i**2, max_number, i):
|
||||
is_prime[j] = False
|
||||
|
||||
return [i for i in range(2, max_number) if is_prime[i]]
|
||||
|
||||
|
||||
def solution(max_number: int = 10**8) -> int:
|
||||
"""
|
||||
Returns the number of composite integers below max_number have precisely two,
|
||||
not necessarily distinct, prime factors
|
||||
|
||||
>>> solution(30)
|
||||
10
|
||||
"""
|
||||
|
||||
prime_numbers = calculate_prime_numbers(max_number // 2)
|
||||
|
||||
semiprimes_count = 0
|
||||
left = 0
|
||||
right = len(prime_numbers) - 1
|
||||
while left <= right:
|
||||
while prime_numbers[left] * prime_numbers[right] >= max_number:
|
||||
right -= 1
|
||||
semiprimes_count += right - left + 1
|
||||
left += 1
|
||||
|
||||
return semiprimes_count
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"{solution() = }")
|
Loading…
x
Reference in New Issue
Block a user