Merge branch 'TheAlgorithms:master' into master

This commit is contained in:
Dipankar Mitra 2023-05-16 20:57:04 +05:30 committed by GitHub
commit 6e7ed74f98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 75 additions and 68 deletions

View File

@ -16,7 +16,7 @@ repos:
- id: auto-walrus - id: auto-walrus
- repo: https://github.com/charliermarsh/ruff-pre-commit - repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.263 rev: v0.0.267
hooks: hooks:
- id: ruff - id: ruff
@ -33,7 +33,7 @@ repos:
- tomli - tomli
- repo: https://github.com/tox-dev/pyproject-fmt - repo: https://github.com/tox-dev/pyproject-fmt
rev: "0.11.1" rev: "0.11.2"
hooks: hooks:
- id: pyproject-fmt - id: pyproject-fmt
@ -51,7 +51,7 @@ 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.2.0 rev: v1.3.0
hooks: hooks:
- id: mypy - id: mypy
args: args:

View File

@ -294,7 +294,6 @@
* [Mergesort](divide_and_conquer/mergesort.py) * [Mergesort](divide_and_conquer/mergesort.py)
* [Peak](divide_and_conquer/peak.py) * [Peak](divide_and_conquer/peak.py)
* [Power](divide_and_conquer/power.py) * [Power](divide_and_conquer/power.py)
* [Strassen Matrix Multiplication](divide_and_conquer/strassen_matrix_multiplication.py)
## Dynamic Programming ## Dynamic Programming
* [Abbreviation](dynamic_programming/abbreviation.py) * [Abbreviation](dynamic_programming/abbreviation.py)
@ -632,6 +631,7 @@
* [Radians](maths/radians.py) * [Radians](maths/radians.py)
* [Radix2 Fft](maths/radix2_fft.py) * [Radix2 Fft](maths/radix2_fft.py)
* [Relu](maths/relu.py) * [Relu](maths/relu.py)
* [Remove Digit](maths/remove_digit.py)
* [Runge Kutta](maths/runge_kutta.py) * [Runge Kutta](maths/runge_kutta.py)
* [Segmented Sieve](maths/segmented_sieve.py) * [Segmented Sieve](maths/segmented_sieve.py)
* Series * Series
@ -694,6 +694,8 @@
## Neural Network ## Neural Network
* [2 Hidden Layers Neural Network](neural_network/2_hidden_layers_neural_network.py) * [2 Hidden Layers Neural Network](neural_network/2_hidden_layers_neural_network.py)
* Activation Functions
* [Exponential Linear Unit](neural_network/activation_functions/exponential_linear_unit.py)
* [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py) * [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py)
* [Convolution Neural Network](neural_network/convolution_neural_network.py) * [Convolution Neural Network](neural_network/convolution_neural_network.py)
* [Input Data](neural_network/input_data.py) * [Input Data](neural_network/input_data.py)
@ -1080,6 +1082,7 @@
## Sorts ## Sorts
* [Bead Sort](sorts/bead_sort.py) * [Bead Sort](sorts/bead_sort.py)
* [Binary Insertion Sort](sorts/binary_insertion_sort.py)
* [Bitonic Sort](sorts/bitonic_sort.py) * [Bitonic Sort](sorts/bitonic_sort.py)
* [Bogo Sort](sorts/bogo_sort.py) * [Bogo Sort](sorts/bogo_sort.py)
* [Bubble Sort](sorts/bubble_sort.py) * [Bubble Sort](sorts/bubble_sort.py)
@ -1170,6 +1173,7 @@
* [Reverse Words](strings/reverse_words.py) * [Reverse Words](strings/reverse_words.py)
* [Snake Case To Camel Pascal Case](strings/snake_case_to_camel_pascal_case.py) * [Snake Case To Camel Pascal Case](strings/snake_case_to_camel_pascal_case.py)
* [Split](strings/split.py) * [Split](strings/split.py)
* [String Switch Case](strings/string_switch_case.py)
* [Text Justification](strings/text_justification.py) * [Text Justification](strings/text_justification.py)
* [Top K Frequent Words](strings/top_k_frequent_words.py) * [Top K Frequent Words](strings/top_k_frequent_words.py)
* [Upper](strings/upper.py) * [Upper](strings/upper.py)

View File

@ -96,7 +96,7 @@ def add_si_prefix(value: float) -> str:
for name_prefix, value_prefix in prefixes.items(): for name_prefix, value_prefix in prefixes.items():
numerical_part = value / (10**value_prefix) numerical_part = value / (10**value_prefix)
if numerical_part > 1: if numerical_part > 1:
return f"{str(numerical_part)} {name_prefix}" return f"{numerical_part!s} {name_prefix}"
return str(value) return str(value)
@ -111,7 +111,7 @@ def add_binary_prefix(value: float) -> str:
for prefix in BinaryUnit: for prefix in BinaryUnit:
numerical_part = value / (2**prefix.value) numerical_part = value / (2**prefix.value)
if numerical_part > 1: if numerical_part > 1:
return f"{str(numerical_part)} {prefix.name}" return f"{numerical_part!s} {prefix.name}"
return str(value) return str(value)

