Skip to content
65 changes: 65 additions & 0 deletions maths/optimised_sieve_of_eratosthenes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Optimized Sieve of Eratosthenes: An efficient algorithm to compute all prime numbers
# up to limit. This version skips even numbers after 2, improving both memory and time
# usage. It is particularly efficient for larger limits (e.g., up to 10**8 on typical
# hardware).
# Wikipedia URL - https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

from math import isqrt


def optimized_sieve(limit: int) -> list[int]:
"""
Compute all prime numbers up to and including `limit` using an optimized
Sieve of Eratosthenes.

This implementation skips even numbers after 2 to reduce memory and
runtime by about 50%.

Parameters
----------
limit : int
Upper bound (inclusive) of the range in which to find prime numbers.
Expected to be a non-negative integer. If limit < 2 the function
returns an empty list.

Returns
-------
list[int]
A list of primes in ascending order that are <= limit.

Examples
--------
>>> optimized_sieve(10)
[2, 3, 5, 7]
>>> optimized_sieve(1)
[]
>>> optimized_sieve(2)
[2]
>>> optimized_sieve(30)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
"""
if limit < 2:
return []

# Handle 2 separately, then consider only odd numbers
primes = [2] if limit >= 2 else []

# Only odd numbers from 3 to limit
size = (limit - 1) // 2
is_prime = [True] * (size + 1)
bound = isqrt(limit)

for i in range((bound - 1) // 2 + 1):
if is_prime[i]:
p = 2 * i + 3
# Start marking from p^2, converted to index
start = (p * p - 3) // 2
for j in range(start, size + 1, p):
is_prime[j] = False

primes.extend(2 * i + 3 for i in range(size + 1) if is_prime[i])
return primes


if __name__ == "__main__":
print(optimized_sieve(50))
70 changes: 70 additions & 0 deletions matrix/determinant_calculator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Wikipedia URL- https://en.wikipedia.org/wiki/Determinant

def get_minor(matrix: list[list[int] | list[float]], row: int, col: int) -> list[list[int] | list[float]]:

Check failure on line 3 in matrix/determinant_calculator.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

matrix/determinant_calculator.py:3:89: E501 Line too long (106 > 88)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As there is no test file in this pull request nor any test function or class in the file matrix/determinant_calculator.py, please provide doctest for the function get_minor

"""
Returns the minor matrix obtained by removing the specified row and column.

Parameters
----------
matrix : list[list[int] | list[float]]
The original square matrix.
row : int
The row to remove.
col : int
The column to remove.

Returns
-------
list[list[int] | list[float]]
Minor matrix.
"""
return [r[:col] + r[col+1:] for i, r in enumerate(matrix) if i != row]


def determinant_manual(matrix: list[list[int] | list[float]]) -> int | float:
"""
Calculates the determinant of a square matrix using cofactor expansion.

Parameters
----------
matrix : list[list[int] | list[float]]
A square matrix.

Returns
-------
int | float
Determinant of the matrix.

Examples
--------
>>> determinant_manual([[1,2],[3,4]])
-2
>>> determinant_manual([[2]])
2
>>> determinant_manual([[1,2,3],[4,5,6],[7,8,9]])
0
"""
n = len(matrix)

if n == 1:
return matrix[0][0]

if n == 2:
return matrix[0][0]*matrix[1][1] - matrix[0][1]*matrix[1][0]

det = 0
for j in range(n):
minor = get_minor(matrix, 0, j)
cofactor = (-1) ** j * determinant_manual(minor)
det += matrix[0][j] * cofactor
return det


if __name__ == "__main__":
# Simple demo
matrix_demo = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
print(f"The determinant is: {determinant_manual(matrix_demo)}")
Loading