mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-02-25 18:38:39 +00:00
Merge branch 'TheAlgorithms:master' into fix-mypy-errs-5
This commit is contained in:
commit
345c1dd847
4
.github/stale.yml
vendored
4
.github/stale.yml
vendored
@ -45,7 +45,7 @@ pulls:
|
||||
closeComment: >
|
||||
Please reopen this pull request once you commit the changes requested
|
||||
or make improvements on the code. If this is not the case and you need
|
||||
some help, feel free to seek help from our [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im)
|
||||
some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms/community)
|
||||
or ping one of the reviewers. Thank you for your contributions!
|
||||
|
||||
issues:
|
||||
@ -59,5 +59,5 @@ issues:
|
||||
closeComment: >
|
||||
Please reopen this issue once you add more information and updates here.
|
||||
If this is not the case and you need some help, feel free to seek help
|
||||
from our [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im) or ping one of the
|
||||
from our [Gitter](https://gitter.im/TheAlgorithms/community) or ping one of the
|
||||
reviewers. Thank you for your contributions!
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
## Before contributing
|
||||
|
||||
Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before sending your pull requests, make sure that you __read the whole guidelines__. If you have any doubt on the contributing guide, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im).
|
||||
Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before sending your pull requests, make sure that you __read the whole guidelines__. If you have any doubt on the contributing guide, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms/community).
|
||||
|
||||
## Contributing
|
||||
|
||||
@ -176,7 +176,7 @@ We want your work to be readable by others; therefore, we encourage you to note
|
||||
|
||||
- Most importantly,
|
||||
- __Be consistent in the use of these guidelines when submitting.__
|
||||
- __Join__ us on [Discord](https://discord.com/invite/c7MnfGFGa6) and [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im) __now!__
|
||||
- __Join__ us on [Discord](https://discord.com/invite/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms/community) __now!__
|
||||
- Happy coding!
|
||||
|
||||
Writer [@poyea](https://github.com/poyea), Jun 2019.
|
||||
|
@ -317,6 +317,7 @@
|
||||
* [Longest Sub Array](dynamic_programming/longest_sub_array.py)
|
||||
* [Matrix Chain Order](dynamic_programming/matrix_chain_order.py)
|
||||
* [Max Non Adjacent Sum](dynamic_programming/max_non_adjacent_sum.py)
|
||||
* [Max Product Subarray](dynamic_programming/max_product_subarray.py)
|
||||
* [Max Sub Array](dynamic_programming/max_sub_array.py)
|
||||
* [Max Sum Contiguous Subsequence](dynamic_programming/max_sum_contiguous_subsequence.py)
|
||||
* [Min Distance Up Bottom](dynamic_programming/min_distance_up_bottom.py)
|
||||
@ -936,6 +937,8 @@
|
||||
* [Sol1](project_euler/problem_091/sol1.py)
|
||||
* Problem 092
|
||||
* [Sol1](project_euler/problem_092/sol1.py)
|
||||
* Problem 094
|
||||
* [Sol1](project_euler/problem_094/sol1.py)
|
||||
* Problem 097
|
||||
* [Sol1](project_euler/problem_097/sol1.py)
|
||||
* Problem 099
|
||||
@ -990,6 +993,8 @@
|
||||
* [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
|
||||
@ -1014,6 +1019,8 @@
|
||||
* [Sol1](project_euler/problem_587/sol1.py)
|
||||
* Problem 686
|
||||
* [Sol1](project_euler/problem_686/sol1.py)
|
||||
* Problem 800
|
||||
* [Sol1](project_euler/problem_800/sol1.py)
|
||||
|
||||
## Quantum
|
||||
* [Bb84](quantum/bb84.py)
|
||||
|
@ -16,7 +16,7 @@
|
||||
<a href="https://discord.gg/c7MnfGFGa6">
|
||||
<img src="https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=7289DA&style=flat-square" height="20" alt="Discord chat">
|
||||
</a>
|
||||
<a href="https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im">
|
||||
<a href="https://gitter.im/TheAlgorithms/community">
|
||||
<img src="https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square" height="20" alt="Gitter chat">
|
||||
</a>
|
||||
<!-- Second row: -->
|
||||
@ -42,7 +42,7 @@ Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribut
|
||||
|
||||
## Community Channels
|
||||
|
||||
We are on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im)! Community channels are a great way for you to ask questions and get help. Please join us!
|
||||
We are on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms/community)! Community channels are a great way for you to ask questions and get help. Please join us!
|
||||
|
||||
## List of Algorithms
|
||||
|
||||
|
@ -1,62 +1,101 @@
|
||||
"""Lower-Upper (LU) Decomposition.
|
||||
"""
|
||||
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.
|
||||
|
||||
Reference:
|
||||
- https://en.wikipedia.org/wiki/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
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
from numpy import float64
|
||||
from numpy.typing import ArrayLike
|
||||
|
||||
|
||||
def lower_upper_decomposition(
|
||||
table: ArrayLike[float64],
|
||||
) -> tuple[ArrayLike[float64], ArrayLike[float64]]:
|
||||
"""Lower-Upper (LU) Decomposition
|
||||
|
||||
Example:
|
||||
|
||||
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
|
||||
>>> matrix = np.array([[2, -2, 1], [0, 1, 2], [5, 3, 1]])
|
||||
>>> outcome = lower_upper_decomposition(matrix)
|
||||
>>> outcome[0]
|
||||
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||
>>> lower_mat
|
||||
array([[1. , 0. , 0. ],
|
||||
[0. , 1. , 0. ],
|
||||
[2.5, 8. , 1. ]])
|
||||
>>> outcome[1]
|
||||
>>> upper_mat
|
||||
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_upper_decomposition(matrix)
|
||||
>>> lower_mat, upper_mat = 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
|
||||
"""
|
||||
# Table that contains our data
|
||||
# Table has to be a square array so we need to check first
|
||||
# Ensure that table is a square array
|
||||
rows, columns = np.shape(table)
|
||||
if rows != columns:
|
||||
raise ValueError(
|
||||
f"'table' has to be of square shaped array but got a {rows}x{columns} "
|
||||
+ f"array:\n{table}"
|
||||
f"'table' has to be of square shaped array but got a "
|
||||
f"{rows}x{columns} array:\n{table}"
|
||||
)
|
||||
|
||||
lower = np.zeros((rows, columns))
|
||||
upper = np.zeros((rows, columns))
|
||||
for i in range(columns):
|
||||
for j in range(i):
|
||||
total = 0
|
||||
for k in range(j):
|
||||
total += lower[i][k] * upper[k][j]
|
||||
total = sum(lower[i][k] * upper[k][j] for k in range(j))
|
||||
if upper[j][j] == 0:
|
||||
raise ArithmeticError("No LU decomposition exists")
|
||||
lower[i][j] = (table[i][j] - total) / upper[j][j]
|
||||
lower[i][i] = 1
|
||||
for j in range(i, columns):
|
||||
total = 0
|
||||
for k in range(i):
|
||||
total += lower[i][k] * upper[k][j]
|
||||
total = sum(lower[i][k] * upper[k][j] for k in range(j))
|
||||
upper[i][j] = table[i][j] - total
|
||||
return lower, upper
|
||||
|
||||
|
@ -93,7 +93,7 @@ if __name__ == "__main__":
|
||||
test_image = tf.keras.preprocessing.image.img_to_array(test_image)
|
||||
test_image = np.expand_dims(test_image, axis=0)
|
||||
result = classifier.predict(test_image)
|
||||
training_set.class_indices
|
||||
# training_set.class_indices
|
||||
if result[0][0] == 0:
|
||||
prediction = "Normal"
|
||||
if result[0][0] == 1:
|
||||
|
@ -24,7 +24,7 @@ class CircularLinkedList:
|
||||
break
|
||||
|
||||
def __len__(self) -> int:
|
||||
return len(tuple(iter(self)))
|
||||
return sum(1 for _ in 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 len(tuple(iter(self)))
|
||||
return sum(1 for _ in self)
|
||||
|
||||
def insert_at_head(self, data):
|
||||
self.insert_at_nth(0, data)
|
||||
@ -81,7 +81,9 @@ class DoublyLinkedList:
|
||||
....
|
||||
IndexError: list index out of range
|
||||
"""
|
||||
if not 0 <= index <= len(self):
|
||||
length = len(self)
|
||||
|
||||
if not 0 <= index <= length:
|
||||
raise IndexError("list index out of range")
|
||||
new_node = Node(data)
|
||||
if self.head is None:
|
||||
@ -90,7 +92,7 @@ class DoublyLinkedList:
|
||||
self.head.previous = new_node
|
||||
new_node.next = self.head
|
||||
self.head = new_node
|
||||
elif index == len(self):
|
||||
elif index == length:
|
||||
self.tail.next = new_node
|
||||
new_node.previous = self.tail
|
||||
self.tail = new_node
|
||||
@ -131,15 +133,17 @@ class DoublyLinkedList:
|
||||
....
|
||||
IndexError: list index out of range
|
||||
"""
|
||||
if not 0 <= index <= len(self) - 1:
|
||||
length = len(self)
|
||||
|
||||
if not 0 <= index <= length - 1:
|
||||
raise IndexError("list index out of range")
|
||||
delete_node = self.head # default first node
|
||||
if len(self) == 1:
|
||||
if length == 1:
|
||||
self.head = self.tail = None
|
||||
elif index == 0:
|
||||
self.head = self.head.next
|
||||
self.head.previous = None
|
||||
elif index == len(self) - 1:
|
||||
elif index == length - 1:
|
||||
delete_node = self.tail
|
||||
self.tail = self.tail.previous
|
||||
self.tail.next = None
|
||||
|
@ -44,7 +44,7 @@ class SortedLinkedList:
|
||||
>>> len(SortedLinkedList(test_data_odd))
|
||||
8
|
||||
"""
|
||||
return len(tuple(iter(self)))
|
||||
return sum(1 for _ in self)
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
|
@ -72,7 +72,7 @@ class LinkedList:
|
||||
>>> len(linked_list)
|
||||
0
|
||||
"""
|
||||
return len(tuple(iter(self)))
|
||||
return sum(1 for _ in self)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""
|
||||
|
@ -18,105 +18,126 @@ def gen_gaussian_kernel(k_size, sigma):
|
||||
return g
|
||||
|
||||
|
||||
def canny(image, threshold_low=15, threshold_high=30, weak=128, strong=255):
|
||||
image_row, image_col = image.shape[0], image.shape[1]
|
||||
# gaussian_filter
|
||||
gaussian_out = img_convolve(image, gen_gaussian_kernel(9, sigma=1.4))
|
||||
# get the gradient and degree by sobel_filter
|
||||
sobel_grad, sobel_theta = sobel_filter(gaussian_out)
|
||||
gradient_direction = np.rad2deg(sobel_theta)
|
||||
gradient_direction += PI
|
||||
|
||||
dst = np.zeros((image_row, image_col))
|
||||
|
||||
def suppress_non_maximum(image_shape, gradient_direction, sobel_grad):
|
||||
"""
|
||||
Non-maximum suppression. If the edge strength of the current pixel is the largest
|
||||
compared to the other pixels in the mask with the same direction, the value will be
|
||||
preserved. Otherwise, the value will be suppressed.
|
||||
"""
|
||||
for row in range(1, image_row - 1):
|
||||
for col in range(1, image_col - 1):
|
||||
destination = np.zeros(image_shape)
|
||||
|
||||
for row in range(1, image_shape[0] - 1):
|
||||
for col in range(1, image_shape[1] - 1):
|
||||
direction = gradient_direction[row, col]
|
||||
|
||||
if (
|
||||
0 <= direction < 22.5
|
||||
0 <= direction < PI / 8
|
||||
or 15 * PI / 8 <= direction <= 2 * PI
|
||||
or 7 * PI / 8 <= direction <= 9 * PI / 8
|
||||
):
|
||||
w = sobel_grad[row, col - 1]
|
||||
e = sobel_grad[row, col + 1]
|
||||
if sobel_grad[row, col] >= w and sobel_grad[row, col] >= e:
|
||||
dst[row, col] = sobel_grad[row, col]
|
||||
destination[row, col] = sobel_grad[row, col]
|
||||
|
||||
elif (PI / 8 <= direction < 3 * PI / 8) or (
|
||||
9 * PI / 8 <= direction < 11 * PI / 8
|
||||
elif (
|
||||
PI / 8 <= direction < 3 * PI / 8
|
||||
or 9 * PI / 8 <= direction < 11 * PI / 8
|
||||
):
|
||||
sw = sobel_grad[row + 1, col - 1]
|
||||
ne = sobel_grad[row - 1, col + 1]
|
||||
if sobel_grad[row, col] >= sw and sobel_grad[row, col] >= ne:
|
||||
dst[row, col] = sobel_grad[row, col]
|
||||
destination[row, col] = sobel_grad[row, col]
|
||||
|
||||
elif (3 * PI / 8 <= direction < 5 * PI / 8) or (
|
||||
11 * PI / 8 <= direction < 13 * PI / 8
|
||||
elif (
|
||||
3 * PI / 8 <= direction < 5 * PI / 8
|
||||
or 11 * PI / 8 <= direction < 13 * PI / 8
|
||||
):
|
||||
n = sobel_grad[row - 1, col]
|
||||
s = sobel_grad[row + 1, col]
|
||||
if sobel_grad[row, col] >= n and sobel_grad[row, col] >= s:
|
||||
dst[row, col] = sobel_grad[row, col]
|
||||
destination[row, col] = sobel_grad[row, col]
|
||||
|
||||
elif (5 * PI / 8 <= direction < 7 * PI / 8) or (
|
||||
13 * PI / 8 <= direction < 15 * PI / 8
|
||||
elif (
|
||||
5 * PI / 8 <= direction < 7 * PI / 8
|
||||
or 13 * PI / 8 <= direction < 15 * PI / 8
|
||||
):
|
||||
nw = sobel_grad[row - 1, col - 1]
|
||||
se = sobel_grad[row + 1, col + 1]
|
||||
if sobel_grad[row, col] >= nw and sobel_grad[row, col] >= se:
|
||||
dst[row, col] = sobel_grad[row, col]
|
||||
destination[row, col] = sobel_grad[row, col]
|
||||
|
||||
"""
|
||||
High-Low threshold detection. If an edge pixel’s gradient value is higher
|
||||
than the high threshold value, it is marked as a strong edge pixel. If an
|
||||
edge pixel’s gradient value is smaller than the high threshold value and
|
||||
larger than the low threshold value, it is marked as a weak edge pixel. If
|
||||
an edge pixel's value is smaller than the low threshold value, it will be
|
||||
suppressed.
|
||||
"""
|
||||
if dst[row, col] >= threshold_high:
|
||||
dst[row, col] = strong
|
||||
elif dst[row, col] <= threshold_low:
|
||||
dst[row, col] = 0
|
||||
return destination
|
||||
|
||||
|
||||
def detect_high_low_threshold(
|
||||
image_shape, destination, threshold_low, threshold_high, weak, strong
|
||||
):
|
||||
"""
|
||||
High-Low threshold detection. If an edge pixel’s gradient value is higher
|
||||
than the high threshold value, it is marked as a strong edge pixel. If an
|
||||
edge pixel’s gradient value is smaller than the high threshold value and
|
||||
larger than the low threshold value, it is marked as a weak edge pixel. If
|
||||
an edge pixel's value is smaller than the low threshold value, it will be
|
||||
suppressed.
|
||||
"""
|
||||
for row in range(1, image_shape[0] - 1):
|
||||
for col in range(1, image_shape[1] - 1):
|
||||
if destination[row, col] >= threshold_high:
|
||||
destination[row, col] = strong
|
||||
elif destination[row, col] <= threshold_low:
|
||||
destination[row, col] = 0
|
||||
else:
|
||||
dst[row, col] = weak
|
||||
destination[row, col] = weak
|
||||
|
||||
|
||||
def track_edge(image_shape, destination, weak, strong):
|
||||
"""
|
||||
Edge tracking. Usually a weak edge pixel caused from true edges will be connected
|
||||
to a strong edge pixel while noise responses are unconnected. As long as there is
|
||||
one strong edge pixel that is involved in its 8-connected neighborhood, that weak
|
||||
edge point can be identified as one that should be preserved.
|
||||
"""
|
||||
for row in range(1, image_row):
|
||||
for col in range(1, image_col):
|
||||
if dst[row, col] == weak:
|
||||
for row in range(1, image_shape[0]):
|
||||
for col in range(1, image_shape[1]):
|
||||
if destination[row, col] == weak:
|
||||
if 255 in (
|
||||
dst[row, col + 1],
|
||||
dst[row, col - 1],
|
||||
dst[row - 1, col],
|
||||
dst[row + 1, col],
|
||||
dst[row - 1, col - 1],
|
||||
dst[row + 1, col - 1],
|
||||
dst[row - 1, col + 1],
|
||||
dst[row + 1, col + 1],
|
||||
destination[row, col + 1],
|
||||
destination[row, col - 1],
|
||||
destination[row - 1, col],
|
||||
destination[row + 1, col],
|
||||
destination[row - 1, col - 1],
|
||||
destination[row + 1, col - 1],
|
||||
destination[row - 1, col + 1],
|
||||
destination[row + 1, col + 1],
|
||||
):
|
||||
dst[row, col] = strong
|
||||
destination[row, col] = strong
|
||||
else:
|
||||
dst[row, col] = 0
|
||||
destination[row, col] = 0
|
||||
|
||||
return dst
|
||||
|
||||
def canny(image, threshold_low=15, threshold_high=30, weak=128, strong=255):
|
||||
# gaussian_filter
|
||||
gaussian_out = img_convolve(image, gen_gaussian_kernel(9, sigma=1.4))
|
||||
# get the gradient and degree by sobel_filter
|
||||
sobel_grad, sobel_theta = sobel_filter(gaussian_out)
|
||||
gradient_direction = PI + np.rad2deg(sobel_theta)
|
||||
|
||||
destination = suppress_non_maximum(image.shape, gradient_direction, sobel_grad)
|
||||
|
||||
detect_high_low_threshold(
|
||||
image.shape, destination, threshold_low, threshold_high, weak, strong
|
||||
)
|
||||
|
||||
track_edge(image.shape, destination, weak, strong)
|
||||
|
||||
return destination
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# read original image in gray mode
|
||||
lena = cv2.imread(r"../image_data/lena.jpg", 0)
|
||||
# canny edge detection
|
||||
canny_dst = canny(lena)
|
||||
cv2.imshow("canny", canny_dst)
|
||||
canny_destination = canny(lena)
|
||||
cv2.imshow("canny", canny_destination)
|
||||
cv2.waitKey(0)
|
||||
|
@ -1,33 +1,35 @@
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def rgb2gray(rgb: np.array) -> np.array:
|
||||
def rgb_to_gray(rgb: np.ndarray) -> np.ndarray:
|
||||
"""
|
||||
Return gray image from rgb image
|
||||
>>> rgb2gray(np.array([[[127, 255, 0]]]))
|
||||
>>> rgb_to_gray(np.array([[[127, 255, 0]]]))
|
||||
array([[187.6453]])
|
||||
>>> rgb2gray(np.array([[[0, 0, 0]]]))
|
||||
>>> rgb_to_gray(np.array([[[0, 0, 0]]]))
|
||||
array([[0.]])
|
||||
>>> rgb2gray(np.array([[[2, 4, 1]]]))
|
||||
>>> rgb_to_gray(np.array([[[2, 4, 1]]]))
|
||||
array([[3.0598]])
|
||||
>>> rgb2gray(np.array([[[26, 255, 14], [5, 147, 20], [1, 200, 0]]]))
|
||||
>>> rgb_to_gray(np.array([[[26, 255, 14], [5, 147, 20], [1, 200, 0]]]))
|
||||
array([[159.0524, 90.0635, 117.6989]])
|
||||
"""
|
||||
r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2]
|
||||
return 0.2989 * r + 0.5870 * g + 0.1140 * b
|
||||
|
||||
|
||||
def gray2binary(gray: np.array) -> np.array:
|
||||
def gray_to_binary(gray: np.ndarray) -> np.ndarray:
|
||||
"""
|
||||
Return binary image from gray image
|
||||
>>> gray2binary(np.array([[127, 255, 0]]))
|
||||
>>> gray_to_binary(np.array([[127, 255, 0]]))
|
||||
array([[False, True, False]])
|
||||
>>> gray2binary(np.array([[0]]))
|
||||
>>> gray_to_binary(np.array([[0]]))
|
||||
array([[False]])
|
||||
>>> gray2binary(np.array([[26.2409, 4.9315, 1.4729]]))
|
||||
>>> gray_to_binary(np.array([[26.2409, 4.9315, 1.4729]]))
|
||||
array([[False, False, False]])
|
||||
>>> gray2binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]]))
|
||||
>>> gray_to_binary(np.array([[26, 255, 14], [5, 147, 20], [1, 200, 0]]))
|
||||
array([[False, True, False],
|
||||
[False, True, False],
|
||||
[False, True, False]])
|
||||
@ -35,7 +37,7 @@ def gray2binary(gray: np.array) -> np.array:
|
||||
return (gray > 127) & (gray <= 255)
|
||||
|
||||
|
||||
def dilation(image: np.array, kernel: np.array) -> np.array:
|
||||
def dilation(image: np.ndarray, kernel: np.ndarray) -> np.ndarray:
|
||||
"""
|
||||
Return dilated image
|
||||
>>> dilation(np.array([[True, False, True]]), np.array([[0, 1, 0]]))
|
||||
@ -61,14 +63,13 @@ def dilation(image: np.array, kernel: np.array) -> np.array:
|
||||
return output
|
||||
|
||||
|
||||
# kernel to be applied
|
||||
structuring_element = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# read original image
|
||||
image = np.array(Image.open(r"..\image_data\lena.jpg"))
|
||||
output = dilation(gray2binary(rgb2gray(image)), structuring_element)
|
||||
lena_path = Path(__file__).resolve().parent / "image_data" / "lena.jpg"
|
||||
lena = np.array(Image.open(lena_path))
|
||||
# kernel to be applied
|
||||
structuring_element = np.array([[0, 1, 0], [1, 1, 1], [0, 1, 0]])
|
||||
output = dilation(gray_to_binary(rgb_to_gray(lena)), structuring_element)
|
||||
# Save the output image
|
||||
pil_img = Image.fromarray(output).convert("RGB")
|
||||
pil_img.save("result_dilation.png")
|
||||
|
53
dynamic_programming/max_product_subarray.py
Normal file
53
dynamic_programming/max_product_subarray.py
Normal file
@ -0,0 +1,53 @@
|
||||
def max_product_subarray(numbers: list[int]) -> int:
|
||||
"""
|
||||
Returns the maximum product that can be obtained by multiplying a
|
||||
contiguous subarray of the given integer list `nums`.
|
||||
|
||||
Example:
|
||||
>>> max_product_subarray([2, 3, -2, 4])
|
||||
6
|
||||
>>> max_product_subarray((-2, 0, -1))
|
||||
0
|
||||
>>> max_product_subarray([2, 3, -2, 4, -1])
|
||||
48
|
||||
>>> max_product_subarray([-1])
|
||||
-1
|
||||
>>> max_product_subarray([0])
|
||||
0
|
||||
>>> max_product_subarray([])
|
||||
0
|
||||
>>> max_product_subarray("")
|
||||
0
|
||||
>>> max_product_subarray(None)
|
||||
0
|
||||
>>> max_product_subarray([2, 3, -2, 4.5, -1])
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: numbers must be an iterable of integers
|
||||
>>> max_product_subarray("ABC")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: numbers must be an iterable of integers
|
||||
"""
|
||||
if not numbers:
|
||||
return 0
|
||||
|
||||
if not isinstance(numbers, (list, tuple)) or not all(
|
||||
isinstance(number, int) for number in numbers
|
||||
):
|
||||
raise ValueError("numbers must be an iterable of integers")
|
||||
|
||||
max_till_now = min_till_now = max_prod = numbers[0]
|
||||
|
||||
for i in range(1, len(numbers)):
|
||||
# update the maximum and minimum subarray products
|
||||
number = numbers[i]
|
||||
if number < 0:
|
||||
max_till_now, min_till_now = min_till_now, max_till_now
|
||||
max_till_now = max(number, max_till_now * number)
|
||||
min_till_now = min(number, min_till_now * number)
|
||||
|
||||
# update the maximum product found till now
|
||||
max_prod = max(max_prod, max_till_now)
|
||||
|
||||
return max_prod
|
@ -1,8 +1,9 @@
|
||||
if __name__ == "__main__":
|
||||
import socket # Import socket module
|
||||
import socket
|
||||
|
||||
sock = socket.socket() # Create a socket object
|
||||
host = socket.gethostname() # Get local machine name
|
||||
|
||||
def main():
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
host = socket.gethostname()
|
||||
port = 12312
|
||||
|
||||
sock.connect((host, port))
|
||||
@ -13,11 +14,14 @@ if __name__ == "__main__":
|
||||
print("Receiving data...")
|
||||
while True:
|
||||
data = sock.recv(1024)
|
||||
print(f"{data = }")
|
||||
if not data:
|
||||
break
|
||||
out_file.write(data) # Write data to a file
|
||||
out_file.write(data)
|
||||
|
||||
print("Successfully got the file")
|
||||
print("Successfully received the file")
|
||||
sock.close()
|
||||
print("Connection closed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -17,6 +17,32 @@ from typing import Any
|
||||
import numpy as np
|
||||
|
||||
|
||||
def pass_and_relaxation(
|
||||
graph: dict,
|
||||
v: str,
|
||||
visited_forward: set,
|
||||
visited_backward: set,
|
||||
cst_fwd: dict,
|
||||
cst_bwd: dict,
|
||||
queue: PriorityQueue,
|
||||
parent: dict,
|
||||
shortest_distance: float | int,
|
||||
) -> float | int:
|
||||
for nxt, d in graph[v]:
|
||||
if nxt in visited_forward:
|
||||
continue
|
||||
old_cost_f = cst_fwd.get(nxt, np.inf)
|
||||
new_cost_f = cst_fwd[v] + d
|
||||
if new_cost_f < old_cost_f:
|
||||
queue.put((new_cost_f, nxt))
|
||||
cst_fwd[nxt] = new_cost_f
|
||||
parent[nxt] = v
|
||||
if nxt in visited_backward:
|
||||
if cst_fwd[v] + d + cst_bwd[nxt] < shortest_distance:
|
||||
shortest_distance = cst_fwd[v] + d + cst_bwd[nxt]
|
||||
return shortest_distance
|
||||
|
||||
|
||||
def bidirectional_dij(
|
||||
source: str, destination: str, graph_forward: dict, graph_backward: dict
|
||||
) -> int:
|
||||
@ -51,53 +77,36 @@ def bidirectional_dij(
|
||||
if source == destination:
|
||||
return 0
|
||||
|
||||
while queue_forward and queue_backward:
|
||||
while not queue_forward.empty():
|
||||
_, v_fwd = queue_forward.get()
|
||||
|
||||
if v_fwd not in visited_forward:
|
||||
break
|
||||
else:
|
||||
break
|
||||
while not queue_forward.empty() and not queue_backward.empty():
|
||||
_, v_fwd = queue_forward.get()
|
||||
visited_forward.add(v_fwd)
|
||||
|
||||
while not queue_backward.empty():
|
||||
_, v_bwd = queue_backward.get()
|
||||
|
||||
if v_bwd not in visited_backward:
|
||||
break
|
||||
else:
|
||||
break
|
||||
_, v_bwd = queue_backward.get()
|
||||
visited_backward.add(v_bwd)
|
||||
|
||||
# forward pass and relaxation
|
||||
for nxt_fwd, d_forward in graph_forward[v_fwd]:
|
||||
if nxt_fwd in visited_forward:
|
||||
continue
|
||||
old_cost_f = cst_fwd.get(nxt_fwd, np.inf)
|
||||
new_cost_f = cst_fwd[v_fwd] + d_forward
|
||||
if new_cost_f < old_cost_f:
|
||||
queue_forward.put((new_cost_f, nxt_fwd))
|
||||
cst_fwd[nxt_fwd] = new_cost_f
|
||||
parent_forward[nxt_fwd] = v_fwd
|
||||
if nxt_fwd in visited_backward:
|
||||
if cst_fwd[v_fwd] + d_forward + cst_bwd[nxt_fwd] < shortest_distance:
|
||||
shortest_distance = cst_fwd[v_fwd] + d_forward + cst_bwd[nxt_fwd]
|
||||
shortest_distance = pass_and_relaxation(
|
||||
graph_forward,
|
||||
v_fwd,
|
||||
visited_forward,
|
||||
visited_backward,
|
||||
cst_fwd,
|
||||
cst_bwd,
|
||||
queue_forward,
|
||||
parent_forward,
|
||||
shortest_distance,
|
||||
)
|
||||
|
||||
# backward pass and relaxation
|
||||
for nxt_bwd, d_backward in graph_backward[v_bwd]:
|
||||
if nxt_bwd in visited_backward:
|
||||
continue
|
||||
old_cost_b = cst_bwd.get(nxt_bwd, np.inf)
|
||||
new_cost_b = cst_bwd[v_bwd] + d_backward
|
||||
if new_cost_b < old_cost_b:
|
||||
queue_backward.put((new_cost_b, nxt_bwd))
|
||||
cst_bwd[nxt_bwd] = new_cost_b
|
||||
parent_backward[nxt_bwd] = v_bwd
|
||||
|
||||
if nxt_bwd in visited_forward:
|
||||
if cst_bwd[v_bwd] + d_backward + cst_fwd[nxt_bwd] < shortest_distance:
|
||||
shortest_distance = cst_bwd[v_bwd] + d_backward + cst_fwd[nxt_bwd]
|
||||
shortest_distance = pass_and_relaxation(
|
||||
graph_backward,
|
||||
v_bwd,
|
||||
visited_backward,
|
||||
visited_forward,
|
||||
cst_bwd,
|
||||
cst_fwd,
|
||||
queue_backward,
|
||||
parent_backward,
|
||||
shortest_distance,
|
||||
)
|
||||
|
||||
if cst_fwd[v_fwd] + cst_bwd[v_bwd] >= shortest_distance:
|
||||
break
|
||||
|
208
physics/grahams_law.py
Normal file
208
physics/grahams_law.py
Normal file
@ -0,0 +1,208 @@
|
||||
"""
|
||||
Title: Graham's Law of Effusion
|
||||
|
||||
Description: Graham's law of effusion states that the rate of effusion of a gas is
|
||||
inversely proportional to the square root of the molar mass of its particles:
|
||||
|
||||
r1/r2 = sqrt(m2/m1)
|
||||
|
||||
r1 = Rate of effusion for the first gas.
|
||||
r2 = Rate of effusion for the second gas.
|
||||
m1 = Molar mass of the first gas.
|
||||
m2 = Molar mass of the second gas.
|
||||
|
||||
(Description adapted from https://en.wikipedia.org/wiki/Graham%27s_law)
|
||||
"""
|
||||
|
||||
from math import pow, sqrt
|
||||
|
||||
|
||||
def validate(*values: float) -> bool:
|
||||
"""
|
||||
Input Parameters:
|
||||
-----------------
|
||||
effusion_rate_1: Effustion rate of first gas (m^2/s, mm^2/s, etc.)
|
||||
effusion_rate_2: Effustion rate of second gas (m^2/s, mm^2/s, etc.)
|
||||
molar_mass_1: Molar mass of the first gas (g/mol, kg/kmol, etc.)
|
||||
molar_mass_2: Molar mass of the second gas (g/mol, kg/kmol, etc.)
|
||||
|
||||
Returns:
|
||||
--------
|
||||
>>> validate(2.016, 4.002)
|
||||
True
|
||||
>>> validate(-2.016, 4.002)
|
||||
False
|
||||
>>> validate()
|
||||
False
|
||||
"""
|
||||
result = len(values) > 0 and all(value > 0.0 for value in values)
|
||||
return result
|
||||
|
||||
|
||||
def effusion_ratio(molar_mass_1: float, molar_mass_2: float) -> float | ValueError:
|
||||
"""
|
||||
Input Parameters:
|
||||
-----------------
|
||||
molar_mass_1: Molar mass of the first gas (g/mol, kg/kmol, etc.)
|
||||
molar_mass_2: Molar mass of the second gas (g/mol, kg/kmol, etc.)
|
||||
|
||||
Returns:
|
||||
--------
|
||||
>>> effusion_ratio(2.016, 4.002)
|
||||
1.408943
|
||||
>>> effusion_ratio(-2.016, 4.002)
|
||||
ValueError('Input Error: Molar mass values must greater than 0.')
|
||||
>>> effusion_ratio(2.016)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: effusion_ratio() missing 1 required positional argument: 'molar_mass_2'
|
||||
"""
|
||||
return (
|
||||
round(sqrt(molar_mass_2 / molar_mass_1), 6)
|
||||
if validate(molar_mass_1, molar_mass_2)
|
||||
else ValueError("Input Error: Molar mass values must greater than 0.")
|
||||
)
|
||||
|
||||
|
||||
def first_effusion_rate(
|
||||
effusion_rate: float, molar_mass_1: float, molar_mass_2: float
|
||||
) -> float | ValueError:
|
||||
"""
|
||||
Input Parameters:
|
||||
-----------------
|
||||
effusion_rate: Effustion rate of second gas (m^2/s, mm^2/s, etc.)
|
||||
molar_mass_1: Molar mass of the first gas (g/mol, kg/kmol, etc.)
|
||||
molar_mass_2: Molar mass of the second gas (g/mol, kg/kmol, etc.)
|
||||
|
||||
Returns:
|
||||
--------
|
||||
>>> first_effusion_rate(1, 2.016, 4.002)
|
||||
1.408943
|
||||
>>> first_effusion_rate(-1, 2.016, 4.002)
|
||||
ValueError('Input Error: Molar mass and effusion rate values must greater than 0.')
|
||||
>>> first_effusion_rate(1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: first_effusion_rate() missing 2 required positional arguments: \
|
||||
'molar_mass_1' and 'molar_mass_2'
|
||||
>>> first_effusion_rate(1, 2.016)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: first_effusion_rate() missing 1 required positional argument: \
|
||||
'molar_mass_2'
|
||||
"""
|
||||
return (
|
||||
round(effusion_rate * sqrt(molar_mass_2 / molar_mass_1), 6)
|
||||
if validate(effusion_rate, molar_mass_1, molar_mass_2)
|
||||
else ValueError(
|
||||
"Input Error: Molar mass and effusion rate values must greater than 0."
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def second_effusion_rate(
|
||||
effusion_rate: float, molar_mass_1: float, molar_mass_2: float
|
||||
) -> float | ValueError:
|
||||
"""
|
||||
Input Parameters:
|
||||
-----------------
|
||||
effusion_rate: Effustion rate of second gas (m^2/s, mm^2/s, etc.)
|
||||
molar_mass_1: Molar mass of the first gas (g/mol, kg/kmol, etc.)
|
||||
molar_mass_2: Molar mass of the second gas (g/mol, kg/kmol, etc.)
|
||||
|
||||
Returns:
|
||||
--------
|
||||
>>> second_effusion_rate(1, 2.016, 4.002)
|
||||
0.709752
|
||||
>>> second_effusion_rate(-1, 2.016, 4.002)
|
||||
ValueError('Input Error: Molar mass and effusion rate values must greater than 0.')
|
||||
>>> second_effusion_rate(1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: second_effusion_rate() missing 2 required positional arguments: \
|
||||
'molar_mass_1' and 'molar_mass_2'
|
||||
>>> second_effusion_rate(1, 2.016)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: second_effusion_rate() missing 1 required positional argument: \
|
||||
'molar_mass_2'
|
||||
"""
|
||||
return (
|
||||
round(effusion_rate / sqrt(molar_mass_2 / molar_mass_1), 6)
|
||||
if validate(effusion_rate, molar_mass_1, molar_mass_2)
|
||||
else ValueError(
|
||||
"Input Error: Molar mass and effusion rate values must greater than 0."
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def first_molar_mass(
|
||||
molar_mass: float, effusion_rate_1: float, effusion_rate_2: float
|
||||
) -> float | ValueError:
|
||||
"""
|
||||
Input Parameters:
|
||||
-----------------
|
||||
molar_mass: Molar mass of the first gas (g/mol, kg/kmol, etc.)
|
||||
effusion_rate_1: Effustion rate of first gas (m^2/s, mm^2/s, etc.)
|
||||
effusion_rate_2: Effustion rate of second gas (m^2/s, mm^2/s, etc.)
|
||||
|
||||
Returns:
|
||||
--------
|
||||
>>> first_molar_mass(2, 1.408943, 0.709752)
|
||||
0.507524
|
||||
>>> first_molar_mass(-1, 2.016, 4.002)
|
||||
ValueError('Input Error: Molar mass and effusion rate values must greater than 0.')
|
||||
>>> first_molar_mass(1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: first_molar_mass() missing 2 required positional arguments: \
|
||||
'effusion_rate_1' and 'effusion_rate_2'
|
||||
>>> first_molar_mass(1, 2.016)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: first_molar_mass() missing 1 required positional argument: \
|
||||
'effusion_rate_2'
|
||||
"""
|
||||
return (
|
||||
round(molar_mass / pow(effusion_rate_1 / effusion_rate_2, 2), 6)
|
||||
if validate(molar_mass, effusion_rate_1, effusion_rate_2)
|
||||
else ValueError(
|
||||
"Input Error: Molar mass and effusion rate values must greater than 0."
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def second_molar_mass(
|
||||
molar_mass: float, effusion_rate_1: float, effusion_rate_2: float
|
||||
) -> float | ValueError:
|
||||
"""
|
||||
Input Parameters:
|
||||
-----------------
|
||||
molar_mass: Molar mass of the first gas (g/mol, kg/kmol, etc.)
|
||||
effusion_rate_1: Effustion rate of first gas (m^2/s, mm^2/s, etc.)
|
||||
effusion_rate_2: Effustion rate of second gas (m^2/s, mm^2/s, etc.)
|
||||
|
||||
Returns:
|
||||
--------
|
||||
>>> second_molar_mass(2, 1.408943, 0.709752)
|
||||
1.970351
|
||||
>>> second_molar_mass(-2, 1.408943, 0.709752)
|
||||
ValueError('Input Error: Molar mass and effusion rate values must greater than 0.')
|
||||
>>> second_molar_mass(1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: second_molar_mass() missing 2 required positional arguments: \
|
||||
'effusion_rate_1' and 'effusion_rate_2'
|
||||
>>> second_molar_mass(1, 2.016)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
TypeError: second_molar_mass() missing 1 required positional argument: \
|
||||
'effusion_rate_2'
|
||||
"""
|
||||
return (
|
||||
round(pow(effusion_rate_1 / effusion_rate_2, 2) / molar_mass, 6)
|
||||
if validate(molar_mass, effusion_rate_1, effusion_rate_2)
|
||||
else ValueError(
|
||||
"Input Error: Molar mass and effusion rate values must greater than 0."
|
||||
)
|
||||
)
|
@ -10,7 +10,7 @@ The solutions will be checked by our [automated testing on GitHub Actions](https
|
||||
|
||||
## Solution Guidelines
|
||||
|
||||
Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before reading the solution guidelines, make sure you read the whole [Contributing Guidelines](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md) as it won't be repeated in here. If you have any doubt on the guidelines, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://app.gitter.im/#/room/#TheAlgorithms_community:gitter.im). You can use the [template](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#solution-template) we have provided below as your starting point but be sure to read the [Coding Style](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#coding-style) part first.
|
||||
Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before reading the solution guidelines, make sure you read the whole [Contributing Guidelines](https://github.com/TheAlgorithms/Python/blob/master/CONTRIBUTING.md) as it won't be repeated in here. If you have any doubt on the guidelines, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms/community). You can use the [template](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#solution-template) we have provided below as your starting point but be sure to read the [Coding Style](https://github.com/TheAlgorithms/Python/blob/master/project_euler/README.md#coding-style) part first.
|
||||
|
||||
### Coding Style
|
||||
|
||||
|
0
project_euler/problem_094/__init__.py
Normal file
0
project_euler/problem_094/__init__.py
Normal file
44
project_euler/problem_094/sol1.py
Normal file
44
project_euler/problem_094/sol1.py
Normal file
@ -0,0 +1,44 @@
|
||||
"""
|
||||
Project Euler Problem 94: https://projecteuler.net/problem=94
|
||||
|
||||
It is easily proved that no equilateral triangle exists with integral length sides and
|
||||
integral area. However, the almost equilateral triangle 5-5-6 has an area of 12 square
|
||||
units.
|
||||
|
||||
We shall define an almost equilateral triangle to be a triangle for which two sides are
|
||||
equal and the third differs by no more than one unit.
|
||||
|
||||
Find the sum of the perimeters of all almost equilateral triangles with integral side
|
||||
lengths and area and whose perimeters do not exceed one billion (1,000,000,000).
|
||||
"""
|
||||
|
||||
|
||||
def solution(max_perimeter: int = 10**9) -> int:
|
||||
"""
|
||||
Returns the sum of the perimeters of all almost equilateral triangles with integral
|
||||
side lengths and area and whose perimeters do not exceed max_perimeter
|
||||
|
||||
>>> solution(20)
|
||||
16
|
||||
"""
|
||||
|
||||
prev_value = 1
|
||||
value = 2
|
||||
|
||||
perimeters_sum = 0
|
||||
i = 0
|
||||
perimeter = 0
|
||||
while perimeter <= max_perimeter:
|
||||
perimeters_sum += perimeter
|
||||
|
||||
prev_value += 2 * value
|
||||
value += prev_value
|
||||
|
||||
perimeter = 2 * value + 2 if i % 2 == 0 else 2 * value - 2
|
||||
i += 1
|
||||
|
||||
return perimeters_sum
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"{solution() = }")
|
0
project_euler/problem_187/__init__.py
Normal file
0
project_euler/problem_187/__init__.py
Normal file
58
project_euler/problem_187/sol1.py
Normal file
58
project_euler/problem_187/sol1.py
Normal file
@ -0,0 +1,58 @@
|
||||
"""
|
||||
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() = }")
|
0
project_euler/problem_800/__init__.py
Normal file
0
project_euler/problem_800/__init__.py
Normal file
65
project_euler/problem_800/sol1.py
Normal file
65
project_euler/problem_800/sol1.py
Normal file
@ -0,0 +1,65 @@
|
||||
"""
|
||||
Project Euler Problem 800: https://projecteuler.net/problem=800
|
||||
|
||||
An integer of the form p^q q^p with prime numbers p != q is called a hybrid-integer.
|
||||
For example, 800 = 2^5 5^2 is a hybrid-integer.
|
||||
|
||||
We define C(n) to be the number of hybrid-integers less than or equal to n.
|
||||
You are given C(800) = 2 and C(800^800) = 10790
|
||||
|
||||
Find C(800800^800800)
|
||||
"""
|
||||
|
||||
from math import isqrt, log2
|
||||
|
||||
|
||||
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(base: int = 800800, degree: int = 800800) -> int:
|
||||
"""
|
||||
Returns the number of hybrid-integers less than or equal to base^degree
|
||||
|
||||
>>> solution(800, 1)
|
||||
2
|
||||
|
||||
>>> solution(800, 800)
|
||||
10790
|
||||
"""
|
||||
|
||||
upper_bound = degree * log2(base)
|
||||
max_prime = int(upper_bound)
|
||||
prime_numbers = calculate_prime_numbers(max_prime)
|
||||
|
||||
hybrid_integers_count = 0
|
||||
left = 0
|
||||
right = len(prime_numbers) - 1
|
||||
while left < right:
|
||||
while (
|
||||
prime_numbers[right] * log2(prime_numbers[left])
|
||||
+ prime_numbers[left] * log2(prime_numbers[right])
|
||||
> upper_bound
|
||||
):
|
||||
right -= 1
|
||||
hybrid_integers_count += right - left
|
||||
left += 1
|
||||
|
||||
return hybrid_integers_count
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"{solution() = }")
|
@ -61,7 +61,7 @@ show-source = true
|
||||
target-version = "py311"
|
||||
|
||||
[tool.ruff.mccabe] # DO NOT INCREASE THIS VALUE
|
||||
max-complexity = 20 # default: 10
|
||||
max-complexity = 17 # default: 10
|
||||
|
||||
[tool.ruff.pylint] # DO NOT INCREASE THESE VALUES
|
||||
max-args = 10 # default: 5
|
||||
|
@ -723,5 +723,112 @@
|
||||
"722": "9687101dfe209fd65f57a10603baa38ba83c9152e43a8b802b96f1e07f568e0e",
|
||||
"723": "74832787e7d4e0cb7991256c8f6d02775dffec0684de234786f25f898003f2de",
|
||||
"724": "fa05e2b497e7eafa64574017a4c45aadef6b163d907b03d63ba3f4021096d329",
|
||||
"725": "005c873563f51bbebfdb1f8dbc383259e9a98e506bc87ae8d8c9044b81fc6418"
|
||||
"725": "005c873563f51bbebfdb1f8dbc383259e9a98e506bc87ae8d8c9044b81fc6418",
|
||||
"726": "93e41c533136bf4b436e493090fd4e7b277234db2a69c62a871f775ff26681bf",
|
||||
"727": "c366f7426ca9351dcdde2e3bea01181897cda4d9b44977678ea3828419b84851",
|
||||
"728": "8de62a644511d27c7c23c7722f56112b3c1ab9b05a078a98a0891f09f92464c6",
|
||||
"729": "0ae82177174eef99fc80a2ec921295f61a6ac4dfed86a1bf333a50c26d01955c",
|
||||
"730": "78cd876a176c8fbf7c2155b80dccbdededdbc43c28ef17b5a6e554d649325d38",
|
||||
"731": "54afb9f829be51d29f90eecbfe40e5ba91f3a3bf538de62f3e34674af15eb542",
|
||||
"732": "c4dc4610dcafc806b30e5d3f5560b57f462218a04397809843a7110838f0ebac",
|
||||
"733": "bdde7d98d057d6a6ae360fd2f872d8bccb7e7f2971df37a3c5f20712ea3c618f",
|
||||
"734": "9a514875bd9af26fcc565337771f852d311cd77033186e4d957e7b6c7b8ce018",
|
||||
"735": "8bbc5a27c0031d8c44f3f73c99622a202cd6ea9a080049d615a7ae80ce6024f9",
|
||||
"736": "e0d4c78b9b3dae51940877aff28275d036eccfc641111c8e34227ff6015a0fab",
|
||||
"737": "a600884bcaa01797310c83b198bad58c98530289305af29b0bf75f679af38d3a",
|
||||
"738": "c85f15fdaafe7d5525acff960afef7e4b8ffded5a7ee0d1dc2b0e8d0c26b9b46",
|
||||
"739": "8716e9302f0fb90153e2f522bd88a710361a897480e4ccc0542473c704793518",
|
||||
"740": "6ff41ee34b263b742cda109aee3be9ad6c95eec2ce31d6a9fc5353bba1b41afd",
|
||||
"741": "99ac0eb9589b895e5755895206bbad5febd6bc29b2912df1c7544c547e26bca3",
|
||||
"742": "7d2761a240aa577348df4813ea248088d0d6d8d421142c712ed576cdc90d4df9",
|
||||
"743": "d93c42a129c0961b4e36738efae3b7e8ffae3a4daeced20e85bb740d3d72522d",
|
||||
"744": "211f76700a010461486dde6c723720be85e68c192cd8a8ed0a88860b8ae9b0f0",
|
||||
"745": "2d32dc1fea2f1b8600c0ada927b057b566870ceb5362cce71ac3693dcb7136ae",
|
||||
"746": "2df1c2a0181f0c25e8d13d2a1eadba55a6b06267a2b22075fcf6867fb2e10c02",
|
||||
"747": "a8d8f93142e320c6f0dd386c7a3bfb011bbdc15b85291a9be8f0266b3608175e",
|
||||
"748": "7de937e04c10386b240afb8bb2ff590009946df8b7850a0329ccdb59fca8955f",
|
||||
"749": "1a55f5484ccf964aeb186faedefa01db05d87180891dc2280b6eb85b6efb4779",
|
||||
"750": "fa4318c213179e6af1c949be7cf47210f4383e0a44d191e2bad44228d3192f14",
|
||||
"751": "12fe650fcb3afc214b3d647c655070e8142cfd397441fc7636ad7e6ffcaefde2",
|
||||
"752": "e416c0123bc6b82df8726b328494db31aa4781d938a0a6e2107b1e44c73c0434",
|
||||
"753": "0ee3299bc89e1e4c2fc79285fb1cd84c887456358a825e56be92244b7115f5af",
|
||||
"754": "1370574b16207c41d3dafb62aa898379ec101ac36843634b1633b7b509d4c35a",
|
||||
"755": "78bb4b18b13f5254cfafe872c0e93791ab5206b2851960dc6aebea8f62b9580c",
|
||||
"756": "6becaabbda2e9ea22373e62e989b6b70467efa24fbe2f0d124d7a99a53e93f74",
|
||||
"757": "fbfee0a5c4fa57a1dd6cf0c9bb2423cf7e7bcb130e67114aa360e42234987314",
|
||||
"758": "8e4dfc259cec9dfd89d4b4ac8c33c75af6e0f5f7926526ee22ad4d45f93d3c18",
|
||||
"759": "40bac0ed2e4f7861a6d9a2d87191a9034e177c319aa40a43638cc1b69572e5f2",
|
||||
"760": "7ab50386a211f0815593389ab05b57a1a5eb5cbf5b9a85fe4afc517dcab74e06",
|
||||
"761": "1cdb0318ac16e11c8d2ae7b1d7ca7138f7b1a461e9d75bd69be0f9cdd3add0c5",
|
||||
"762": "84c4662267d5809380a540dfc2881665b3019047d74d5ef0a01f86e45f4b5b59",
|
||||
"763": "f0def5903139447fabe7d106db5fff660d94b45af7b8b48d789596cf65ab2514",
|
||||
"764": "7b4131f4d1e13d091ca7dd4d32317a14a2a24e6e1abd214df1c14c215287b330",
|
||||
"765": "7558b775727426bccd945f5aa6b3e131e6034a7b1ff8576332329ef65d6a1663",
|
||||
"766": "23c309430fa9546adb617457dbfd30fb7432904595c8c000e9b67ea23f32a53b",
|
||||
"767": "70aef22ac2db8a5bdfcc42ff8dafbd2901e85e268f5f3c45085aa40c590b1d42",
|
||||
"768": "b69a808dfc654b037e2f47ace16f48fe3bb553b3c8eed3e2b6421942fbf521d0",
|
||||
"769": "78537a30577e806c6d8d94725e54d2d52e56f7f39f89c133cd5d0a2aad7e46e4",
|
||||
"770": "c9d80c19c4895d1498bf809fcc37c447fa961fb325e5667eb35d6aa992966b41",
|
||||
"771": "9803ace30c0d90d422e703fdf25a10a9342d0178a277ebc20c7bd6feac4c7a15",
|
||||
"772": "f5a1e391af815ea6453db58a1bd71790f433c44ed63e5e93d8f5c045dfd5a464",
|
||||
"773": "e1b93fc323c4d9c383100603339548e1e56ce9c38bcdcc425024c12b862ea8cb",
|
||||
"774": "3646cd098b213014fb7bbc9597871585e62ee0cf2770e141f1df771237cc09ab",
|
||||
"775": "d9d7d515ce7350c9e5696d85f68bbb42daa74b9e171a601dd04c823b18bb7757",
|
||||
"776": "83286074d3bc86a5b449facb5fe5eafc91eb4c8031e2fb5e716443402cd8ed0f",
|
||||
"777": "e62616a387d05b619d47cee3d49d5d2db19393736bf54b6cdd20933c0531cb7e",
|
||||
"778": "d4de958ba44d25353de5b380e04d06c7968794ad50dbf6231ad0049ff53e106b",
|
||||
"779": "c08ce54a59afc4af62f28b80a9c9a5190822d124eed8d73fd6db3e19c81e2157",
|
||||
"780": "fc7ba646c16482f0f4f5ce2b06d21183dba2bdeaf9469b36b55bc7bc2d87baf3",
|
||||
"781": "8fa5733f06838fb61b55b3e9d59c5061d922147e59947fe52e566dd975b2199f",
|
||||
"782": "9f757d92df401ee049bc066bb2625c6287e5e4bcd38c958396a77a578f036a24",
|
||||
"783": "270ff37f60c267a673bd4b223e44941f01ae9cfbf6bbdf99ca57af89b1e9a66f",
|
||||
"784": "388b17c4c7b829cef767f83b4686c903faeec1241edfe5f58ee91d2b0c7f8dfc",
|
||||
"785": "77cf600204c5265e1d5d3d26bf28ba1e92e6f24def040c16977450bec8b1cb99",
|
||||
"786": "fb14022b7edbc6c7bfde27f35b49f6acaa4f0fc383af27614cb9d4a1980e626b",
|
||||
"787": "7516ba0ac1951665723dcc4adcc52764d9497e7b6ed30bdb9937ac9df82b7c4f",
|
||||
"788": "adede1d30258bb0f353af11f559b67f8b823304c71e967f52db52d002760c24f",
|
||||
"789": "0c82e744a1f9bc57fd8ae8b2f479998455bc45126de971c59b68541c254e303a",
|
||||
"790": "319847122251afd20d4d650047c55981a509fa2be78abd7c9c3caa0555e60a05",
|
||||
"791": "2e0bbdcd0a8460e1e33c55668d0dc9752379a78b9f3561d7a17b922a5541a3fb",
|
||||
"792": "5f77834c5a509023dd95dd98411eae1dd4bafd125deca590632f409f92fd257b",
|
||||
"793": "dbfd900a3b31eeec2f14b916f5151611541cb716d80b7b9a1229de12293a02ea",
|
||||
"794": "d019fe415aba832c4c761140d60c466c9aaad52b504df3167c17f2d3f0b277a7",
|
||||
"795": "617b259349da44c2af2664acde113673ab3bb03a85d31f1be8f01027d0ebd4d3",
|
||||
"796": "cba6b30a818d073398e5802211987f0897523e4752987bb445b2bca079670e22",
|
||||
"797": "61e42cac3d7858b8850111a8c64c56432a18dd058dfb6afd773f07d703703b1a",
|
||||
"798": "ae8b155d6b77522af79f7e4017fefe92aaa5d45eff132c83dc4d4bcfc9686020",
|
||||
"799": "a41cb14ddf8f1948a01f590fbe53d9ca4e2faf48375ce1c306f91acf7c94e005",
|
||||
"800": "c6a47bc6f02cf06be16728fb308c83f2f2ae350325ef7016867f5bdaea849d71",
|
||||
"801": "d14b358c76b55106613f9c0a2112393338dfd01513b0fd231b79fc8db20e41f0",
|
||||
"802": "22ae33e67fb48accfaa3b36e70c5a19066b974194c3130680de0c7cdce2d0f2e",
|
||||
"803": "d95b3f9bbb7054042c1fba4db02f7223a2dad94977a36f08c8aaf92f373f9e78",
|
||||
"804": "b0b1cf7253593eb2334c75e66dbe22b4b4540347485f1ea24e80226b4b18171c",
|
||||
"805": "41b1ff5db0e70984ad20c50d1a9ac2b5a53ccd5f42796c8e948ae8880005fbb9",
|
||||
"806": "b9c813beb39671adb8e1530555cadca44c21ddc7127932274918df2091dbd9ca",
|
||||
"807": "745fd9ba97970d85a29877942839e41fc192794420e86f3bde39fd26db7a8bff",
|
||||
"808": "6c73b947eb603602a7e8afadc83eaaa381a46db8b82a6fb89c9c1d93cb023fce",
|
||||
"809": "eebac7753da4c1230dfce0f15fc124ffff01b0e432f0b74623b60cff71bbc9a9",
|
||||
"810": "42be7899672a1a0046823603ce60dbeda7250a56fcb8d0913093850c85394307",
|
||||
"811": "8698cd28ae4d93db36631870c33e4a8a527d970050d994666115f54260b64138",
|
||||
"812": "dc2495924f37353db8b846323b8085fae9db502e890c513ed2e64ed7281f567f",
|
||||
"813": "92179dde05aa6557baca65699fda50ca024d33a77078d8e128caa3c5db84064b",
|
||||
"814": "344ed8cb7684307c00b7f03d751729a7f9d2a5f4a4cb4574594113d69593c0c1",
|
||||
"815": "f642cf15345af3feab60e26a02aee038f759914906a5b2b469b46fdeee50ff59",
|
||||
"816": "058178444e85f2aedb2f75d824a469747381f0bd3235d8c72df4385fec86eb07",
|
||||
"817": "582fdc2233298192b09ceaf1463d6be06a09894075532630aa9d9efcfcb31da4",
|
||||
"818": "67f6964d6ff114a43371b8375c44db2f1362df4f110b4a7ce8d79cf1b76621a0",
|
||||
"819": "c7a82513ad48dfc87f2c1e0f2915b71464b7f5a16501c71df4ae4a8741dceef3",
|
||||
"820": "9b23ae0181f320aadda2637ac2179c8b41b00715630c3acb643c7aee3b81cf90",
|
||||
"821": "0941e396ff15b98fd7827de8e33ef94996d48ba719a88ba8e2da7f2605df3e5c",
|
||||
"822": "ed8ef7f568939b9df1b77ae58344940b91c7e154a4367fe2b179bc7b9484d4e6",
|
||||
"823": "05139328571a86096032b57e3a6a02a61acad4fb0d8f8e1b5d0ffb0d063ba697",
|
||||
"826": "7f40f14ca65e5c06dd9ec9bbb212adb4d97a503199cb3c30ed921a04373bbe1c",
|
||||
"827": "80461f02c63654c642382a6ffb7a44d0a3554434dfcfcea00ba91537724c7106",
|
||||
"828": "520c196175625a0230afb76579ea26033372de3ef4c78aceb146b84322bfa871",
|
||||
"829": "ed0089e61cf5540dd4a8fef1c468b96cf57f1d2bb79968755ba856d547ddafdf",
|
||||
"831": "8ec445084427419ca6da405e0ded9814a4b4e11a2be84d88a8dea421f8e49992",
|
||||
"832": "cfcb9ebef9308823f64798b5e12a59bf77ff6f92b0eae3790a61c0a26f577010",
|
||||
"833": "e6ff3a5b257eb53366a32bfc8ea410a00a78bafa63650c76ac2bceddfbb42ff5",
|
||||
"834": "b0d2a7e7d629ef14db9e7352a9a06d6ca66f750429170bb169ca52c172b8cc96",
|
||||
"835": "bdfa1b1eecbad79f5de48bc6daee4d2b07689d7fb172aa306dd6094172b396f0"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user