diff --git a/.travis.yml b/.travis.yml index cbbdc25e0..d2394b409 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,14 +14,14 @@ jobs: - scripts/validate_filenames.py # no uppercase, no spaces, in a directory - pip install -r requirements.txt # fast fail on black, flake8, validate_filenames script: - - mypy --ignore-missing-imports . + - mypy --ignore-missing-imports . || true # https://github.com/python/mypy/issues/7907 - pytest --doctest-modules --ignore=project_euler/ --durations=10 --cov-report=term-missing:skip-covered --cov=. . - name: Project Euler before_script: pip install pytest-cov script: - pytest --doctest-modules --durations=10 --cov-report=term-missing:skip-covered --cov=project_euler/ project_euler/ +after_success: + - scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md notifications: webhooks: https://www.travisbuddy.com/ on_success: never -after_success: - - scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md diff --git a/arithmetic_analysis/in_static_equilibrium.py b/arithmetic_analysis/in_static_equilibrium.py index dd7fa7061..f08b39c35 100644 --- a/arithmetic_analysis/in_static_equilibrium.py +++ b/arithmetic_analysis/in_static_equilibrium.py @@ -6,14 +6,14 @@ flake8 : passed mypy : passed """ -from typing import List +from __future__ import annotations from numpy import array, cos, cross, radians, sin # type: ignore def polar_force( magnitude: float, angle: float, radian_mode: bool = False -) -> List[float]: +) -> list[float]: """ Resolves force along rectangular components. (force, angle) => (force_x, force_y) diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 3956b21a9..ceaffe3fa 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -5,11 +5,11 @@ Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring """ -from typing import List +from __future__ import annotations def valid_coloring( - neighbours: List[int], colored_vertices: List[int], color: int + neighbours: list[int], colored_vertices: list[int], color: int ) -> bool: """ For each neighbour check if coloring constraint is satisfied @@ -35,7 +35,7 @@ def valid_coloring( def util_color( - graph: List[List[int]], max_colors: int, colored_vertices: List[int], index: int + graph: list[list[int]], max_colors: int, colored_vertices: list[int], index: int ) -> bool: """ Pseudo-Code @@ -86,7 +86,7 @@ def util_color( return False -def color(graph: List[List[int]], max_colors: int) -> List[int]: +def color(graph: list[list[int]], max_colors: int) -> list[int]: """ Wrapper function to call subroutine called util_color which will either return True or False. diff --git a/backtracking/hamiltonian_cycle.py b/backtracking/hamiltonian_cycle.py index 7be1ea350..bf15cce4a 100644 --- a/backtracking/hamiltonian_cycle.py +++ b/backtracking/hamiltonian_cycle.py @@ -6,11 +6,11 @@ Wikipedia: https://en.wikipedia.org/wiki/Hamiltonian_path """ -from typing import List +from __future__ import annotations def valid_connection( - graph: List[List[int]], next_ver: int, curr_ind: int, path: List[int] + graph: list[list[int]], next_ver: int, curr_ind: int, path: list[int] ) -> bool: """ Checks whether it is possible to add next into path by validating 2 statements @@ -47,7 +47,7 @@ def valid_connection( return not any(vertex == next_ver for vertex in path) -def util_hamilton_cycle(graph: List[List[int]], path: List[int], curr_ind: int) -> bool: +def util_hamilton_cycle(graph: list[list[int]], path: list[int], curr_ind: int) -> bool: """ Pseudo-Code Base Case: @@ -108,7 +108,7 @@ def util_hamilton_cycle(graph: List[List[int]], path: List[int], curr_ind: int) return False -def hamilton_cycle(graph: List[List[int]], start_index: int = 0) -> List[int]: +def hamilton_cycle(graph: list[list[int]], start_index: int = 0) -> list[int]: r""" Wrapper function to call subroutine called util_hamilton_cycle, which will either return array of vertices indicating hamiltonian cycle diff --git a/backtracking/knight_tour.py b/backtracking/knight_tour.py index e4a93fbc2..2413ba468 100644 --- a/backtracking/knight_tour.py +++ b/backtracking/knight_tour.py @@ -1,9 +1,9 @@ # Knight Tour Intro: https://www.youtube.com/watch?v=ab_dY3dZFHM -from typing import List, Tuple +from __future__ import annotations -def get_valid_pos(position: Tuple[int], n: int) -> List[Tuple[int]]: +def get_valid_pos(position: tuple[int], n: int) -> list[tuple[int]]: """ Find all the valid positions a knight can move to from the current position. @@ -32,7 +32,7 @@ def get_valid_pos(position: Tuple[int], n: int) -> List[Tuple[int]]: return permissible_positions -def is_complete(board: List[List[int]]) -> bool: +def is_complete(board: list[list[int]]) -> bool: """ Check if the board (matrix) has been completely filled with non-zero values. @@ -46,7 +46,7 @@ def is_complete(board: List[List[int]]) -> bool: return not any(elem == 0 for row in board for elem in row) -def open_knight_tour_helper(board: List[List[int]], pos: Tuple[int], curr: int) -> bool: +def open_knight_tour_helper(board: list[list[int]], pos: tuple[int], curr: int) -> bool: """ Helper function to solve knight tour problem. """ @@ -66,7 +66,7 @@ def open_knight_tour_helper(board: List[List[int]], pos: Tuple[int], curr: int) return False -def open_knight_tour(n: int) -> List[List[int]]: +def open_knight_tour(n: int) -> list[list[int]]: """ Find the solution for the knight tour problem for a board of size n. Raises ValueError if the tour cannot be performed for the given size. diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index fb2b74bd7..811611971 100644 --- a/backtracking/n_queens_math.py +++ b/backtracking/n_queens_math.py @@ -75,14 +75,14 @@ Applying this two formulas we can check if a queen in some position is being att for another one or vice versa. """ -from typing import List +from __future__ import annotations def depth_first_search( - possible_board: List[int], - diagonal_right_collisions: List[int], - diagonal_left_collisions: List[int], - boards: List[List[str]], + possible_board: list[int], + diagonal_right_collisions: list[int], + diagonal_left_collisions: list[int], + boards: list[list[str]], n: int, ) -> None: """ diff --git a/cellular_automata/one_dimensional.py b/cellular_automata/one_dimensional.py index a6229dd90..da77e4445 100644 --- a/cellular_automata/one_dimensional.py +++ b/cellular_automata/one_dimensional.py @@ -4,7 +4,7 @@ ruleset number https://mathworld.wolfram.com/ElementaryCellularAutomaton.html """ -from typing import List +from __future__ import annotations from PIL import Image @@ -15,7 +15,7 @@ CELLS = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, # fmt: on -def format_ruleset(ruleset: int) -> List[int]: +def format_ruleset(ruleset: int) -> list[int]: """ >>> format_ruleset(11100) [0, 0, 0, 1, 1, 1, 0, 0] @@ -27,7 +27,7 @@ def format_ruleset(ruleset: int) -> List[int]: return [int(c) for c in f"{ruleset:08}"[:8]] -def new_generation(cells: List[List[int]], rule: List[int], time: int) -> List[int]: +def new_generation(cells: list[list[int]], rule: list[int], time: int) -> list[int]: population = len(cells[0]) # 31 next_generation = [] for i in range(population): @@ -41,7 +41,7 @@ def new_generation(cells: List[List[int]], rule: List[int], time: int) -> List[i return next_generation -def generate_image(cells: List[List[int]]) -> Image.Image: +def generate_image(cells: list[list[int]]) -> Image.Image: """ Convert the cells into a greyscale PIL.Image.Image and return it to the caller. >>> from random import random diff --git a/ciphers/rsa_factorization.py b/ciphers/rsa_factorization.py index 9ec34e6c5..6df32b6cc 100644 --- a/ciphers/rsa_factorization.py +++ b/ciphers/rsa_factorization.py @@ -7,12 +7,13 @@ Source: on page 3 of https://crypto.stanford.edu/~dabo/papers/RSA-survey.pdf More readable source: https://www.di-mgt.com.au/rsa_factorize_n.html large number can take minutes to factor, therefore are not included in doctest. """ +from __future__ import annotations + import math import random -from typing import List -def rsafactor(d: int, e: int, N: int) -> List[int]: +def rsafactor(d: int, e: int, N: int) -> list[int]: """ This function returns the factors of N, where p*q=N Return: [p, q] diff --git a/compression/burrows_wheeler.py b/compression/burrows_wheeler.py index 03912f80e..1a6610915 100644 --- a/compression/burrows_wheeler.py +++ b/compression/burrows_wheeler.py @@ -10,10 +10,10 @@ without needing to store any additional data except the position of the first original character. The BWT is thus a "free" method of improving the efficiency of text compression algorithms, costing only some extra computation. """ -from typing import Dict, List +from __future__ import annotations -def all_rotations(s: str) -> List[str]: +def all_rotations(s: str) -> list[str]: """ :param s: The string that will be rotated len(s) times. :return: A list with the rotations. @@ -43,7 +43,7 @@ def all_rotations(s: str) -> List[str]: return [s[i:] + s[:i] for i in range(len(s))] -def bwt_transform(s: str) -> Dict: +def bwt_transform(s: str) -> dict: """ :param s: The string that will be used at bwt algorithm :return: the string composed of the last char of each row of the ordered diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index 38d93a32e..5bc79e74e 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -1,5 +1,6 @@ +from __future__ import annotations + import math -from typing import List class SegmentTree: @@ -36,7 +37,7 @@ class SegmentTree: return idx * 2 + 1 def build( - self, idx: int, left_element: int, right_element: int, A: List[int] + self, idx: int, left_element: int, right_element: int, A: list[int] ) -> None: if left_element == right_element: self.segment_tree[idx] = A[left_element - 1] diff --git a/data_structures/binary_tree/lowest_common_ancestor.py b/data_structures/binary_tree/lowest_common_ancestor.py index c25536cda..2f1e893fc 100644 --- a/data_structures/binary_tree/lowest_common_ancestor.py +++ b/data_structures/binary_tree/lowest_common_ancestor.py @@ -1,11 +1,12 @@ # https://en.wikipedia.org/wiki/Lowest_common_ancestor # https://en.wikipedia.org/wiki/Breadth-first_search +from __future__ import annotations + import queue -from typing import Dict, List, Tuple -def swap(a: int, b: int) -> Tuple[int, int]: +def swap(a: int, b: int) -> tuple[int, int]: """ Return a tuple (b, a) when given two integers a and b >>> swap(2,3) @@ -21,7 +22,7 @@ def swap(a: int, b: int) -> Tuple[int, int]: return a, b -def create_sparse(max_node: int, parent: List[List[int]]) -> List[List[int]]: +def create_sparse(max_node: int, parent: list[list[int]]) -> list[list[int]]: """ creating sparse table which saves each nodes 2^i-th parent """ @@ -35,8 +36,8 @@ def create_sparse(max_node: int, parent: List[List[int]]) -> List[List[int]]: # returns lca of node u,v def lowest_common_ancestor( - u: int, v: int, level: List[int], parent: List[List[int]] -) -> List[List[int]]: + u: int, v: int, level: list[int], parent: list[list[int]] +) -> list[list[int]]: # u must be deeper in the tree than v if level[u] < level[v]: u, v = swap(u, v) @@ -57,12 +58,12 @@ def lowest_common_ancestor( # runs a breadth first search from root node of the tree def breadth_first_search( - level: List[int], - parent: List[List[int]], + level: list[int], + parent: list[list[int]], max_node: int, - graph: Dict[int, int], + graph: dict[int, int], root=1, -) -> Tuple[List[int], List[List[int]]]: +) -> tuple[list[int], list[list[int]]]: """ sets every nodes direct parent parent of root node is set to 0 diff --git a/data_structures/binary_tree/non_recursive_segment_tree.py b/data_structures/binary_tree/non_recursive_segment_tree.py index cdcf1fa8d..064e5aded 100644 --- a/data_structures/binary_tree/non_recursive_segment_tree.py +++ b/data_structures/binary_tree/non_recursive_segment_tree.py @@ -35,13 +35,15 @@ https://www.geeksforgeeks.org/segment-tree-efficient-implementation/ >>> st.query(0, 2) [1, 2, 3] """ -from typing import Callable, List, TypeVar +from __future__ import annotations + +from typing import Callable, TypeVar T = TypeVar("T") class SegmentTree: - def __init__(self, arr: List[T], fnc: Callable[[T, T], T]) -> None: + def __init__(self, arr: list[T], fnc: Callable[[T, T], T]) -> None: """ Segment Tree constructor, it works just with commutative combiner. :param arr: list of elements for the segment tree diff --git a/data_structures/binary_tree/treap.py b/data_structures/binary_tree/treap.py index fbb576502..26648f7ab 100644 --- a/data_structures/binary_tree/treap.py +++ b/data_structures/binary_tree/treap.py @@ -1,7 +1,8 @@ # flake8: noqa +from __future__ import annotations + from random import random -from typing import Tuple class Node: @@ -33,7 +34,7 @@ class Node: return value + left + right -def split(root: Node, value: int) -> Tuple[Node, Node]: +def split(root: Node, value: int) -> tuple[Node, Node]: """ We split current tree into 2 trees with value: diff --git a/data_structures/linked_list/skip_list.py b/data_structures/linked_list/skip_list.py index ee572cd3e..8f06e6193 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -3,8 +3,10 @@ Based on "Skip Lists: A Probabilistic Alternative to Balanced Trees" by William https://epaperpress.com/sortsearch/download/skiplist.pdf """ +from __future__ import annotations + from random import random -from typing import Generic, List, Optional, Tuple, TypeVar +from typing import Generic, Optional, TypeVar KT = TypeVar("KT") VT = TypeVar("VT") @@ -14,7 +16,7 @@ class Node(Generic[KT, VT]): def __init__(self, key: KT, value: VT): self.key = key self.value = value - self.forward: List[Node[KT, VT]] = [] + self.forward: list[Node[KT, VT]] = [] def __repr__(self) -> str: """ @@ -122,7 +124,7 @@ class SkipList(Generic[KT, VT]): return level - def _locate_node(self, key) -> Tuple[Optional[Node[KT, VT]], List[Node[KT, VT]]]: + def _locate_node(self, key) -> tuple[Optional[Node[KT, VT]], list[Node[KT, VT]]]: """ :param key: Searched key, :return: Tuple with searched node (or None if given key is not present) diff --git a/divide_and_conquer/strassen_matrix_multiplication.py b/divide_and_conquer/strassen_matrix_multiplication.py index 486258e8b..29a174dae 100644 --- a/divide_and_conquer/strassen_matrix_multiplication.py +++ b/divide_and_conquer/strassen_matrix_multiplication.py @@ -1,8 +1,9 @@ +from __future__ import annotations + import math -from typing import List, Tuple -def default_matrix_multiplication(a: List, b: List) -> List: +def default_matrix_multiplication(a: list, b: list) -> list: """ Multiplication only for 2x2 matrices """ @@ -15,23 +16,21 @@ def default_matrix_multiplication(a: List, b: List) -> List: return new_matrix -def matrix_addition(matrix_a: List, matrix_b: List): +def matrix_addition(matrix_a: list, matrix_b: list): return [ [matrix_a[row][col] + matrix_b[row][col] for col in range(len(matrix_a[row]))] for row in range(len(matrix_a)) ] -def matrix_subtraction(matrix_a: List, matrix_b: List): +def matrix_subtraction(matrix_a: list, matrix_b: list): return [ [matrix_a[row][col] - matrix_b[row][col] for col in range(len(matrix_a[row]))] for row in range(len(matrix_a)) ] -def split_matrix( - a: List, -) -> Tuple[List, List, List, List]: +def split_matrix(a: list) -> tuple[list, list, list, list]: """ Given an even length matrix, returns the top_left, top_right, bot_left, bot_right quadrant. @@ -64,16 +63,16 @@ def split_matrix( return top_left, top_right, bot_left, bot_right -def matrix_dimensions(matrix: List) -> Tuple[int, int]: +def matrix_dimensions(matrix: list) -> tuple[int, int]: return len(matrix), len(matrix[0]) -def print_matrix(matrix: List) -> None: +def print_matrix(matrix: list) -> None: for i in range(len(matrix)): print(matrix[i]) -def actual_strassen(matrix_a: List, matrix_b: List) -> List: +def actual_strassen(matrix_a: list, matrix_b: list) -> list: """ Recursive function to calculate the product of two matrices, using the Strassen Algorithm. It only supports even length matrices. @@ -106,7 +105,7 @@ def actual_strassen(matrix_a: List, matrix_b: List) -> List: return new_matrix -def strassen(matrix1: List, matrix2: List) -> List: +def strassen(matrix1: list, matrix2: list) -> list: """ >>> strassen([[2,1,3],[3,4,6],[1,4,2],[7,6,7]], [[4,2,3,4],[2,1,1,1],[8,6,4,2]]) [[34, 23, 19, 15], [68, 46, 37, 28], [28, 18, 15, 12], [96, 62, 55, 48]] diff --git a/dynamic_programming/fast_fibonacci.py b/dynamic_programming/fast_fibonacci.py index 63481fe70..f48186a34 100644 --- a/dynamic_programming/fast_fibonacci.py +++ b/dynamic_programming/fast_fibonacci.py @@ -4,8 +4,9 @@ This program calculates the nth Fibonacci number in O(log(n)). It's possible to calculate F(1_000_000) in less than a second. """ +from __future__ import annotations + import sys -from typing import Tuple def fibonacci(n: int) -> int: @@ -20,7 +21,7 @@ def fibonacci(n: int) -> int: # returns (F(n), F(n-1)) -def _fib(n: int) -> Tuple[int, int]: +def _fib(n: int) -> tuple[int, int]: if n == 0: # (F(0), F(1)) return (0, 1) diff --git a/dynamic_programming/fractional_knapsack_2.py b/dynamic_programming/fractional_knapsack_2.py index eadb73c61..cae577383 100644 --- a/dynamic_programming/fractional_knapsack_2.py +++ b/dynamic_programming/fractional_knapsack_2.py @@ -2,12 +2,12 @@ # https://www.guru99.com/fractional-knapsack-problem-greedy.html # https://medium.com/walkinthecode/greedy-algorithm-fractional-knapsack-problem-9aba1daecc93 -from typing import List, Tuple +from __future__ import annotations def fractional_knapsack( - value: List[int], weight: List[int], capacity: int -) -> Tuple[int, List[int]]: + value: list[int], weight: list[int], capacity: int +) -> tuple[int, list[int]]: """ >>> value = [1, 3, 5, 7, 9] >>> weight = [0.9, 0.7, 0.5, 0.3, 0.1] diff --git a/dynamic_programming/iterating_through_submasks.py b/dynamic_programming/iterating_through_submasks.py index cb27a5b88..855af61d6 100644 --- a/dynamic_programming/iterating_through_submasks.py +++ b/dynamic_programming/iterating_through_submasks.py @@ -5,10 +5,10 @@ You are given a bitmask m and you want to efficiently iterate through all of its submasks. The mask s is submask of m if only bits that were included in bitmask are set """ -from typing import List +from __future__ import annotations -def list_of_submasks(mask: int) -> List[int]: +def list_of_submasks(mask: int) -> list[int]: """ Args: diff --git a/dynamic_programming/longest_increasing_subsequence.py b/dynamic_programming/longest_increasing_subsequence.py index 48d5e8e8f..f5ca8a2b5 100644 --- a/dynamic_programming/longest_increasing_subsequence.py +++ b/dynamic_programming/longest_increasing_subsequence.py @@ -10,10 +10,10 @@ return it. Example: [10, 22, 9, 33, 21, 50, 41, 60, 80] as input will return [10, 22, 33, 41, 60, 80] as output """ -from typing import List +from __future__ import annotations -def longest_subsequence(array: List[int]) -> List[int]: # This function is recursive +def longest_subsequence(array: list[int]) -> list[int]: # This function is recursive """ Some examples >>> longest_subsequence([10, 22, 9, 33, 21, 50, 41, 60, 80]) diff --git a/dynamic_programming/longest_increasing_subsequence_o(nlogn).py b/dynamic_programming/longest_increasing_subsequence_o(nlogn).py index b33774057..af536f8bb 100644 --- a/dynamic_programming/longest_increasing_subsequence_o(nlogn).py +++ b/dynamic_programming/longest_increasing_subsequence_o(nlogn).py @@ -4,7 +4,7 @@ # comments: This programme outputs the Longest Strictly Increasing Subsequence in # O(NLogN) Where N is the Number of elements in the list ############################# -from typing import List +from __future__ import annotations def CeilIndex(v, l, r, key): # noqa: E741 @@ -17,7 +17,7 @@ def CeilIndex(v, l, r, key): # noqa: E741 return r -def LongestIncreasingSubsequenceLength(v: List[int]) -> int: +def LongestIncreasingSubsequenceLength(v: list[int]) -> int: """ >>> LongestIncreasingSubsequenceLength([2, 5, 3, 7, 11, 8, 10, 13, 6]) 6 diff --git a/dynamic_programming/max_non_adjacent_sum.py b/dynamic_programming/max_non_adjacent_sum.py index 15dd8ce66..5362b22ca 100644 --- a/dynamic_programming/max_non_adjacent_sum.py +++ b/dynamic_programming/max_non_adjacent_sum.py @@ -1,9 +1,9 @@ # Video Explanation: https://www.youtube.com/watch?v=6w60Zi1NtL8&feature=emb_logo -from typing import List +from __future__ import annotations -def maximum_non_adjacent_sum(nums: List[int]) -> int: +def maximum_non_adjacent_sum(nums: list[int]) -> int: """ Find the maximum non-adjacent sum of the integers in the nums input list diff --git a/dynamic_programming/max_sub_array.py b/dynamic_programming/max_sub_array.py index 1ca4f90bb..3060010ef 100644 --- a/dynamic_programming/max_sub_array.py +++ b/dynamic_programming/max_sub_array.py @@ -1,7 +1,7 @@ """ author : Mayank Kumar Jha (mk9440) """ -from typing import List +from __future__ import annotations def find_max_sub_array(A, low, high): @@ -38,7 +38,7 @@ def find_max_cross_sum(A, low, mid, high): return max_left, max_right, (left_sum + right_sum) -def max_sub_array(nums: List[int]) -> int: +def max_sub_array(nums: list[int]) -> int: """ Finds the contiguous subarray which has the largest sum and return its sum. diff --git a/dynamic_programming/minimum_cost_path.py b/dynamic_programming/minimum_cost_path.py index 09295a4fa..3ad24b552 100644 --- a/dynamic_programming/minimum_cost_path.py +++ b/dynamic_programming/minimum_cost_path.py @@ -1,9 +1,9 @@ # Youtube Explanation: https://www.youtube.com/watch?v=lBRtnuxg-gU -from typing import List +from __future__ import annotations -def minimum_cost_path(matrix: List[List[int]]) -> int: +def minimum_cost_path(matrix: list[list[int]]) -> int: """ Find the minimum cost traced by all possible paths from top left to bottom right in a given matrix diff --git a/genetic_algorithm/basic_string.py b/genetic_algorithm/basic_string.py index 482a6cb5e..97dbe182b 100644 --- a/genetic_algorithm/basic_string.py +++ b/genetic_algorithm/basic_string.py @@ -5,8 +5,9 @@ https://en.wikipedia.org/wiki/Genetic_algorithm Author: D4rkia """ +from __future__ import annotations + import random -from typing import List, Tuple # Maximum size of the population. bigger could be faster but is more memory expensive N_POPULATION = 200 @@ -20,7 +21,7 @@ MUTATION_PROBABILITY = 0.4 random.seed(random.randint(0, 1000)) -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. @@ -69,7 +70,7 @@ def basic(target: str, genes: List[str], debug: bool = True) -> Tuple[int, int, total_population += len(population) # Random population created now it's time to evaluate - def evaluate(item: str, main_target: str = target) -> Tuple[str, float]: + 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 @@ -84,7 +85,7 @@ def basic(target: str, genes: List[str], debug: bool = True) -> Tuple[int, int, # Adding a bit of concurrency can make everything faster, # # import concurrent.futures - # population_score: List[Tuple[str, float]] = [] + # population_score: list[tuple[str, float]] = [] # with concurrent.futures.ThreadPoolExecutor( # max_workers=NUM_WORKERS) as executor: # futures = {executor.submit(evaluate, item) for item in population} @@ -121,7 +122,7 @@ def basic(target: str, genes: List[str], debug: bool = True) -> Tuple[int, int, ] # Select, Crossover and Mutate a new population - def select(parent_1: Tuple[str, float]) -> List[str]: + def select(parent_1: tuple[str, float]) -> list[str]: """Select the second parent and generate new population""" pop = [] # Generate more child proportionally to the fitness score @@ -135,7 +136,7 @@ def basic(target: str, genes: List[str], debug: bool = True) -> Tuple[int, int, pop.append(mutate(child_2)) return pop - def crossover(parent_1: str, parent_2: str) -> Tuple[str, str]: + def crossover(parent_1: str, parent_2: str) -> tuple[str, str]: """Slice and combine two string in a random point""" random_slice = random.randint(0, len(parent_1) - 1) child_1 = parent_1[:random_slice] + parent_2[random_slice:] diff --git a/graphics/bezier_curve.py b/graphics/bezier_curve.py index 48755647e..295ff47e8 100644 --- a/graphics/bezier_curve.py +++ b/graphics/bezier_curve.py @@ -1,6 +1,6 @@ # https://en.wikipedia.org/wiki/B%C3%A9zier_curve # https://www.tutorialspoint.com/computer_graphics/computer_graphics_curves.htm -from typing import List, Tuple +from __future__ import annotations from scipy.special import comb @@ -12,7 +12,7 @@ class BezierCurve: This implementation works only for 2d coordinates in the xy plane. """ - def __init__(self, list_of_points: List[Tuple[float, float]]): + def __init__(self, list_of_points: list[tuple[float, float]]): """ list_of_points: Control points in the xy plane on which to interpolate. These points control the behavior (shape) of the Bezier curve. @@ -22,7 +22,7 @@ class BezierCurve: # Degree = 1 will produce a straight line. self.degree = len(list_of_points) - 1 - def basis_function(self, t: float) -> List[float]: + def basis_function(self, t: float) -> list[float]: """ The basis function determines the weight of each control point at time t. t: time value between 0 and 1 inclusive at which to evaluate the basis of @@ -36,7 +36,7 @@ class BezierCurve: [0.0, 1.0] """ assert 0 <= t <= 1, "Time t must be between 0 and 1." - output_values: List[float] = [] + output_values: list[float] = [] for i in range(len(self.list_of_points)): # basis function for each i output_values.append( @@ -46,7 +46,7 @@ class BezierCurve: assert round(sum(output_values), 5) == 1 return output_values - def bezier_curve_function(self, t: float) -> Tuple[float, float]: + def bezier_curve_function(self, t: float) -> tuple[float, float]: """ The function to produce the values of the Bezier curve at time t. t: the value of time t at which to evaluate the Bezier function @@ -80,8 +80,8 @@ class BezierCurve: """ from matplotlib import pyplot as plt - to_plot_x: List[float] = [] # x coordinates of points to plot - to_plot_y: List[float] = [] # y coordinates of points to plot + to_plot_x: list[float] = [] # x coordinates of points to plot + to_plot_y: list[float] = [] # y coordinates of points to plot t = 0.0 while t <= 1: diff --git a/graphs/bellman_ford.py b/graphs/bellman_ford.py index d4d37a365..ace798564 100644 --- a/graphs/bellman_ford.py +++ b/graphs/bellman_ford.py @@ -1,4 +1,4 @@ -from typing import Dict, List +from __future__ import annotations def printDist(dist, V): @@ -7,7 +7,7 @@ def printDist(dist, V): print("\t".join(f"{i}\t{d}" for i, d in enumerate(distances))) -def BellmanFord(graph: List[Dict[str, int]], V: int, E: int, src: int) -> int: +def BellmanFord(graph: list[dict[str, int]], V: int, E: int, src: int) -> int: """ Returns shortest paths from a vertex src to all other vertices. diff --git a/graphs/bidirectional_a_star.py b/graphs/bidirectional_a_star.py index 76313af76..72ff4fa65 100644 --- a/graphs/bidirectional_a_star.py +++ b/graphs/bidirectional_a_star.py @@ -2,9 +2,10 @@ https://en.wikipedia.org/wiki/Bidirectional_search """ +from __future__ import annotations + import time from math import sqrt -from typing import List, Tuple # 1 for manhattan, 0 for euclidean HEURISTIC = 0 @@ -89,7 +90,7 @@ class AStar: self.reached = False - def search(self) -> List[Tuple[int]]: + def search(self) -> list[tuple[int]]: while self.open_nodes: # Open Nodes are sorted using __lt__ self.open_nodes.sort() @@ -120,7 +121,7 @@ class AStar: if not (self.reached): return [(self.start.pos)] - def get_successors(self, parent: Node) -> List[Node]: + def get_successors(self, parent: Node) -> list[Node]: """ Returns a list of successors (both in the grid and free spaces) """ @@ -146,7 +147,7 @@ class AStar: ) return successors - def retrace_path(self, node: Node) -> List[Tuple[int]]: + def retrace_path(self, node: Node) -> list[tuple[int]]: """ Retrace the path from parents to parents until start node """ @@ -177,7 +178,7 @@ class BidirectionalAStar: self.bwd_astar = AStar(goal, start) self.reached = False - def search(self) -> List[Tuple[int]]: + def search(self) -> list[tuple[int]]: while self.fwd_astar.open_nodes or self.bwd_astar.open_nodes: self.fwd_astar.open_nodes.sort() self.bwd_astar.open_nodes.sort() @@ -224,7 +225,7 @@ class BidirectionalAStar: def retrace_bidirectional_path( self, fwd_node: Node, bwd_node: Node - ) -> List[Tuple[int]]: + ) -> list[tuple[int]]: fwd_path = self.fwd_astar.retrace_path(fwd_node) bwd_path = self.bwd_astar.retrace_path(bwd_node) bwd_path.pop() diff --git a/graphs/bidirectional_breadth_first_search.py b/graphs/bidirectional_breadth_first_search.py index d941c0db5..39d8dc7d4 100644 --- a/graphs/bidirectional_breadth_first_search.py +++ b/graphs/bidirectional_breadth_first_search.py @@ -2,8 +2,9 @@ https://en.wikipedia.org/wiki/Bidirectional_search """ +from __future__ import annotations + import time -from typing import List, Tuple grid = [ [0, 0, 0, 0, 0, 0, 0], @@ -51,7 +52,7 @@ class BreadthFirstSearch: self.node_queue = [self.start] self.reached = False - def search(self) -> List[Tuple[int]]: + def search(self) -> list[tuple[int]]: while self.node_queue: current_node = self.node_queue.pop(0) @@ -67,7 +68,7 @@ class BreadthFirstSearch: if not (self.reached): return [(self.start.pos)] - def get_successors(self, parent: Node) -> List[Node]: + def get_successors(self, parent: Node) -> list[Node]: """ Returns a list of successors (both in the grid and free spaces) """ @@ -86,7 +87,7 @@ class BreadthFirstSearch: ) return successors - def retrace_path(self, node: Node) -> List[Tuple[int]]: + def retrace_path(self, node: Node) -> list[tuple[int]]: """ Retrace the path from parents to parents until start node """ @@ -118,7 +119,7 @@ class BidirectionalBreadthFirstSearch: self.bwd_bfs = BreadthFirstSearch(goal, start) self.reached = False - def search(self) -> List[Tuple[int]]: + def search(self) -> list[tuple[int]]: while self.fwd_bfs.node_queue or self.bwd_bfs.node_queue: current_fwd_node = self.fwd_bfs.node_queue.pop(0) current_bwd_node = self.bwd_bfs.node_queue.pop(0) @@ -146,7 +147,7 @@ class BidirectionalBreadthFirstSearch: def retrace_bidirectional_path( self, fwd_node: Node, bwd_node: Node - ) -> List[Tuple[int]]: + ) -> list[tuple[int]]: fwd_path = self.fwd_bfs.retrace_path(fwd_node) bwd_path = self.bwd_bfs.retrace_path(bwd_node) bwd_path.pop() diff --git a/graphs/breadth_first_search_2.py b/graphs/breadth_first_search_2.py index 293a1012f..a90e963a4 100644 --- a/graphs/breadth_first_search_2.py +++ b/graphs/breadth_first_search_2.py @@ -12,7 +12,7 @@ while Q is non-empty: mark w as explored add w to Q (at the end) """ -from typing import Dict, Set +from __future__ import annotations G = { "A": ["B", "C"], @@ -24,7 +24,7 @@ G = { } -def breadth_first_search(graph: Dict, start: str) -> Set[str]: +def breadth_first_search(graph: dict, start: str) -> set[str]: """ >>> ''.join(sorted(breadth_first_search(G, 'A'))) 'ABCDEF' diff --git a/graphs/breadth_first_search_shortest_path.py b/graphs/breadth_first_search_shortest_path.py index c25a5bb4f..b43479d46 100644 --- a/graphs/breadth_first_search_shortest_path.py +++ b/graphs/breadth_first_search_shortest_path.py @@ -1,7 +1,7 @@ """Breath First Search (BFS) can be used when finding the shortest path from a given source node to a target node in an unweighted graph. """ -from typing import Dict +from __future__ import annotations graph = { "A": ["B", "C", "E"], @@ -15,7 +15,7 @@ graph = { class Graph: - def __init__(self, graph: Dict[str, str], source_vertex: str) -> None: + def __init__(self, graph: dict[str, str], source_vertex: str) -> None: """Graph is implemented as dictionary of adjacency lists. Also, Source vertex have to be defined upon initialization. """ diff --git a/graphs/depth_first_search.py b/graphs/depth_first_search.py index 43f2eaaea..907cc172f 100644 --- a/graphs/depth_first_search.py +++ b/graphs/depth_first_search.py @@ -1,9 +1,9 @@ """Non recursive implementation of a DFS algorithm.""" -from typing import Dict, Set +from __future__ import annotations -def depth_first_search(graph: Dict, start: str) -> Set[int]: +def depth_first_search(graph: dict, start: str) -> set[int]: """Depth First Search on Graph :param graph: directed graph in dictionary format :param vertex: starting vertex as a string diff --git a/graphs/gale_shapley_bigraph.py b/graphs/gale_shapley_bigraph.py index 07a3922f8..59baf8296 100644 --- a/graphs/gale_shapley_bigraph.py +++ b/graphs/gale_shapley_bigraph.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def stable_matching(donor_pref: List[int], recipient_pref: List[int]) -> List[int]: +def stable_matching(donor_pref: list[int], recipient_pref: list[int]) -> list[int]: """ Finds the stable match in any bipartite graph, i.e a pairing where no 2 objects prefer each other over their partner. The function accepts the preferences of diff --git a/graphs/greedy_best_first.py b/graphs/greedy_best_first.py index 2e63a50ce..4b80a6853 100644 --- a/graphs/greedy_best_first.py +++ b/graphs/greedy_best_first.py @@ -2,7 +2,7 @@ https://en.wikipedia.org/wiki/Best-first_search#Greedy_BFS """ -from typing import List, Tuple +from __future__ import annotations grid = [ [0, 0, 0, 0, 0, 0, 0], @@ -81,7 +81,7 @@ class GreedyBestFirst: self.reached = False - def search(self) -> List[Tuple[int]]: + def search(self) -> list[tuple[int]]: """ Search for the path, if a path is not found, only the starting position is returned @@ -116,7 +116,7 @@ class GreedyBestFirst: if not (self.reached): return [self.start.pos] - def get_successors(self, parent: Node) -> List[Node]: + def get_successors(self, parent: Node) -> list[Node]: """ Returns a list of successors (both in the grid and free spaces) """ @@ -143,7 +143,7 @@ class GreedyBestFirst: ) return successors - def retrace_path(self, node: Node) -> List[Tuple[int]]: + def retrace_path(self, node: Node) -> list[tuple[int]]: """ Retrace the path from parents to parents until start node """ diff --git a/graphs/karger.py b/graphs/karger.py index baa0eebd9..f72128c81 100644 --- a/graphs/karger.py +++ b/graphs/karger.py @@ -2,8 +2,9 @@ An implementation of Karger's Algorithm for partitioning a graph. """ +from __future__ import annotations + import random -from typing import Dict, List, Set, Tuple # Adjacency list representation of this graph: # https://en.wikipedia.org/wiki/File:Single_run_of_Karger%E2%80%99s_Mincut_algorithm.svg @@ -21,7 +22,7 @@ TEST_GRAPH = { } -def partition_graph(graph: Dict[str, List[str]]) -> Set[Tuple[str, str]]: +def partition_graph(graph: dict[str, list[str]]) -> set[tuple[str, str]]: """ Partitions a graph using Karger's Algorithm. Implemented from pseudocode found here: @@ -60,9 +61,7 @@ def partition_graph(graph: Dict[str, List[str]]) -> Set[Tuple[str, str]]: for neighbor in uv_neighbors: graph_copy[neighbor].append(uv) - contracted_nodes[uv] = { - node for node in contracted_nodes[u].union(contracted_nodes[v]) - } + contracted_nodes[uv] = set(contracted_nodes[u].union(contracted_nodes[v])) # Remove nodes u and v. del graph_copy[u] diff --git a/graphs/prim.py b/graphs/prim.py index f7376cfb4..70329da7e 100644 --- a/graphs/prim.py +++ b/graphs/prim.py @@ -100,7 +100,7 @@ def prim_heap(graph: list, root: Vertex) -> Iterator[tuple]: u.pi = None root.key = 0 - h = [v for v in graph] + h = list(graph) hq.heapify(h) while h: diff --git a/linear_algebra/src/polynom_for_points.py b/linear_algebra/src/polynom_for_points.py index 8db89fc2c..7a363723d 100644 --- a/linear_algebra/src/polynom_for_points.py +++ b/linear_algebra/src/polynom_for_points.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def points_to_polynomial(coordinates: List[List[int]]) -> str: +def points_to_polynomial(coordinates: list[list[int]]) -> str: """ coordinates is a two dimensional matrix: [[x, y], [x, y], ...] number of points you want to use @@ -60,7 +60,7 @@ def points_to_polynomial(coordinates: List[List[int]]) -> str: while count_of_line < x: count_in_line = 0 a = coordinates[count_of_line][0] - count_line: List[int] = [] + count_line: list[int] = [] while count_in_line < x: count_line.append(a ** (x - (count_in_line + 1))) count_in_line += 1 @@ -69,7 +69,7 @@ def points_to_polynomial(coordinates: List[List[int]]) -> str: count_of_line = 0 # put the y values into a vector - vector: List[int] = [] + vector: list[int] = [] while count_of_line < x: vector.append(coordinates[count_of_line][1]) count_of_line += 1 @@ -94,7 +94,7 @@ def points_to_polynomial(coordinates: List[List[int]]) -> str: count = 0 # make solutions - solution: List[str] = [] + solution: list[str] = [] while count < x: solution.append(vector[count] / matrix[count][count]) count += 1 @@ -103,7 +103,7 @@ def points_to_polynomial(coordinates: List[List[int]]) -> str: solved = "f(x)=" while count < x: - remove_e: List[str] = str(solution[count]).split("E") + remove_e: list[str] = str(solution[count]).split("E") if len(remove_e) > 1: solution[count] = remove_e[0] + "*10^" + remove_e[1] solved += "x^" + str(x - (count + 1)) + "*" + str(solution[count]) diff --git a/linear_algebra/src/transformations_2d.py b/linear_algebra/src/transformations_2d.py index 9ee238fd7..6a15189c5 100644 --- a/linear_algebra/src/transformations_2d.py +++ b/linear_algebra/src/transformations_2d.py @@ -11,11 +11,12 @@ projection(45) = [[0.27596319193541496, 0.446998331800279], reflection(45) = [[0.05064397763545947, 0.893996663600558], [0.893996663600558, 0.7018070490682369]] """ +from __future__ import annotations + from math import cos, sin -from typing import List -def scaling(scaling_factor: float) -> List[List[float]]: +def scaling(scaling_factor: float) -> list[list[float]]: """ >>> scaling(5) [[5.0, 0.0], [0.0, 5.0]] @@ -24,7 +25,7 @@ def scaling(scaling_factor: float) -> List[List[float]]: return [[scaling_factor * int(x == y) for x in range(2)] for y in range(2)] -def rotation(angle: float) -> List[List[float]]: +def rotation(angle: float) -> list[list[float]]: """ >>> rotation(45) # doctest: +NORMALIZE_WHITESPACE [[0.5253219888177297, -0.8509035245341184], @@ -34,7 +35,7 @@ def rotation(angle: float) -> List[List[float]]: return [[c, -s], [s, c]] -def projection(angle: float) -> List[List[float]]: +def projection(angle: float) -> list[list[float]]: """ >>> projection(45) # doctest: +NORMALIZE_WHITESPACE [[0.27596319193541496, 0.446998331800279], @@ -45,7 +46,7 @@ def projection(angle: float) -> List[List[float]]: return [[c * c, cs], [cs, s * s]] -def reflection(angle: float) -> List[List[float]]: +def reflection(angle: float) -> list[list[float]]: """ >>> reflection(45) # doctest: +NORMALIZE_WHITESPACE [[0.05064397763545947, 0.893996663600558], diff --git a/maths/3n_plus_1.py b/maths/3n_plus_1.py index baaa74f89..28c9fd7b4 100644 --- a/maths/3n_plus_1.py +++ b/maths/3n_plus_1.py @@ -1,7 +1,7 @@ -from typing import List, Tuple +from __future__ import annotations -def n31(a: int) -> Tuple[List[int], int]: +def n31(a: int) -> tuple[list[int], int]: """ Returns the Collatz sequence and its length of any positive integer. >>> n31(4) diff --git a/maths/abs_max.py b/maths/abs_max.py index 554e27f6e..e5a821965 100644 --- a/maths/abs_max.py +++ b/maths/abs_max.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def abs_max(x: List[int]) -> int: +def abs_max(x: list[int]) -> int: """ >>> abs_max([0,5,1,11]) 11 diff --git a/maths/allocation_number.py b/maths/allocation_number.py index c6f1e562f..4e74bb2e6 100644 --- a/maths/allocation_number.py +++ b/maths/allocation_number.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def allocation_num(number_of_bytes: int, partitions: int) -> List[str]: +def allocation_num(number_of_bytes: int, partitions: int) -> list[str]: """ Divide a number of bytes into x partitions. diff --git a/maths/collatz_sequence.py b/maths/collatz_sequence.py index 6ace77312..7b3636de6 100644 --- a/maths/collatz_sequence.py +++ b/maths/collatz_sequence.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def collatz_sequence(n: int) -> List[int]: +def collatz_sequence(n: int) -> list[int]: """ Collatz conjecture: start with any positive integer n. The next term is obtained as follows: diff --git a/maths/entropy.py b/maths/entropy.py index c380afd3b..74980ef9e 100644 --- a/maths/entropy.py +++ b/maths/entropy.py @@ -4,11 +4,11 @@ Implementation of entropy of information https://en.wikipedia.org/wiki/Entropy_(information_theory) """ +from __future__ import annotations import math from collections import Counter from string import ascii_lowercase -from typing import Tuple def calculate_prob(text: str) -> None: @@ -89,7 +89,7 @@ def calculate_prob(text: str) -> None: print("{0:.1f}".format(round(((-1 * my_sec_sum) - (-1 * my_fir_sum))))) -def analyze_text(text: str) -> Tuple[dict, dict]: +def analyze_text(text: str) -> tuple[dict, dict]: """ Convert text input into two dicts of counts. The first dictionary stores the frequency of single character strings. diff --git a/maths/is_square_free.py b/maths/is_square_free.py index 6d27d0af3..8d83d95ff 100644 --- a/maths/is_square_free.py +++ b/maths/is_square_free.py @@ -3,10 +3,10 @@ References: wikipedia:square free number python/black : True flake8 : True """ -from typing import List +from __future__ import annotations -def is_square_free(factors: List[int]) -> bool: +def is_square_free(factors: list[int]) -> bool: """ # doctest: +NORMALIZE_WHITESPACE This functions takes a list of prime factors as input. diff --git a/maths/line_length.py b/maths/line_length.py index 6df0a916e..1d386b44b 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -1,4 +1,4 @@ -import math as m +import math from typing import Callable, Union @@ -29,7 +29,7 @@ def line_length( '10.000000' >>> def f(x): - ... return m.sin(5 * x) + m.cos(10 * x) + x * x/10 + ... return math.sin(5 * x) + math.cos(10 * x) + x * x/10 >>> f"{line_length(f, 0.0, 10.0, 10000):.6f}" '69.534930' """ @@ -43,7 +43,7 @@ def line_length( # Approximates curve as a sequence of linear lines and sums their length x2 = (x_end - x_start) / steps + x1 fx2 = fnc(x2) - length += m.hypot(x2 - x1, fx2 - fx1) + length += math.hypot(x2 - x1, fx2 - fx1) # Increment step x1 = x2 @@ -55,7 +55,7 @@ def line_length( if __name__ == "__main__": def f(x): - return m.sin(10 * x) + return math.sin(10 * x) print("f(x) = sin(10 * x)") print("The length of the curve from x = -10 to x = 10 is:") diff --git a/maths/monte_carlo_dice.py b/maths/monte_carlo_dice.py index c36c3e83e..e8e3abe83 100644 --- a/maths/monte_carlo_dice.py +++ b/maths/monte_carlo_dice.py @@ -1,5 +1,6 @@ +from __future__ import annotations + import random -from typing import List class Dice: @@ -16,7 +17,7 @@ class Dice: return "Fair Dice" -def throw_dice(num_throws: int, num_dice: int = 2) -> List[float]: +def throw_dice(num_throws: int, num_dice: int = 2) -> list[float]: """ Return probability list of all possible sums when throwing dice. @@ -35,7 +36,7 @@ def throw_dice(num_throws: int, num_dice: int = 2) -> List[float]: dices = [Dice() for i in range(num_dice)] count_of_sum = [0] * (len(dices) * Dice.NUM_SIDES + 1) for i in range(num_throws): - count_of_sum[sum([dice.roll() for dice in dices])] += 1 + count_of_sum[sum(dice.roll() for dice in dices)] += 1 probability = [round((count * 100) / num_throws, 2) for count in count_of_sum] return probability[num_dice:] # remove probability of sums that never appear diff --git a/maths/prime_factors.py b/maths/prime_factors.py index 34795dd98..e520ae3a6 100644 --- a/maths/prime_factors.py +++ b/maths/prime_factors.py @@ -1,10 +1,10 @@ """ python/black : True """ -from typing import List +from __future__ import annotations -def prime_factors(n: int) -> List[int]: +def prime_factors(n: int) -> list[int]: """ Returns prime factors of n as a list. diff --git a/maths/quadratic_equations_complex_numbers.py b/maths/quadratic_equations_complex_numbers.py index 7c47bdef2..01a411bc5 100644 --- a/maths/quadratic_equations_complex_numbers.py +++ b/maths/quadratic_equations_complex_numbers.py @@ -1,8 +1,9 @@ +from __future__ import annotations + from cmath import sqrt -from typing import Tuple -def quadratic_roots(a: int, b: int, c: int) -> Tuple[complex, complex]: +def quadratic_roots(a: int, b: int, c: int) -> tuple[complex, complex]: """ Given the numerical coefficients a, b and c, calculates the roots for any quadratic equation of the form ax^2 + bx + c diff --git a/maths/relu.py b/maths/relu.py index 826ada65f..458c6bd5c 100644 --- a/maths/relu.py +++ b/maths/relu.py @@ -9,12 +9,12 @@ After through ReLU, the element of the vector always 0 or real number. Script inspired from its corresponding Wikipedia article https://en.wikipedia.org/wiki/Rectifier_(neural_networks) """ -from typing import List +from __future__ import annotations import numpy as np -def relu(vector: List[float]): +def relu(vector: list[float]): """ Implements the relu function diff --git a/matrix/inverse_of_matrix.py b/matrix/inverse_of_matrix.py index abbeb79dd..9deca6c3c 100644 --- a/matrix/inverse_of_matrix.py +++ b/matrix/inverse_of_matrix.py @@ -1,8 +1,9 @@ +from __future__ import annotations + from decimal import Decimal -from typing import List -def inverse_of_matrix(matrix: List[List[float]]) -> List[List[float]]: +def inverse_of_matrix(matrix: list[list[float]]) -> list[list[float]]: """ A matrix multiplied with its inverse gives the identity matrix. This function finds the inverse of a 2x2 matrix. diff --git a/matrix/matrix_operation.py b/matrix/matrix_operation.py index 3838dab6b..dca01f9c3 100644 --- a/matrix/matrix_operation.py +++ b/matrix/matrix_operation.py @@ -2,10 +2,10 @@ Functions for 2D matrix operations """ -from typing import List, Tuple +from __future__ import annotations -def add(*matrix_s: List[list]) -> List[list]: +def add(*matrix_s: list[list]) -> list[list]: """ >>> add([[1,2],[3,4]],[[2,3],[4,5]]) [[3, 5], [7, 9]] @@ -20,7 +20,7 @@ def add(*matrix_s: List[list]) -> List[list]: return [[sum(t) for t in zip(*m)] for m in zip(*matrix_s)] -def subtract(matrix_a: List[list], matrix_b: List[list]) -> List[list]: +def subtract(matrix_a: list[list], matrix_b: list[list]) -> list[list]: """ >>> subtract([[1,2],[3,4]],[[2,3],[4,5]]) [[-1, -1], [-1, -1]] @@ -35,7 +35,7 @@ def subtract(matrix_a: List[list], matrix_b: List[list]) -> List[list]: return [[i - j for i, j in zip(*m)] for m in zip(matrix_a, matrix_b)] -def scalar_multiply(matrix: List[list], n: int) -> List[list]: +def scalar_multiply(matrix: list[list], n: int) -> list[list]: """ >>> scalar_multiply([[1,2],[3,4]],5) [[5, 10], [15, 20]] @@ -45,7 +45,7 @@ def scalar_multiply(matrix: List[list], n: int) -> List[list]: return [[x * n for x in row] for row in matrix] -def multiply(matrix_a: List[list], matrix_b: List[list]) -> List[list]: +def multiply(matrix_a: list[list], matrix_b: list[list]) -> list[list]: """ >>> multiply([[1,2],[3,4]],[[5,5],[7,5]]) [[19, 15], [43, 35]] @@ -67,7 +67,7 @@ def multiply(matrix_a: List[list], matrix_b: List[list]) -> List[list]: ] -def identity(n: int) -> List[list]: +def identity(n: int) -> list[list]: """ :param n: dimension for nxn matrix :type n: int @@ -79,7 +79,7 @@ def identity(n: int) -> List[list]: return [[int(row == column) for column in range(n)] for row in range(n)] -def transpose(matrix: List[list], return_map: bool = True) -> List[list]: +def transpose(matrix: list[list], return_map: bool = True) -> list[list]: """ >>> transpose([[1,2],[3,4]]) # doctest: +ELLIPSIS List[list]: return list(map(list, zip(*matrix))) -def minor(matrix: List[list], row: int, column: int) -> List[list]: +def minor(matrix: list[list], row: int, column: int) -> list[list]: """ >>> minor([[1, 2], [3, 4]], 1, 1) [[1]] @@ -102,7 +102,7 @@ def minor(matrix: List[list], row: int, column: int) -> List[list]: return [row[:column] + row[column + 1 :] for row in minor] -def determinant(matrix: List[list]) -> int: +def determinant(matrix: list[list]) -> int: """ >>> determinant([[1, 2], [3, 4]]) -2 @@ -118,7 +118,7 @@ def determinant(matrix: List[list]) -> int: ) -def inverse(matrix: List[list]) -> List[list]: +def inverse(matrix: list[list]) -> list[list]: """ >>> inverse([[1, 2], [3, 4]]) [[-2.0, 1.0], [1.5, -0.5]] @@ -142,17 +142,17 @@ def inverse(matrix: List[list]) -> List[list]: return scalar_multiply(adjugate, 1 / det) -def _check_not_integer(matrix: List[list]) -> bool: +def _check_not_integer(matrix: list[list]) -> bool: if not isinstance(matrix, int) and not isinstance(matrix[0], int): return True raise TypeError("Expected a matrix, got int/list instead") -def _shape(matrix: List[list]) -> list: +def _shape(matrix: list[list]) -> list: return len(matrix), len(matrix[0]) -def _verify_matrix_sizes(matrix_a: List[list], matrix_b: List[list]) -> Tuple[list]: +def _verify_matrix_sizes(matrix_a: list[list], matrix_b: list[list]) -> tuple[list]: shape = _shape(matrix_a) + _shape(matrix_b) if shape[0] != shape[3] or shape[1] != shape[2]: raise ValueError( diff --git a/matrix/searching_in_sorted_matrix.py b/matrix/searching_in_sorted_matrix.py index 470fc01df..ca6263a32 100644 --- a/matrix/searching_in_sorted_matrix.py +++ b/matrix/searching_in_sorted_matrix.py @@ -1,21 +1,23 @@ -from typing import List, Union +from __future__ import annotations + +from typing import Union def search_in_a_sorted_matrix( - mat: List[list], m: int, n: int, key: Union[int, float] + mat: list[list], m: int, n: int, key: Union[int, float] ) -> None: """ - >>> search_in_a_sorted_matrix(\ - [[2, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]], 3, 3, 5) + >>> search_in_a_sorted_matrix( + ... [[2, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]], 3, 3, 5) Key 5 found at row- 1 column- 2 - >>> search_in_a_sorted_matrix(\ - [[2, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]], 3, 3, 21) + >>> search_in_a_sorted_matrix( + ... [[2, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]], 3, 3, 21) Key 21 not found - >>> search_in_a_sorted_matrix(\ - [[2.1, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]], 3, 3, 2.1) + >>> search_in_a_sorted_matrix( + ... [[2.1, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]], 3, 3, 2.1) Key 2.1 found at row- 1 column- 1 - >>> search_in_a_sorted_matrix(\ - [[2.1, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]], 3, 3, 2.2) + >>> search_in_a_sorted_matrix( + ... [[2.1, 5, 7], [4, 8, 13], [9, 11, 15], [12, 17, 20]], 3, 3, 2.2) Key 2.2 not found """ i, j = m - 1, 0 diff --git a/other/dijkstra_bankers_algorithm.py b/other/dijkstra_bankers_algorithm.py index 405c10b88..be7bceba1 100644 --- a/other/dijkstra_bankers_algorithm.py +++ b/other/dijkstra_bankers_algorithm.py @@ -15,8 +15,9 @@ before deciding whether allocation should be allowed to continue. (https://rosettacode.org/wiki/Banker%27s_algorithm) """ +from __future__ import annotations + import time -from typing import Dict, List import numpy as np @@ -40,9 +41,9 @@ test_maximum_claim_table = [ class BankersAlgorithm: def __init__( self, - claim_vector: List[int], - allocated_resources_table: List[List[int]], - maximum_claim_table: List[List[int]], + claim_vector: list[int], + allocated_resources_table: list[list[int]], + maximum_claim_table: list[list[int]], ) -> None: """ :param claim_vector: A nxn/nxm list depicting the amount of each resources @@ -56,7 +57,7 @@ class BankersAlgorithm: self.__allocated_resources_table = allocated_resources_table self.__maximum_claim_table = maximum_claim_table - def __processes_resource_summation(self) -> List[int]: + def __processes_resource_summation(self) -> list[int]: """ Check for allocated resources in line with each resource in the claim vector """ @@ -65,7 +66,7 @@ class BankersAlgorithm: for i in range(len(self.__allocated_resources_table[0])) ] - def __available_resources(self) -> List[int]: + def __available_resources(self) -> list[int]: """ Check for available resources in line with each resource in the claim vector """ @@ -73,7 +74,7 @@ class BankersAlgorithm: self.__processes_resource_summation() ) - def __need(self) -> List[List[int]]: + def __need(self) -> list[list[int]]: """ Implement safety checker that calculates the needs by ensuring that max_claim[i][j] - alloc_table[i][j] <= avail[j] @@ -83,7 +84,7 @@ class BankersAlgorithm: for i, allocated_resource in enumerate(self.__allocated_resources_table) ] - def __need_index_manager(self) -> Dict[int, List[int]]: + def __need_index_manager(self) -> dict[int, list[int]]: """ This function builds an index control dictionary to track original ids/indices of processes when altered during execution of method "main" diff --git a/other/markov_chain.py b/other/markov_chain.py index 9b13fa515..b93c408cd 100644 --- a/other/markov_chain.py +++ b/other/markov_chain.py @@ -1,6 +1,7 @@ +from __future__ import annotations + from collections import Counter from random import random -from typing import Dict, List, Tuple class MarkovChainGraphUndirectedUnweighted: @@ -23,7 +24,7 @@ class MarkovChainGraphUndirectedUnweighted: self.add_node(node2) self.connections[node1][node2] = probability - def get_nodes(self) -> List[str]: + def get_nodes(self) -> list[str]: return list(self.connections) def transition(self, node: str) -> str: @@ -37,8 +38,8 @@ class MarkovChainGraphUndirectedUnweighted: def get_transitions( - start: str, transitions: List[Tuple[str, str, float]], steps: int -) -> Dict[str, int]: + start: str, transitions: list[tuple[str, str, float]], steps: int +) -> dict[str, int]: """ Running Markov Chain algorithm and calculating the number of times each node is visited diff --git a/other/triplet_sum.py b/other/triplet_sum.py index 25fed5d54..0e78bb52b 100644 --- a/other/triplet_sum.py +++ b/other/triplet_sum.py @@ -3,13 +3,14 @@ Given an array of integers and another integer target, we are required to find a triplet from the array such that it's sum is equal to the target. """ +from __future__ import annotations + from itertools import permutations from random import randint from timeit import repeat -from typing import List, Tuple -def make_dataset() -> Tuple[List[int], int]: +def make_dataset() -> tuple[list[int], int]: arr = [randint(-1000, 1000) for i in range(10)] r = randint(-5000, 5000) return (arr, r) @@ -18,7 +19,7 @@ def make_dataset() -> Tuple[List[int], int]: dataset = make_dataset() -def triplet_sum1(arr: List[int], target: int) -> Tuple[int, int, int]: +def triplet_sum1(arr: list[int], target: int) -> tuple[int, int, int]: """ Returns a triplet in the array with sum equal to target, else (0, 0, 0). @@ -37,7 +38,7 @@ def triplet_sum1(arr: List[int], target: int) -> Tuple[int, int, int]: return (0, 0, 0) -def triplet_sum2(arr: List[int], target: int) -> Tuple[int, int, int]: +def triplet_sum2(arr: list[int], target: int) -> tuple[int, int, int]: """ Returns a triplet in the array with sum equal to target, else (0, 0, 0). @@ -64,7 +65,7 @@ def triplet_sum2(arr: List[int], target: int) -> Tuple[int, int, int]: return (0, 0, 0) -def solution_times() -> Tuple[float, float]: +def solution_times() -> tuple[float, float]: setup_code = """ from __main__ import dataset, triplet_sum1, triplet_sum2 """ diff --git a/project_euler/problem_35/sol1.py b/project_euler/problem_35/sol1.py index c47eb7d82..5f023c56a 100644 --- a/project_euler/problem_35/sol1.py +++ b/project_euler/problem_35/sol1.py @@ -10,7 +10,7 @@ below 1 million using the Seive of Eratosthenes. Then, out of all these primes, we will rule out the numbers which contain an even digit. After this we will generate each circular combination of the number and check if all are prime. """ -from typing import List +from __future__ import annotations seive = [True] * 1000001 i = 2 @@ -47,7 +47,7 @@ def contains_an_even_digit(n: int) -> bool: return any(digit in "02468" for digit in str(n)) -def find_circular_primes(limit: int = 1000000) -> List[int]: +def find_circular_primes(limit: int = 1000000) -> list[int]: """ Return circular primes below limit. >>> len(find_circular_primes(100)) diff --git a/project_euler/problem_37/sol1.py b/project_euler/problem_37/sol1.py index c01d64d83..e3aec5a84 100644 --- a/project_euler/problem_37/sol1.py +++ b/project_euler/problem_37/sol1.py @@ -9,8 +9,7 @@ and right to left. NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes. """ - -from typing import List +from __future__ import annotations seive = [True] * 1000001 seive[1] = False @@ -36,7 +35,7 @@ def is_prime(n: int) -> bool: return seive[n] -def list_truncated_nums(n: int) -> List[int]: +def list_truncated_nums(n: int) -> list[int]: """ Returns a list of all left and right truncated numbers of n >>> list_truncated_nums(927628) @@ -71,7 +70,7 @@ def validate(n: int) -> bool: return True -def compute_truncated_primes(count: int = 11) -> List[int]: +def compute_truncated_primes(count: int = 11) -> list[int]: """ Returns the list of truncated primes >>> compute_truncated_primes(11) diff --git a/project_euler/problem_39/sol1.py b/project_euler/problem_39/sol1.py index b0a5d5188..79fa309f0 100644 --- a/project_euler/problem_39/sol1.py +++ b/project_euler/problem_39/sol1.py @@ -6,11 +6,12 @@ If p is the perimeter of a right angle triangle with integral length sides, For which value of p ≤ 1000, is the number of solutions maximised? """ +from __future__ import annotations + from collections import Counter -from typing import Dict -def pythagorean_triple(max_perimeter: int) -> Dict: +def pythagorean_triple(max_perimeter: int) -> dict: """ Returns a dictionary with keys as the perimeter of a right angled triangle and value as the number of corresponding triplets. diff --git a/project_euler/problem_41/sol1.py b/project_euler/problem_41/sol1.py index 4ed09ccb8..b4c0d842a 100644 --- a/project_euler/problem_41/sol1.py +++ b/project_euler/problem_41/sol1.py @@ -1,6 +1,7 @@ +from __future__ import annotations + from itertools import permutations from math import sqrt -from typing import List """ We shall say that an n-digit number is pandigital if it makes use of all the digits @@ -34,7 +35,7 @@ def is_prime(n: int) -> bool: return True -def compute_pandigital_primes(n: int) -> List[int]: +def compute_pandigital_primes(n: int) -> list[int]: """ Returns a list of all n-digit pandigital primes. >>> compute_pandigital_primes(2) diff --git a/project_euler/problem_46/sol1.py b/project_euler/problem_46/sol1.py index 761e9b8cc..e94e9247d 100644 --- a/project_euler/problem_46/sol1.py +++ b/project_euler/problem_46/sol1.py @@ -15,7 +15,7 @@ What is the smallest odd composite that cannot be written as the sum of a prime and twice a square? """ -from typing import List +from __future__ import annotations seive = [True] * 100001 i = 2 @@ -43,7 +43,7 @@ def is_prime(n: int) -> bool: odd_composites = [num for num in range(3, len(seive), 2) if not is_prime(num)] -def compute_nums(n: int) -> List[int]: +def compute_nums(n: int) -> list[int]: """ Returns a list of first n odd composite numbers which do not follow the conjecture. diff --git a/project_euler/problem_54/sol1.py b/project_euler/problem_54/sol1.py index 3275fe6cd..d36d3702d 100644 --- a/project_euler/problem_54/sol1.py +++ b/project_euler/problem_54/sol1.py @@ -40,7 +40,7 @@ Similar problem on codewars: https://www.codewars.com/kata/ranking-poker-hands https://www.codewars.com/kata/sortable-poker-hands """ -from typing import List, Set, Tuple +from __future__ import annotations class PokerHand(object): @@ -310,7 +310,7 @@ class PokerHand(object): self._second_pair = second return kind - def _internal_state(self) -> Tuple[List[int], Set[str]]: + def _internal_state(self) -> tuple[list[int], set[str]]: # Internal representation of hand as a list of card values and # a set of card suit trans: dict = {"T": "10", "J": "11", "Q": "12", "K": "13", "A": "14"} diff --git a/scheduling/first_come_first_served.py b/scheduling/first_come_first_served.py index b51fc9fe0..c5f61720f 100644 --- a/scheduling/first_come_first_served.py +++ b/scheduling/first_come_first_served.py @@ -2,10 +2,10 @@ # In this Algorithm we just care about the order that the processes arrived # without carring about their duration time # https://en.wikipedia.org/wiki/Scheduling_(computing)#First_come,_first_served -from typing import List +from __future__ import annotations -def calculate_waiting_times(duration_times: List[int]) -> List[int]: +def calculate_waiting_times(duration_times: list[int]) -> list[int]: """ This function calculates the waiting time of some processes that have a specified duration time. @@ -24,8 +24,8 @@ def calculate_waiting_times(duration_times: List[int]) -> List[int]: def calculate_turnaround_times( - duration_times: List[int], waiting_times: List[int] -) -> List[int]: + duration_times: list[int], waiting_times: list[int] +) -> list[int]: """ This function calculates the turnaround time of some processes. Return: The time difference between the completion time and the @@ -44,7 +44,7 @@ def calculate_turnaround_times( ] -def calculate_average_turnaround_time(turnaround_times: List[int]) -> float: +def calculate_average_turnaround_time(turnaround_times: list[int]) -> float: """ This function calculates the average of the turnaround times Return: The average of the turnaround times. @@ -58,7 +58,7 @@ def calculate_average_turnaround_time(turnaround_times: List[int]) -> float: return sum(turnaround_times) / len(turnaround_times) -def calculate_average_waiting_time(waiting_times: List[int]) -> float: +def calculate_average_waiting_time(waiting_times: list[int]) -> float: """ This function calculates the average of the waiting times Return: The average of the waiting times. diff --git a/scheduling/round_robin.py b/scheduling/round_robin.py index 4a79301c1..e8d54dd9a 100755 --- a/scheduling/round_robin.py +++ b/scheduling/round_robin.py @@ -3,11 +3,12 @@ Round Robin is a scheduling algorithm. In Round Robin each process is assigned a fixed time slot in a cyclic way. https://en.wikipedia.org/wiki/Round-robin_scheduling """ +from __future__ import annotations + from statistics import mean -from typing import List -def calculate_waiting_times(burst_times: List[int]) -> List[int]: +def calculate_waiting_times(burst_times: list[int]) -> list[int]: """ Calculate the waiting times of a list of processes that have a specified duration. @@ -40,8 +41,8 @@ def calculate_waiting_times(burst_times: List[int]) -> List[int]: def calculate_turn_around_times( - burst_times: List[int], waiting_times: List[int] -) -> List[int]: + burst_times: list[int], waiting_times: list[int] +) -> list[int]: """ >>> calculate_turn_around_times([1, 2, 3, 4], [0, 1, 3]) [1, 3, 6] diff --git a/scheduling/shortest_job_first.py b/scheduling/shortest_job_first.py index ecb6e01fd..f9e2ad975 100644 --- a/scheduling/shortest_job_first.py +++ b/scheduling/shortest_job_first.py @@ -3,14 +3,14 @@ Shortest job remaining first Please note arrival time and burst Please use spaces to separate times entered. """ -from typing import List +from __future__ import annotations import pandas as pd def calculate_waitingtime( - arrival_time: List[int], burst_time: List[int], no_of_processes: int -) -> List[int]: + arrival_time: list[int], burst_time: list[int], no_of_processes: int +) -> list[int]: """ Calculate the waiting time of each processes Return: list of waiting times. @@ -72,8 +72,8 @@ def calculate_waitingtime( def calculate_turnaroundtime( - burst_time: List[int], no_of_processes: int, waiting_time: List[int] -) -> List[int]: + burst_time: list[int], no_of_processes: int, waiting_time: list[int] +) -> list[int]: """ Calculate the turn around time of each Processes Return: list of turn around times. @@ -91,7 +91,7 @@ def calculate_turnaroundtime( def calculate_average_times( - waiting_time: List[int], turn_around_time: List[int], no_of_processes: int + waiting_time: list[int], turn_around_time: list[int], no_of_processes: int ): """ This function calculates the average of the waiting & turnaround times diff --git a/searches/double_linear_search.py b/searches/double_linear_search.py index 6056f00fc..d9dad3c68 100644 --- a/searches/double_linear_search.py +++ b/searches/double_linear_search.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def double_linear_search(array: List[int], search_item: int) -> int: +def double_linear_search(array: list[int], search_item: int) -> int: """ Iterate through the array from both sides to find the index of search_item. diff --git a/searches/simple_binary_search.py b/searches/simple_binary_search.py index b6215312f..8495dda8d 100644 --- a/searches/simple_binary_search.py +++ b/searches/simple_binary_search.py @@ -7,10 +7,10 @@ python3 -m doctest -v simple_binary_search.py For manual testing run: python3 simple_binary_search.py """ -from typing import List +from __future__ import annotations -def binary_search(a_list: List[int], item: int) -> bool: +def binary_search(a_list: list[int], item: int) -> bool: """ >>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42] >>> print(binary_search(test_list, 3)) diff --git a/sorts/iterative_merge_sort.py b/sorts/iterative_merge_sort.py index e6e151339..5ee0badab 100644 --- a/sorts/iterative_merge_sort.py +++ b/sorts/iterative_merge_sort.py @@ -9,10 +9,10 @@ For manual testing run: python3 iterative_merge_sort.py """ -from typing import List +from __future__ import annotations -def merge(input_list: List, low: int, mid: int, high: int) -> List: +def merge(input_list: list, low: int, mid: int, high: int) -> list: """ sorting left-half and right-half individually then merging them into result @@ -26,7 +26,7 @@ def merge(input_list: List, low: int, mid: int, high: int) -> List: # iteration over the unsorted list -def iter_merge_sort(input_list: List) -> List: +def iter_merge_sort(input_list: list) -> list: """ Return a sorted copy of the input list diff --git a/sorts/merge_insertion_sort.py b/sorts/merge_insertion_sort.py index 339851699..fb71d84a3 100644 --- a/sorts/merge_insertion_sort.py +++ b/sorts/merge_insertion_sort.py @@ -11,10 +11,10 @@ For manual testing run: python3 merge_insertion_sort.py """ -from typing import List +from __future__ import annotations -def merge_insertion_sort(collection: List[int]) -> List[int]: +def merge_insertion_sort(collection: list[int]) -> list[int]: """Pure implementation of merge-insertion sort algorithm in Python :param collection: some mutable ordered collection with heterogeneous diff --git a/sorts/radix_sort.py b/sorts/radix_sort.py index 0ddf996cf..7942462ea 100644 --- a/sorts/radix_sort.py +++ b/sorts/radix_sort.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def radix_sort(list_of_ints: List[int]) -> List[int]: +def radix_sort(list_of_ints: list[int]) -> list[int]: """ radix_sort(range(15)) == sorted(range(15)) True diff --git a/sorts/recursive_insertion_sort.py b/sorts/recursive_insertion_sort.py index 5b14c2a6c..66dd08157 100644 --- a/sorts/recursive_insertion_sort.py +++ b/sorts/recursive_insertion_sort.py @@ -2,10 +2,10 @@ A recursive implementation of the insertion sort algorithm """ -from typing import List +from __future__ import annotations -def rec_insertion_sort(collection: List, n: int): +def rec_insertion_sort(collection: list, n: int): """ Given a collection of numbers and its length, sorts the collections in ascending order @@ -36,7 +36,7 @@ def rec_insertion_sort(collection: List, n: int): rec_insertion_sort(collection, n - 1) -def insert_next(collection: List, index: int): +def insert_next(collection: list, index: int): """ Inserts the '(index-1)th' element into place diff --git a/traversals/binary_tree_traversals.py b/traversals/binary_tree_traversals.py index 50cdd5af7..cb471ba55 100644 --- a/traversals/binary_tree_traversals.py +++ b/traversals/binary_tree_traversals.py @@ -3,8 +3,9 @@ """ This is pure Python implementation of tree traversal algorithms """ +from __future__ import annotations + import queue -from typing import List class TreeNode: diff --git a/web_programming/fetch_jobs.py b/web_programming/fetch_jobs.py index 888f41294..bb2171e1f 100644 --- a/web_programming/fetch_jobs.py +++ b/web_programming/fetch_jobs.py @@ -1,7 +1,9 @@ """ Scraping jobs given job title and location from indeed website """ -from typing import Generator, Tuple +from __future__ import annotations + +from typing import Generator import requests from bs4 import BeautifulSoup @@ -9,7 +11,7 @@ from bs4 import BeautifulSoup url = "https://www.indeed.co.in/jobs?q=mobile+app+development&l=" -def fetch_jobs(location: str = "mumbai") -> Generator[Tuple[str, str], None, None]: +def fetch_jobs(location: str = "mumbai") -> Generator[tuple[str, str], None, None]: soup = BeautifulSoup(requests.get(url + location).content, "html.parser") # This attribute finds out all the specifics listed in a job for job in soup.find_all("div", attrs={"data-tn-component": "organicJob"}): diff --git a/web_programming/get_imdb_top_250_movies_csv.py b/web_programming/get_imdb_top_250_movies_csv.py index 811c21fb0..e54b076eb 100644 --- a/web_programming/get_imdb_top_250_movies_csv.py +++ b/web_programming/get_imdb_top_250_movies_csv.py @@ -1,11 +1,12 @@ +from __future__ import annotations + import csv -from typing import Dict import requests from bs4 import BeautifulSoup -def get_imdb_top_250_movies(url: str = "") -> Dict[str, float]: +def get_imdb_top_250_movies(url: str = "") -> dict[str, float]: url = url or "https://www.imdb.com/chart/top/?ref_=nv_mv_250" soup = BeautifulSoup(requests.get(url).text, "html.parser") titles = soup.find_all("td", attrs="titleColumn")