This commit is contained in:
MaximSmolskiy 2024-08-25 15:19:00 +03:00
commit e6790b5407
46 changed files with 188 additions and 206 deletions

View File

@ -16,7 +16,7 @@ repos:
- id: auto-walrus - id: auto-walrus
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.7 rev: v0.5.7
hooks: hooks:
- id: ruff - id: ruff
- id: ruff-format - id: ruff-format
@ -29,7 +29,7 @@ repos:
- tomli - tomli
- repo: https://github.com/tox-dev/pyproject-fmt - repo: https://github.com/tox-dev/pyproject-fmt
rev: "2.1.3" rev: "2.2.1"
hooks: hooks:
- id: pyproject-fmt - id: pyproject-fmt
@ -47,10 +47,11 @@ repos:
- id: validate-pyproject - id: validate-pyproject
- repo: https://github.com/pre-commit/mirrors-mypy - repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.0 rev: v1.11.1
hooks: hooks:
- id: mypy - id: mypy
args: args:
- --explicit-package-bases
- --ignore-missing-imports - --ignore-missing-imports
- --install-types # See mirrors-mypy README.md - --install-types # See mirrors-mypy README.md
- --non-interactive - --non-interactive

View File

@ -540,8 +540,7 @@
* [Lu Decomposition](linear_algebra/lu_decomposition.py) * [Lu Decomposition](linear_algebra/lu_decomposition.py)
* Src * Src
* [Conjugate Gradient](linear_algebra/src/conjugate_gradient.py) * [Conjugate Gradient](linear_algebra/src/conjugate_gradient.py)
* Gaussian Elimination Pivoting * [Gaussian Elimination Pivoting](linear_algebra/src/gaussian_elimination_pivoting.py)
* [Gaussian Elimination Pivoting](linear_algebra/src/gaussian_elimination_pivoting/gaussian_elimination_pivoting.py)
* [Lib](linear_algebra/src/lib.py) * [Lib](linear_algebra/src/lib.py)
* [Polynom For Points](linear_algebra/src/polynom_for_points.py) * [Polynom For Points](linear_algebra/src/polynom_for_points.py)
* [Power Iteration](linear_algebra/src/power_iteration.py) * [Power Iteration](linear_algebra/src/power_iteration.py)
@ -863,6 +862,7 @@
* [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py) * [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py)
* [Photoelectric Effect](physics/photoelectric_effect.py) * [Photoelectric Effect](physics/photoelectric_effect.py)
* [Potential Energy](physics/potential_energy.py) * [Potential Energy](physics/potential_energy.py)
* [Rainfall Intensity](physics/rainfall_intensity.py)
* [Reynolds Number](physics/reynolds_number.py) * [Reynolds Number](physics/reynolds_number.py)
* [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py) * [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py)
* [Shear Stress](physics/shear_stress.py) * [Shear Stress](physics/shear_stress.py)
@ -1259,6 +1259,7 @@
* [Can String Be Rearranged As Palindrome](strings/can_string_be_rearranged_as_palindrome.py) * [Can String Be Rearranged As Palindrome](strings/can_string_be_rearranged_as_palindrome.py)
* [Capitalize](strings/capitalize.py) * [Capitalize](strings/capitalize.py)
* [Check Anagrams](strings/check_anagrams.py) * [Check Anagrams](strings/check_anagrams.py)
* [Count Vowels](strings/count_vowels.py)
* [Credit Card Validator](strings/credit_card_validator.py) * [Credit Card Validator](strings/credit_card_validator.py)
* [Damerau Levenshtein Distance](strings/damerau_levenshtein_distance.py) * [Damerau Levenshtein Distance](strings/damerau_levenshtein_distance.py)
* [Detecting English Programmatically](strings/detecting_english_programmatically.py) * [Detecting English Programmatically](strings/detecting_english_programmatically.py)

View File

@ -24,10 +24,10 @@ def get_valid_pos(position: tuple[int, int], n: int) -> list[tuple[int, int]]:
] ]
permissible_positions = [] permissible_positions = []
for position in positions: for inner_position in positions:
y_test, x_test = position y_test, x_test = inner_position
if 0 <= y_test < n and 0 <= x_test < n: if 0 <= y_test < n and 0 <= x_test < n:
permissible_positions.append(position) permissible_positions.append(inner_position)
return permissible_positions return permissible_positions