View File

@ -121,8 +121,8 @@ def rgb_to_hsv(red: int, green: int, blue: int) -> list[float]:
float_red = red / 255 float_red = red / 255
float_green = green / 255 float_green = green / 255
float_blue = blue / 255 float_blue = blue / 255
value = max(max(float_red, float_green), float_blue) value = max(float_red, float_green, float_blue)
chroma = value - min(min(float_red, float_green), float_blue) chroma = value - min(float_red, float_green, float_blue)
saturation = 0 if value == 0 else chroma / value saturation = 0 if value == 0 else chroma / value
if chroma == 0: if chroma == 0:

View File

@ -96,7 +96,7 @@ def test_nearest_neighbour(
def test_local_binary_pattern(): def test_local_binary_pattern():
file_path: str = "digital_image_processing/image_data/lena.jpg" file_path = "digital_image_processing/image_data/lena.jpg"
# Reading the image and converting it to grayscale. # Reading the image and converting it to grayscale.
image = imread(file_path, 0) image = imread(file_path, 0)

View File

@ -122,7 +122,7 @@ def strassen(matrix1: list, matrix2: list) -> list:
if dimension1[0] == dimension1[1] and dimension2[0] == dimension2[1]: if dimension1[0] == dimension1[1] and dimension2[0] == dimension2[1]:
return [matrix1, matrix2] return [matrix1, matrix2]
maximum = max(max(dimension1), max(dimension2)) maximum = max(dimension1, dimension2)
maxim = int(math.pow(2, math.ceil(math.log2(maximum)))) maxim = int(math.pow(2, math.ceil(math.log2(maximum))))
new_matrix1 = matrix1 new_matrix1 = matrix1
new_matrix2 = matrix2 new_matrix2 = matrix2

View File

@ -24,7 +24,7 @@ class Fibonacci:
return self.sequence[:index] return self.sequence[:index]
def main(): def main() -> None:
print( print(
"Fibonacci Series Using Dynamic Programming\n", "Fibonacci Series Using Dynamic Programming\n",
"Enter the index of the Fibonacci number you want to calculate ", "Enter the index of the Fibonacci number you want to calculate ",

View File

@ -21,6 +21,54 @@ MUTATION_PROBABILITY = 0.4
random.seed(random.randint(0, 1000)) random.seed(random.randint(0, 1000))
def evaluate(item: str, main_target: str) -> tuple[str, float]:
"""
Evaluate how similar the item is with the target by just
counting each char in the right position
>>> evaluate("Helxo Worlx", "Hello World")
('Helxo Worlx', 9.0)
"""
score = len([g for position, g in enumerate(item) if g == main_target[position]])
return (item, float(score))
def crossover(parent_1: str, parent_2: str) -> tuple[str, str]:
"""Slice and combine two string at a random point."""
random_slice = random.randint(0, len(parent_1) - 1)
child_1 = parent_1[:random_slice] + parent_2[random_slice:]
child_2 = parent_2[:random_slice] + parent_1[random_slice:]
return (child_1, child_2)
def mutate(child: str, genes: list[str]) -> str:
"""Mutate a random gene of a child with another one from the list."""
child_list = list(child)
if random.uniform(0, 1) < MUTATION_PROBABILITY:
child_list[random.randint(0, len(child)) - 1] = random.choice(genes)
return "".join(child_list)
# Select, crossover and mutate a new population.
def select(
parent_1: tuple[str, float],
population_score: list[tuple[str, float]],
genes: list[str],
) -> list[str]:
"""Select the second parent and generate new population"""
pop = []
# Generate more children proportionally to the fitness score.
child_n = int(parent_1[1] * 100) + 1
child_n = 10 if child_n >= 10 else child_n
for _ in range(child_n):
parent_2 = population_score[random.randint(0, N_SELECTED)][0]
child_1, child_2 = crossover(parent_1[0], parent_2)
# Append new string to the population list.
pop.append(mutate(child_1, genes))
pop.append(mutate(child_2, genes))
return pop
def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, str]: def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int, str]:
""" """
Verify that the target contains no genes besides the ones inside genes variable. Verify that the target contains no genes besides the ones inside genes variable.
@ -70,17 +118,6 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int,
total_population += len(population) total_population += len(population)
# Random population created. Now it's time to evaluate. # Random population created. Now it's time to evaluate.
def evaluate(item: str, main_target: str = target) -> tuple[str, float]:
"""
Evaluate how similar the item is with the target by just
counting each char in the right position
>>> evaluate("Helxo Worlx", Hello World)
["Helxo Worlx", 9]
"""
score = len(
[g for position, g in enumerate(item) if g == main_target[position]]
)
return (item, float(score))
# Adding a bit of concurrency can make everything faster, # Adding a bit of concurrency can make everything faster,
# #
@ -94,7 +131,7 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int,
# #
# but with a simple algorithm like this, it will probably be slower. # but with a simple algorithm like this, it will probably be slower.
# We just need to call evaluate for every item inside the population. # We just need to call evaluate for every item inside the population.
population_score = [evaluate(item) for item in population] population_score = [evaluate(item, target) for item in population]
# Check if there is a matching evolution. # Check if there is a matching evolution.
population_score = sorted(population_score, key=lambda x: x[1], reverse=True) population_score = sorted(population_score, key=lambda x: x[1], reverse=True)
@ -121,41 +158,9 @@ def basic(target: str, genes: list[str], debug: bool = True) -> tuple[int, int,
(item, score / len(target)) for item, score in population_score (item, score / len(target)) for item, score in population_score
] ]
# Select, crossover and mutate a new population.
def select(parent_1: tuple[str, float]) -> list[str]:
"""Select the second parent and generate new population"""
pop = []
# Generate more children proportionally to the fitness score.
child_n = int(parent_1[1] * 100) + 1
child_n = 10 if child_n >= 10 else child_n
for _ in range(child_n):
parent_2 = population_score[ # noqa: B023
random.randint(0, N_SELECTED)
][0]
child_1, child_2 = crossover(parent_1[0], parent_2)
# Append new string to the population list.
pop.append(mutate(child_1))
pop.append(mutate(child_2))
return pop
def crossover(parent_1: str, parent_2: str) -> tuple[str, str]:
"""Slice and combine two string at a random point."""
random_slice = random.randint(0, len(parent_1) - 1)
child_1 = parent_1[:random_slice] + parent_2[random_slice:]
child_2 = parent_2[:random_slice] + parent_1[random_slice:]
return (child_1, child_2)
def mutate(child: str) -> str:
"""Mutate a random gene of a child with another one from the list."""
child_list = list(child)
if random.uniform(0, 1) < MUTATION_PROBABILITY:
child_list[random.randint(0, len(child)) - 1] = random.choice(genes)
return "".join(child_list)
# This is selection # This is selection
for i in range(N_SELECTED): for i in range(N_SELECTED):
population.extend(select(population_score[int(i)])) population.extend(select(population_score[int(i)], population_score, genes))
# Check if the population has already reached the maximum value and if so, # Check if the population has already reached the maximum value and if so,
# break the cycle. If this check is disabled, the algorithm will take # break the cycle. If this check is disabled, the algorithm will take
# forever to compute large strings, but will also calculate small strings in # forever to compute large strings, but will also calculate small strings in

View File

@ -1,12 +1,12 @@
from __future__ import annotations from __future__ import annotations
import typing
from collections.abc import Iterable from collections.abc import Iterable
from typing import Union
import numpy as np import numpy as np
Vector = Union[Iterable[float], Iterable[int], np.ndarray] Vector = typing.Union[Iterable[float], Iterable[int], np.ndarray] # noqa: UP007
VectorOut = Union[np.float64, int, float] VectorOut = typing.Union[np.float64, int, float] # noqa: UP007
def euclidean_distance(vector_1: Vector, vector_2: Vector) -> VectorOut: def euclidean_distance(vector_1: Vector, vector_2: Vector) -> VectorOut:

View File

@ -147,6 +147,6 @@ if __name__ == "__main__":
# Print results # Print results
print() print()
print("Results: ") print("Results: ")
print(f"Horizontal Distance: {str(horizontal_distance(init_vel, angle))} [m]") print(f"Horizontal Distance: {horizontal_distance(init_vel, angle)!s} [m]")
print(f"Maximum Height: {str(max_height(init_vel, angle))} [m]") print(f"Maximum Height: {max_height(init_vel, angle)!s} [m]")
print(f"Total Time: {str(total_time(init_vel, angle))} [s]") print(f"Total Time: {total_time(init_vel, angle)!s} [s]")

View File

@ -13,11 +13,9 @@ class TreeNode:
self.left = None self.left = None
def build_tree(): def build_tree() -> TreeNode:
print("\n********Press N to stop entering at any point of time********\n") print("\n********Press N to stop entering at any point of time********\n")
check = input("Enter the value of the root node: ").strip().lower() or "n" check = input("Enter the value of the root node: ").strip().lower()
if check == "n":
return None
q: queue.Queue = queue.Queue() q: queue.Queue = queue.Queue()
tree_node = TreeNode(int(check)) tree_node = TreeNode(int(check))
q.put(tree_node) q.put(tree_node)
@ -37,7 +35,7 @@ def build_tree():
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)
return None raise
def pre_order(node: TreeNode) -> None: def pre_order(node: TreeNode) -> None:
@ -272,7 +270,7 @@ if __name__ == "__main__":
doctest.testmod() doctest.testmod()
print(prompt("Binary Tree Traversals")) print(prompt("Binary Tree Traversals"))
node = build_tree() node: TreeNode = build_tree()
print(prompt("Pre Order Traversal")) print(prompt("Pre Order Traversal"))
pre_order(node) pre_order(node)
print(prompt() + "\n") print(prompt() + "\n")