View File

@ -141,7 +141,7 @@ def transform(
center_x, center_y = (x // 2 for x in kernel.shape) center_x, center_y = (x // 2 for x in kernel.shape)
# Use padded image when applying convolotion # Use padded image when applying convolution
# to not go out of bounds of the original the image # to not go out of bounds of the original the image
transformed = np.zeros(image.shape, dtype=np.uint8) transformed = np.zeros(image.shape, dtype=np.uint8)
padded = np.pad(image, 1, "constant", constant_values=constant) padded = np.pad(image, 1, "constant", constant_values=constant)

View File

@ -297,6 +297,12 @@ def weight_conversion(from_type: str, to_type: str, value: float) -> float:
1.660540199e-23 1.660540199e-23
>>> weight_conversion("atomic-mass-unit","atomic-mass-unit",2) >>> weight_conversion("atomic-mass-unit","atomic-mass-unit",2)
1.999999998903455 1.999999998903455
>>> weight_conversion("slug", "kilogram", 1)
Traceback (most recent call last):
...
ValueError: Invalid 'from_type' or 'to_type' value: 'slug', 'kilogram'
Supported values are: kilogram, gram, milligram, metric-ton, long-ton, short-ton, \
pound, stone, ounce, carrat, atomic-mass-unit
""" """
if to_type not in KILOGRAM_CHART or from_type not in WEIGHT_TYPE_CHART: if to_type not in KILOGRAM_CHART or from_type not in WEIGHT_TYPE_CHART:
msg = ( msg = (

View File

@ -80,9 +80,9 @@ class Node:
""" """
if self.left and (self.data < self.left.data or not self.left.is_sorted): if self.left and (self.data < self.left.data or not self.left.is_sorted):
return False return False
if self.right and (self.data > self.right.data or not self.right.is_sorted): return not (
return False self.right and (self.data > self.right.data or not self.right.is_sorted)
return True )
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,8 +1,3 @@
"""
psf/black : true
ruff : passed
"""
from __future__ import annotations from __future__ import annotations
from collections.abc import Iterator from collections.abc import Iterator
@ -321,9 +316,7 @@ class RedBlackTree:
return False return False
if self.left and not self.left.check_coloring(): if self.left and not self.left.check_coloring():
return False return False
if self.right and not self.right.check_coloring(): return not (self.right and not self.right.check_coloring())
return False
return True
def black_height(self) -> int | None: def black_height(self) -> int | None:
"""Returns the number of black nodes from this node to the """Returns the number of black nodes from this node to the
@ -561,9 +554,7 @@ def test_rotations() -> bool:
right_rot.right.right = RedBlackTree(10, parent=right_rot.right) right_rot.right.right = RedBlackTree(10, parent=right_rot.right)
right_rot.right.right.left = RedBlackTree(5, parent=right_rot.right.right) right_rot.right.right.left = RedBlackTree(5, parent=right_rot.right.right)
right_rot.right.right.right = RedBlackTree(20, parent=right_rot.right.right) right_rot.right.right.right = RedBlackTree(20, parent=right_rot.right.right)
if tree != right_rot: return tree == right_rot
return False
return True
def test_insertion_speed() -> bool: def test_insertion_speed() -> bool:
@ -606,13 +597,11 @@ def test_insert_and_search() -> bool:
tree.insert(12) tree.insert(12)
tree.insert(10) tree.insert(10)
tree.insert(11) tree.insert(11)
if 5 in tree or -6 in tree or -10 in tree or 13 in tree: if any(i in tree for i in (5, -6, -10, 13)):
# Found something not in there # Found something not in there
return False return False
if not (11 in tree and 12 in tree and -8 in tree and 0 in tree): # Find all these things in there
# Didn't find something in there return all(i in tree for i in (11, 12, -8, 0))
return False
return True
def test_insert_delete() -> bool: def test_insert_delete() -> bool:
@ -634,9 +623,7 @@ def test_insert_delete() -> bool:
tree = tree.remove(9) tree = tree.remove(9)
if not tree.check_color_properties(): if not tree.check_color_properties():
return False return False
if list(tree.inorder_traverse()) != [-8, 0, 4, 8, 10, 11, 12]: return list(tree.inorder_traverse()) == [-8, 0, 4, 8, 10, 11, 12]
return False
return True
def test_floor_ceil() -> bool: def test_floor_ceil() -> bool:
@ -664,9 +651,7 @@ def test_min_max() -> bool:
tree.insert(24) tree.insert(24)
tree.insert(20) tree.insert(20)
tree.insert(22) tree.insert(22)
if tree.get_max() != 22 or tree.get_min() != -16: return not (tree.get_max() != 22 or tree.get_min() != -16)
return False
return True
def test_tree_traversal() -> bool: def test_tree_traversal() -> bool:
@ -682,9 +667,7 @@ def test_tree_traversal() -> bool:
return False return False
if list(tree.preorder_traverse()) != [0, -16, 16, 8, 22, 20, 24]: if list(tree.preorder_traverse()) != [0, -16, 16, 8, 22, 20, 24]:
return False return False
if list(tree.postorder_traverse()) != [-16, 8, 20, 24, 22, 16, 0]: return list(tree.postorder_traverse()) == [-16, 8, 20, 24, 22, 16, 0]
return False
return True
def test_tree_chaining() -> bool: def test_tree_chaining() -> bool:
@ -695,9 +678,7 @@ def test_tree_chaining() -> bool:
return False return False
if list(tree.preorder_traverse()) != [0, -16, 16, 8, 22, 20, 24]: if list(tree.preorder_traverse()) != [0, -16, 16, 8, 22, 20, 24]:
return False return False
if list(tree.postorder_traverse()) != [-16, 8, 20, 24, 22, 16, 0]: return list(tree.postorder_traverse()) == [-16, 8, 20, 24, 22, 16, 0]
return False
return True
def print_results(msg: str, passes: bool) -> None: def print_results(msg: str, passes: bool) -> None:

View File

@ -156,9 +156,11 @@ class GraphAdjacencyMatrix(Generic[T]):
self.vertex_to_index.pop(vertex) self.vertex_to_index.pop(vertex)
# decrement indices for vertices shifted by the deleted vertex in the adj matrix # decrement indices for vertices shifted by the deleted vertex in the adj matrix
for vertex in self.vertex_to_index: for inner_vertex in self.vertex_to_index:
if self.vertex_to_index[vertex] >= start_index: if self.vertex_to_index[inner_vertex] >= start_index:
self.vertex_to_index[vertex] = self.vertex_to_index[vertex] - 1 self.vertex_to_index[inner_vertex] = (
self.vertex_to_index[inner_vertex] - 1
)
def contains_vertex(self, vertex: T) -> bool: def contains_vertex(self, vertex: T) -> bool:
""" """

View File

@ -79,7 +79,7 @@ def key(start: TPos, i: int, goal: TPos, g_function: dict[TPos, float]):
def do_something(back_pointer, goal, start): def do_something(back_pointer, goal, start):
grid = np.chararray((n, n)) grid = np.char.chararray((n, n))
for i in range(n): for i in range(n):
for j in range(n): for j in range(n):
grid[i][j] = "*" grid[i][j] = "*"
@ -123,9 +123,7 @@ def do_something(back_pointer, goal, start):
def valid(p: TPos): def valid(p: TPos):
if p[0] < 0 or p[0] > n - 1: if p[0] < 0 or p[0] > n - 1:
return False return False
if p[1] < 0 or p[1] > n - 1: return not (p[1] < 0 or p[1] > n - 1)
return False
return True
def expand_state( def expand_state(

View File

@ -38,7 +38,7 @@ def find_components(
reversed_graph: dict[int, list[int]], vert: int, visited: list[bool] reversed_graph: dict[int, list[int]], vert: int, visited: list[bool]
) -> list[int]: ) -> list[int]:
""" """
Use depth first search to find strongliy connected Use depth first search to find strongly connected
vertices. Now graph is reversed vertices. Now graph is reversed
>>> find_components({0: [1], 1: [2], 2: [0]}, 0, 5 * [False]) >>> find_components({0: [1], 1: [2], 2: [0]}, 0, 5 * [False])
[0, 1, 2] [0, 1, 2]

View File

@ -103,4 +103,4 @@ if __name__ == "__main__":
edges = list(zip(source, target)) edges = list(zip(source, target))
g = create_graph(n_vertices, edges) g = create_graph(n_vertices, edges)
assert [[5], [6], [4], [3, 2, 1, 0]] == tarjan(g) assert tarjan(g) == [[5], [6], [4], [3, 2, 1, 0]]

View File

@ -82,8 +82,8 @@ def reformat_hex(i: int) -> bytes:
hex_rep = format(i, "08x")[-8:] hex_rep = format(i, "08x")[-8:]
little_endian_hex = b"" little_endian_hex = b""
for i in [3, 2, 1, 0]: for j in [3, 2, 1, 0]:
little_endian_hex += hex_rep[2 * i : 2 * i + 2].encode("utf-8") little_endian_hex += hex_rep[2 * j : 2 * j + 2].encode("utf-8")
return little_endian_hex return little_endian_hex

View File

@ -1,15 +1,5 @@
import numpy as np import numpy as np
matrix = np.array(
[
[5.0, -5.0, -3.0, 4.0, -11.0],
[1.0, -4.0, 6.0, -4.0, -10.0],
[-2.0, -5.0, 4.0, -5.0, -12.0],
[-3.0, -3.0, 5.0, -5.0, 8.0],
],
dtype=float,
)
def solve_linear_system(matrix: np.ndarray) -> np.ndarray: def solve_linear_system(matrix: np.ndarray) -> np.ndarray:
""" """
@ -87,15 +77,18 @@ def solve_linear_system(matrix: np.ndarray) -> np.ndarray:
if __name__ == "__main__": if __name__ == "__main__":
from doctest import testmod from doctest import testmod
from pathlib import Path
testmod() testmod()
file_path = Path(__file__).parent / "matrix.txt"
try:
matrix = np.loadtxt(file_path)
except FileNotFoundError:
print(f"Error: {file_path} not found. Using default matrix instead.")
# Example usage: example_matrix = np.array(
print(f"Matrix:\n{matrix}") [
print(f"{solve_linear_system(matrix) = }") [5.0, -5.0, -3.0, 4.0, -11.0],
[1.0, -4.0, 6.0, -4.0, -10.0],
[-2.0, -5.0, 4.0, -5.0, -12.0],
[-3.0, -3.0, 5.0, -5.0, 8.0],
],
dtype=float,
)
print(f"Matrix:\n{example_matrix}")
print(f"{solve_linear_system(example_matrix) = }")

View File

@ -1,4 +0,0 @@
5.0 -5.0 -3.0 4.0 -11.0
1.0 -4.0 6.0 -4.0 -10.0
-2.0 -5.0 4.0 -5.0 -12.0
-3.0 -3.0 5.0 -5.0 8.0

View File

@ -4,7 +4,7 @@ Github : faizan2700
Purpose : You have one function f(x) which takes float integer and returns Purpose : You have one function f(x) which takes float integer and returns
float you have to integrate the function in limits a to b. float you have to integrate the function in limits a to b.
The approximation proposed by Thomas Simpsons in 1743 is one way to calculate The approximation proposed by Thomas Simpson in 1743 is one way to calculate
integration. integration.
( read article : https://cp-algorithms.com/num_methods/simpson-integration.html ) ( read article : https://cp-algorithms.com/num_methods/simpson-integration.html )

View File

@ -76,9 +76,9 @@ def get_3d_vectors_cross(ab: Vector3d, ac: Vector3d) -> Vector3d:
def is_zero_vector(vector: Vector3d, accuracy: int) -> bool: def is_zero_vector(vector: Vector3d, accuracy: int) -> bool:
""" """
Check if vector is equal to (0, 0, 0) of not. Check if vector is equal to (0, 0, 0) or not.
Sine the algorithm is very accurate, we will never get a zero vector, Since the algorithm is very accurate, we will never get a zero vector,
so we need to round the vector axis, so we need to round the vector axis,
because we want a result that is either True or False. because we want a result that is either True or False.
In other applications, we can return a float that represents the collinearity ratio. In other applications, we can return a float that represents the collinearity ratio.
@ -97,9 +97,9 @@ def are_collinear(a: Point3d, b: Point3d, c: Point3d, accuracy: int = 10) -> boo
""" """
Check if three points are collinear or not. Check if three points are collinear or not.
1- Create tow vectors AB and AC. 1- Create two vectors AB and AC.
2- Get the cross vector of the tow vectors. 2- Get the cross vector of the two vectors.
3- Calcolate the length of the cross vector. 3- Calculate the length of the cross vector.
4- If the length is zero then the points are collinear, else they are not. 4- If the length is zero then the points are collinear, else they are not.
The use of the accuracy parameter is explained in is_zero_vector docstring. The use of the accuracy parameter is explained in is_zero_vector docstring.

View File

@ -84,7 +84,6 @@ class FFT:
# Corner case # Corner case
if len(dft) <= 1: if len(dft) <= 1:
return dft[0] return dft[0]
#
next_ncol = self.c_max_length // 2 next_ncol = self.c_max_length // 2
while next_ncol > 0: while next_ncol > 0:
new_dft = [[] for i in range(next_ncol)] new_dft = [[] for i in range(next_ncol)]

View File

@ -1,7 +1,7 @@
""" """
- - - - - -- - - - - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - - -
Name - - CNN - Convolution Neural Network For Photo Recognizing Name - - CNN - Convolution Neural Network For Photo Recognizing
Goal - - Recognize Handing Writing Word Photo Goal - - Recognize Handwriting Word Photo
Detail: Total 5 layers neural network Detail: Total 5 layers neural network
* Convolution layer * Convolution layer
* Pooling layer * Pooling layer
@ -135,7 +135,7 @@ class CNN:
) )
data_featuremap.append(featuremap) data_featuremap.append(featuremap)
# expanding the data slice to One dimenssion # expanding the data slice to one dimension
focus1_list = [] focus1_list = []
for each_focus in data_focus: for each_focus in data_focus:
focus1_list.extend(self.Expand_Mat(each_focus)) focus1_list.extend(self.Expand_Mat(each_focus))
@ -304,7 +304,7 @@ class CNN:
plt.grid(True, alpha=0.5) plt.grid(True, alpha=0.5)
plt.show() plt.show()
print("------------------Training Complished---------------------") print("------------------Training Complete---------------------")
print((" - - Training epoch: ", rp, f" - - Mse: {mse:.6f}")) print((" - - Training epoch: ", rp, f" - - Mse: {mse:.6f}"))
if draw_e: if draw_e:
draw_error() draw_error()
@ -353,5 +353,5 @@ class CNN:
if __name__ == "__main__": if __name__ == "__main__":
""" """
I will put the example on other file I will put the example in another file
""" """

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -85,11 +85,10 @@ def validate(n: int) -> bool:
>>> validate(3797) >>> validate(3797)
True True
""" """
if len(str(n)) > 3 and ( return not (
not is_prime(int(str(n)[-3:])) or not is_prime(int(str(n)[:3])) len(str(n)) > 3
): and (not is_prime(int(str(n)[-3:])) or not is_prime(int(str(n)[:3])))
return False )
return True
def compute_truncated_primes(count: int = 11) -> list[int]: def compute_truncated_primes(count: int = 11) -> list[int]:

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -43,7 +43,7 @@ def solution(limit: int = 1_000_000) -> int:
ind = np.arange(2 * i, limit + 1, i) # indexes for selection ind = np.arange(2 * i, limit + 1, i) # indexes for selection
phi[ind] -= phi[ind] // i phi[ind] -= phi[ind] // i
return np.sum(phi[2 : limit + 1]) return int(np.sum(phi[2 : limit + 1]))
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1 +0,0 @@
#

View File

@ -1 +0,0 @@
#

View File

@ -74,12 +74,6 @@ lint.ignore = [
"UP038", # Use `X | Y` in `{}` call instead of `(X, Y)` -- DO NOT FIX "UP038", # Use `X | Y` in `{}` call instead of `(X, Y)` -- DO NOT FIX
] ]
lint.per-file-ignores."arithmetic_analysis/newton_raphson.py" = [
"PGH001",
]
lint.per-file-ignores."data_structures/binary_tree/binary_search_tree_recursive.py" = [
"BLE001",
]
lint.per-file-ignores."data_structures/hashing/tests/test_hash_map.py" = [ lint.per-file-ignores."data_structures/hashing/tests/test_hash_map.py" = [
"BLE001", "BLE001",
] ]

View File

@ -36,7 +36,7 @@ def build_tree() -> TreeNode:
right_node = TreeNode(int(check)) right_node = TreeNode(int(check))
node_found.right = right_node node_found.right = right_node
q.put(right_node) q.put(right_node)
raise raise ValueError("Something went wrong")
def pre_order(node: TreeNode) -> None: def pre_order(node: TreeNode) -> None:
@ -164,8 +164,8 @@ def level_order_actual(node: TreeNode) -> None:
if node_dequeued.right: if node_dequeued.right:
list_.append(node_dequeued.right) list_.append(node_dequeued.right)
print() print()
for node in list_: for inner_node in list_:
q.put(node) q.put(inner_node)
# iteration version # iteration version

View File

@ -3,13 +3,41 @@ This is pure Python implementation of interpolation search algorithm
""" """
def interpolation_search(sorted_collection, item): def interpolation_search(sorted_collection: list[int], item: int) -> int | None:
"""Pure implementation of interpolation search algorithm in Python """
Be careful collection must be ascending sorted, otherwise result will be Searches for an item in a sorted collection by interpolation search algorithm.
unpredictable
:param sorted_collection: some ascending sorted collection with comparable items Args:
:param item: item value to search sorted_collection: sorted list of integers
:return: index of found item or None if item is not found item: item value to search
Returns:
int: The index of the found item, or None if the item is not found.
Examples:
>>> interpolation_search([1, 2, 3, 4, 5], 2)
1
>>> interpolation_search([1, 2, 3, 4, 5], 4)
3
>>> interpolation_search([1, 2, 3, 4, 5], 6) is None
True
>>> interpolation_search([], 1) is None
True
>>> interpolation_search([100], 100)
0
>>> interpolation_search([1, 2, 3, 4, 5], 0) is None
True
>>> interpolation_search([1, 2, 3, 4, 5], 7) is None
True
>>> interpolation_search([1, 2, 3, 4, 5], 2)
1
>>> interpolation_search([1, 2, 3, 4, 5], 0) is None
True
>>> interpolation_search([1, 2, 3, 4, 5], 7) is None
True
>>> interpolation_search([1, 2, 3, 4, 5], 2)
1
>>> interpolation_search([5, 5, 5, 5, 5], 3) is None
True
""" """
left = 0 left = 0
right = len(sorted_collection) - 1 right = len(sorted_collection) - 1
@ -19,8 +47,7 @@ def interpolation_search(sorted_collection, item):
if sorted_collection[left] == sorted_collection[right]: if sorted_collection[left] == sorted_collection[right]:
if sorted_collection[left] == item: if sorted_collection[left] == item:
return left return left
else: return None
return None
point = left + ((item - sorted_collection[left]) * (right - left)) // ( point = left + ((item - sorted_collection[left]) * (right - left)) // (
sorted_collection[right] - sorted_collection[left] sorted_collection[right] - sorted_collection[left]
@ -33,7 +60,7 @@ def interpolation_search(sorted_collection, item):
current_item = sorted_collection[point] current_item = sorted_collection[point]
if current_item == item: if current_item == item:
return point return point
elif point < left: if point < left:
right = left right = left
left = point left = point
elif point > right: elif point > right:
@ -46,22 +73,42 @@ def interpolation_search(sorted_collection, item):
return None return None
def interpolation_search_by_recursion(sorted_collection, item, left, right): def interpolation_search_by_recursion(
sorted_collection: list[int], item: int, left: int = 0, right: int | None = None
) -> int | None:
"""Pure implementation of interpolation search algorithm in Python by recursion """Pure implementation of interpolation search algorithm in Python by recursion
Be careful collection must be ascending sorted, otherwise result will be Be careful collection must be ascending sorted, otherwise result will be
unpredictable unpredictable
First recursion should be started with left=0 and right=(len(sorted_collection)-1) First recursion should be started with left=0 and right=(len(sorted_collection)-1)
:param sorted_collection: some ascending sorted collection with comparable items
:param item: item value to search
:return: index of found item or None if item is not found
"""
Args:
sorted_collection: some sorted collection with comparable items
item: item value to search
left: left index in collection
right: right index in collection
Returns:
index of item in collection or None if item is not present
Examples:
>>> interpolation_search_by_recursion([0, 5, 7, 10, 15], 0)
0
>>> interpolation_search_by_recursion([0, 5, 7, 10, 15], 15)
4
>>> interpolation_search_by_recursion([0, 5, 7, 10, 15], 5)
1
>>> interpolation_search_by_recursion([0, 5, 7, 10, 15], 100) is None
True
>>> interpolation_search_by_recursion([5, 5, 5, 5, 5], 3) is None
True
"""
if right is None:
right = len(sorted_collection) - 1
# avoid divided by 0 during interpolation # avoid divided by 0 during interpolation
if sorted_collection[left] == sorted_collection[right]: if sorted_collection[left] == sorted_collection[right]:
if sorted_collection[left] == item: if sorted_collection[left] == item:
return left return left
else: return None
return None
point = left + ((item - sorted_collection[left]) * (right - left)) // ( point = left + ((item - sorted_collection[left]) * (right - left)) // (
sorted_collection[right] - sorted_collection[left] sorted_collection[right] - sorted_collection[left]
@ -73,64 +120,18 @@ def interpolation_search_by_recursion(sorted_collection, item, left, right):
if sorted_collection[point] == item: if sorted_collection[point] == item:
return point return point
elif point < left: if point < left:
return interpolation_search_by_recursion(sorted_collection, item, point, left) return interpolation_search_by_recursion(sorted_collection, item, point, left)
elif point > right: if point > right:
return interpolation_search_by_recursion(sorted_collection, item, right, left) return interpolation_search_by_recursion(sorted_collection, item, right, left)
elif sorted_collection[point] > item: if sorted_collection[point] > item:
return interpolation_search_by_recursion( return interpolation_search_by_recursion(
sorted_collection, item, left, point - 1 sorted_collection, item, left, point - 1
) )
else: return interpolation_search_by_recursion(sorted_collection, item, point + 1, right)
return interpolation_search_by_recursion(
sorted_collection, item, point + 1, right
)
def __assert_sorted(collection):
"""Check if collection is ascending sorted, if not - raises :py:class:`ValueError`
:param collection: collection
:return: True if collection is ascending sorted
:raise: :py:class:`ValueError` if collection is not ascending sorted
Examples:
>>> __assert_sorted([0, 1, 2, 4])
True
>>> __assert_sorted([10, -1, 5])
Traceback (most recent call last):
...
ValueError: Collection must be ascending sorted
"""
if collection != sorted(collection):
raise ValueError("Collection must be ascending sorted")
return True
if __name__ == "__main__": if __name__ == "__main__":
import sys import doctest
""" doctest.testmod()
user_input = input('Enter numbers separated by comma:\n').strip()
collection = [int(item) for item in user_input.split(',')]
try:
__assert_sorted(collection)
except ValueError:
sys.exit('Sequence must be ascending sorted to apply interpolation search')
target_input = input('Enter a single number to be found in the list:\n')
target = int(target_input)
"""
debug = 0
if debug == 1:
collection = [10, 30, 40, 45, 50, 66, 77, 93]
try:
__assert_sorted(collection)
except ValueError:
sys.exit("Sequence must be ascending sorted to apply interpolation search")
target = 67
result = interpolation_search(collection, target)
if result is not None:
print(f"{target} found at positions: {result}")
else:
print("Not found")

View File

@ -77,10 +77,7 @@ class FilesArray:
self.empty.add(i) self.empty.add(i)
self.files[i].close() self.files[i].close()
if len(self.empty) == self.num_buffers: return len(self.empty) != self.num_buffers
return False
return True
def unshift(self, index): def unshift(self, index):
value = self.buffers[index] value = self.buffers[index]

0
source/__init__.py Normal file
View File

View File

@ -72,9 +72,7 @@ def can_string_be_rearranged_as_palindrome(input_str: str = "") -> bool:
for character_count in character_freq_dict.values(): for character_count in character_freq_dict.values():
if character_count % 2: if character_count % 2:
odd_char += 1 odd_char += 1
if odd_char > 1: return not odd_char > 1
return False
return True
def benchmark(input_str: str = "") -> None: def benchmark(input_str: str = "") -> None:

34
strings/count_vowels.py Normal file
View File

@ -0,0 +1,34 @@
def count_vowels(s: str) -> int:
"""
Count the number of vowels in a given string.
:param s: Input string to count vowels in.
:return: Number of vowels in the input string.
Examples:
>>> count_vowels("hello world")
3
>>> count_vowels("HELLO WORLD")
3
>>> count_vowels("123 hello world")
3
>>> count_vowels("")
0
>>> count_vowels("a quick brown fox")
5
>>> count_vowels("the quick BROWN fox")
5
>>> count_vowels("PYTHON")
1
"""
if not isinstance(s, str):
raise ValueError("Input must be a string")
vowels = "aeiouAEIOU"
return sum(1 for char in s if char in vowels)
if __name__ == "__main__":
from doctest import testmod
testmod()

View File

@ -101,9 +101,7 @@ def is_valid_email_address(email: str) -> bool:
return False return False
# (7.) Validate the placement of "." characters # (7.) Validate the placement of "." characters
if domain.startswith(".") or domain.endswith(".") or ".." in domain: return not (domain.startswith(".") or domain.endswith(".") or ".." in domain)
return False
return True
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -67,19 +67,19 @@ def text_justification(word: str, max_width: int) -> list:
answer = [] answer = []
line: list[str] = [] line: list[str] = []
width = 0 width = 0
for word in words: for inner_word in words:
if width + len(word) + len(line) <= max_width: if width + len(inner_word) + len(line) <= max_width:
# keep adding words until we can fill out max_width # keep adding words until we can fill out max_width
# width = sum of length of all words (without overall_spaces_count) # width = sum of length of all words (without overall_spaces_count)
# len(word) = length of current word # len(inner_word) = length of current inner_word
# len(line) = number of overall_spaces_count to insert between words # len(line) = number of overall_spaces_count to insert between words
line.append(word) line.append(inner_word)
width += len(word) width += len(inner_word)
else: else:
# justify the line and add it to result # justify the line and add it to result
answer.append(justify(line, width, max_width)) answer.append(justify(line, width, max_width))
# reset new line and new width # reset new line and new width
line, width = [word], len(word) line, width = [inner_word], len(inner_word)
remaining_spaces = max_width - width - len(line) remaining_spaces = max_width - width - len(line)
answer.append(" ".join(line) + (remaining_spaces + 1) * " ") answer.append(" ".join(line) + (remaining_spaces + 1) * " ")
return answer return answer

View File

@ -31,12 +31,7 @@ class Parser(HTMLParser):
# Check the list of defined attributes. # Check the list of defined attributes.
for name, value in attrs: for name, value in attrs:
# If href is defined, not empty nor # print it and not already in urls. # If href is defined, not empty nor # print it and not already in urls.
if ( if name == "href" and value not in (*self.urls, "", "#"):
name == "href"
and value != "#"
and value != ""
and value not in self.urls
):
url = parse.urljoin(self.domain, value) url = parse.urljoin(self.domain, value)
self.urls.append(url) self.urls.append(url)

View File

@ -65,7 +65,7 @@ def get_forbes_real_time_billionaires() -> list[dict[str, int | str]]:
"Country": person["countryOfCitizenship"], "Country": person["countryOfCitizenship"],
"Gender": person["gender"], "Gender": person["gender"],
"Worth ($)": f"{person['finalWorth'] / 1000:.1f} Billion", "Worth ($)": f"{person['finalWorth'] / 1000:.1f} Billion",
"Age": years_old(person["birthDate"]), "Age": str(years_old(person["birthDate"] / 1000)),
} }
for person in response_json["personList"]["personsLists"] for person in response_json["personList"]["personsLists"]
] ]
@ -95,4 +95,7 @@ def display_billionaires(forbes_billionaires: list[dict[str, int | str]]) -> Non
if __name__ == "__main__": if __name__ == "__main__":
from doctest import testmod
testmod()
display_billionaires(get_forbes_real_time_billionaires()) display_billionaires(get_forbes_real_time_billionaires())