From cecf43d6481173e831af829da77911e1a3868a6c Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 7 Sep 2021 13:37:03 +0200 Subject: [PATCH] Pyupgrade to Python 3.9 (#4718) * Pyupgrade to Python 3.9 * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 3 ++- arithmetic_analysis/in_static_equilibrium.py | 4 +-- arithmetic_analysis/lu_decomposition.py | 4 +-- .../newton_forward_interpolation.py | 4 +-- arithmetic_analysis/newton_raphson.py | 5 ++-- backtracking/all_combinations.py | 12 ++++----- backtracking/all_permutations.py | 14 +++++----- backtracking/all_subsequences.py | 10 ++++--- backtracking/coloring.py | 7 +++-- backtracking/hamiltonian_cycle.py | 7 +++-- backtracking/knight_tour.py | 10 +++---- backtracking/minimax.py | 5 ++-- backtracking/n_queens.py | 8 +++--- backtracking/n_queens_math.py | 12 ++++----- backtracking/rat_in_maze.py | 6 ++--- backtracking/sudoku.py | 8 +++--- backtracking/sum_of_subsets.py | 14 +++++----- blockchain/chinese_remainder_theorem.py | 4 +-- blockchain/diophantine_equation.py | 6 ++--- blockchain/modular_division.py | 6 ++--- boolean_algebra/quine_mc_cluskey.py | 12 ++++----- cellular_automata/conways_game_of_life.py | 5 +--- ciphers/caesar_cipher.py | 9 ++++--- ciphers/decrypt_caesar_with_chi_squared.py | 7 +++-- ciphers/diffie.py | 4 +-- ciphers/shuffled_shift_cipher.py | 5 ++-- compression/huffman.py | 2 +- conversions/molecular_chemistry.py | 2 +- conversions/prefix_conversions.py | 11 ++++---- data_structures/binary_tree/avl_tree.py | 25 +++++++++--------- .../binary_tree/basic_binary_tree.py | 10 +++---- .../binary_search_tree_recursive.py | 24 ++++++++--------- .../binary_tree/binary_tree_traversals.py | 7 ++--- .../binary_tree/lazy_segment_tree.py | 5 ++-- .../binary_tree/merge_two_binary_trees.py | 10 +++---- data_structures/binary_tree/red_black_tree.py | 26 ++++++++++--------- data_structures/binary_tree/treap.py | 21 +++++++-------- data_structures/binary_tree/wavelet_tree.py | 7 +++-- data_structures/hashing/hash_table.py | 2 +- .../hashing/hash_table_with_linked_list.py | 2 +- data_structures/heap/heap.py | 12 +++++---- data_structures/heap/randomized_heap.py | 16 ++++++------ data_structures/heap/skew_heap.py | 14 +++++----- .../linked_list/merge_two_lists.py | 5 ++-- data_structures/linked_list/print_reverse.py | 4 +-- data_structures/linked_list/skip_list.py | 7 +++-- .../stacks/evaluate_postfix_notations.py | 7 ++--- data_structures/stacks/linked_stack.py | 6 +++-- data_structures/stacks/stack.py | 4 +-- divide_and_conquer/convex_hull.py | 19 +++++++------- divide_and_conquer/kth_order_statistic.py | 5 ++-- divide_and_conquer/mergesort.py | 6 ++--- divide_and_conquer/peak.py | 4 +-- electronics/electric_power.py | 5 ++-- electronics/ohms_law.py | 4 +-- graphs/basic_graphs.py | 8 +++--- graphs/bellman_ford.py | 8 +++--- graphs/bfs_zero_one_shortest_path.py | 14 +++++----- graphs/bidirectional_a_star.py | 7 ++--- graphs/bidirectional_breadth_first_search.py | 10 +++---- graphs/breadth_first_search.py | 7 +++-- graphs/breadth_first_search_shortest_path.py | 4 +-- graphs/depth_first_search.py | 5 +--- graphs/greedy_best_first.py | 8 +++--- graphs/minimum_spanning_tree_kruskal.py | 2 +- graphs/minimum_spanning_tree_prims2.py | 7 ++--- graphs/page_rank.py | 2 +- graphs/scc_kosaraju.py | 14 +++++----- hashes/luhn.py | 6 ++--- knapsack/knapsack.py | 5 ++-- linear_algebra/src/lib.py | 26 +++++++++---------- machine_learning/similarity_search.py | 5 ++-- maths/area_under_curve.py | 9 ++++--- maths/average_mean.py | 4 +-- maths/average_median.py | 4 +-- maths/entropy.py | 6 ++--- maths/euclidean_distance.py | 2 ++ maths/extended_euclidean_algorithm.py | 4 +-- maths/hardy_ramanujanalgo.py | 2 +- maths/line_length.py | 10 ++++--- maths/max_sum_sliding_window.py | 4 +-- maths/median_of_two_arrays.py | 4 +-- maths/numerical_integration.py | 9 ++++--- maths/sieve_of_eratosthenes.py | 5 ++-- maths/volume.py | 5 ++-- matrix/searching_in_sorted_matrix.py | 4 +-- other/date_to_weekday.py | 2 +- ...y => davisb_putnamb_logemannb_loveland.py} | 24 ++++++++--------- other/lfu_cache.py | 6 +++-- other/lru_cache.py | 6 +++-- project_euler/problem_001/sol1.py | 2 +- project_euler/problem_001/sol5.py | 2 +- project_euler/problem_006/sol3.py | 2 +- project_euler/problem_008/sol2.py | 5 +--- project_euler/problem_012/sol2.py | 2 +- project_euler/problem_013/sol1.py | 2 +- project_euler/problem_014/sol2.py | 6 ++--- project_euler/problem_020/sol2.py | 2 +- project_euler/problem_021/sol1.py | 8 +++--- project_euler/problem_033/sol1.py | 5 ++-- project_euler/problem_036/sol1.py | 5 ++-- project_euler/problem_038/sol1.py | 5 ++-- project_euler/problem_049/sol1.py | 2 +- project_euler/problem_050/sol1.py | 4 +-- project_euler/problem_051/sol1.py | 6 ++--- project_euler/problem_054/sol1.py | 4 +-- project_euler/problem_056/sol1.py | 8 +++--- project_euler/problem_059/sol1.py | 23 ++++++++-------- project_euler/problem_070/sol1.py | 4 +-- project_euler/problem_074/sol1.py | 2 +- project_euler/problem_077/sol1.py | 8 +++--- project_euler/problem_080/sol1.py | 2 +- project_euler/problem_081/sol1.py | 2 +- project_euler/problem_085/sol1.py | 5 ++-- project_euler/problem_089/sol1.py | 2 +- project_euler/problem_101/sol1.py | 18 ++++++------- project_euler/problem_102/sol1.py | 14 +++++----- project_euler/problem_107/sol1.py | 21 ++++++++------- project_euler/problem_119/sol1.py | 2 +- project_euler/problem_123/sol1.py | 5 ++-- project_euler/problem_180/sol1.py | 7 +++-- project_euler/problem_203/sol1.py | 12 ++++----- scheduling/first_come_first_served.py | 12 ++++----- scheduling/round_robin.py | 9 ++++--- scheduling/shortest_job_first.py | 12 ++++----- searches/binary_search.py | 19 +++++++------- searches/fibonacci_search.py | 2 +- searches/ternary_search.py | 8 +++--- sorts/bitonic_sort.py | 8 +++--- sorts/bucket_sort.py | 4 +-- sorts/msd_radix_sort.py | 10 +++---- sorts/patience_sort.py | 7 ++--- sorts/pigeon_sort.py | 4 +-- sorts/quick_sort.py | 6 ++--- sorts/radix_sort.py | 6 ++--- sorts/recursive_insertion_sort.py | 5 +--- sorts/slowsort.py | 7 ++--- strings/aho_corasick.py | 7 ++--- strings/boyer_moore_search.py | 4 +-- strings/knuth_morris_pratt.py | 4 +-- web_programming/emails_from_url.py | 5 ++-- web_programming/fetch_github_info.py | 6 +++-- 142 files changed, 523 insertions(+), 530 deletions(-) rename other/{davis–putnam–logemann–loveland.py => davisb_putnamb_logemannb_loveland.py} (94%) diff --git a/DIRECTORY.md b/DIRECTORY.md index 41485f6f0..0c00d5ca7 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -545,7 +545,7 @@ ## Other * [Activity Selection](https://github.com/TheAlgorithms/Python/blob/master/other/activity_selection.py) * [Date To Weekday](https://github.com/TheAlgorithms/Python/blob/master/other/date_to_weekday.py) - * [Davis–Putnam–Logemann–Loveland](https://github.com/TheAlgorithms/Python/blob/master/other/davis–putnam–logemann–loveland.py) + * [Davisb Putnamb Logemannb Loveland](https://github.com/TheAlgorithms/Python/blob/master/other/davisb_putnamb_logemannb_loveland.py) * [Dijkstra Bankers Algorithm](https://github.com/TheAlgorithms/Python/blob/master/other/dijkstra_bankers_algorithm.py) * [Doomsday](https://github.com/TheAlgorithms/Python/blob/master/other/doomsday.py) * [Fischer Yates Shuffle](https://github.com/TheAlgorithms/Python/blob/master/other/fischer_yates_shuffle.py) @@ -860,6 +860,7 @@ * [Counting Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/counting_sort.py) * [Cycle Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/cycle_sort.py) * [Double Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/double_sort.py) + * [Dutch National Flag Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/dutch_national_flag_sort.py) * [Exchange Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/exchange_sort.py) * [External Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/external_sort.py) * [Gnome Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/gnome_sort.py) diff --git a/arithmetic_analysis/in_static_equilibrium.py b/arithmetic_analysis/in_static_equilibrium.py index 7b5006a1a..6e8d1d043 100644 --- a/arithmetic_analysis/in_static_equilibrium.py +++ b/arithmetic_analysis/in_static_equilibrium.py @@ -1,14 +1,14 @@ """ Checks if a system of forces is in static equilibrium. """ -from typing import List +from __future__ import annotations from numpy import array, cos, cross, ndarray, radians, sin 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/arithmetic_analysis/lu_decomposition.py b/arithmetic_analysis/lu_decomposition.py index 5bb631758..b488b1bb3 100644 --- a/arithmetic_analysis/lu_decomposition.py +++ b/arithmetic_analysis/lu_decomposition.py @@ -3,12 +3,12 @@ Reference: - https://en.wikipedia.org/wiki/LU_decomposition """ -from typing import Tuple +from __future__ import annotations import numpy as np -def lower_upper_decomposition(table: np.ndarray) -> Tuple[np.ndarray, np.ndarray]: +def lower_upper_decomposition(table: np.ndarray) -> tuple[np.ndarray, np.ndarray]: """Lower-Upper (LU) Decomposition Example: diff --git a/arithmetic_analysis/newton_forward_interpolation.py b/arithmetic_analysis/newton_forward_interpolation.py index 66cde4b73..490e0687f 100644 --- a/arithmetic_analysis/newton_forward_interpolation.py +++ b/arithmetic_analysis/newton_forward_interpolation.py @@ -1,7 +1,7 @@ # https://www.geeksforgeeks.org/newton-forward-backward-interpolation/ +from __future__ import annotations import math -from typing import List # for calculating u value @@ -22,7 +22,7 @@ def ucal(u: float, p: int) -> float: def main() -> None: n = int(input("enter the numbers of values: ")) - y: List[List[float]] = [] + y: list[list[float]] = [] for i in range(n): y.append([]) for i in range(n): diff --git a/arithmetic_analysis/newton_raphson.py b/arithmetic_analysis/newton_raphson.py index 146bb0aa5..1a8205386 100644 --- a/arithmetic_analysis/newton_raphson.py +++ b/arithmetic_analysis/newton_raphson.py @@ -2,15 +2,16 @@ # Author: Syed Haseeb Shah (github.com/QuantumNovice) # The Newton-Raphson method (also known as Newton's method) is a way to # quickly find a good approximation for the root of a real-valued function +from __future__ import annotations + from decimal import Decimal from math import * # noqa: F401, F403 -from typing import Union from sympy import diff def newton_raphson( - func: str, a: Union[float, Decimal], precision: float = 10 ** -10 + func: str, a: float | Decimal, precision: float = 10 ** -10 ) -> float: """Finds root from the point 'a' onwards by Newton-Raphson method >>> newton_raphson("sin(x)", 2) diff --git a/backtracking/all_combinations.py b/backtracking/all_combinations.py index 76462837c..bde60f032 100644 --- a/backtracking/all_combinations.py +++ b/backtracking/all_combinations.py @@ -3,16 +3,16 @@ numbers out of 1 ... n. We use backtracking to solve this problem. Time complexity: O(C(n,k)) which is O(n choose k) = O((n!/(k! * (n - k)!))) """ -from typing import List +from __future__ import annotations -def generate_all_combinations(n: int, k: int) -> List[List[int]]: +def generate_all_combinations(n: int, k: int) -> list[list[int]]: """ >>> generate_all_combinations(n=4, k=2) [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]] """ - result: List[List[int]] = [] + result: list[list[int]] = [] create_all_state(1, n, k, [], result) return result @@ -21,8 +21,8 @@ def create_all_state( increment: int, total_number: int, level: int, - current_list: List[int], - total_list: List[List[int]], + current_list: list[int], + total_list: list[list[int]], ) -> None: if level == 0: total_list.append(current_list[:]) @@ -34,7 +34,7 @@ def create_all_state( current_list.pop() -def print_all_state(total_list: List[List[int]]) -> None: +def print_all_state(total_list: list[list[int]]) -> None: for i in total_list: print(*i) diff --git a/backtracking/all_permutations.py b/backtracking/all_permutations.py index a0032c5ca..ff8a53e0d 100644 --- a/backtracking/all_permutations.py +++ b/backtracking/all_permutations.py @@ -5,18 +5,18 @@ Time complexity: O(n! * n), where n denotes the length of the given sequence. """ -from typing import List, Union +from __future__ import annotations -def generate_all_permutations(sequence: List[Union[int, str]]) -> None: +def generate_all_permutations(sequence: list[int | str]) -> None: create_state_space_tree(sequence, [], 0, [0 for i in range(len(sequence))]) def create_state_space_tree( - sequence: List[Union[int, str]], - current_sequence: List[Union[int, str]], + sequence: list[int | str], + current_sequence: list[int | str], index: int, - index_used: List[int], + index_used: list[int], ) -> None: """ Creates a state space tree to iterate through each branch using DFS. @@ -44,8 +44,8 @@ print("Enter the elements") sequence = list(map(int, input().split())) """ -sequence: List[Union[int, str]] = [3, 1, 2, 4] +sequence: list[int | str] = [3, 1, 2, 4] generate_all_permutations(sequence) -sequence_2: List[Union[int, str]] = ["A", "B", "C"] +sequence_2: list[int | str] = ["A", "B", "C"] generate_all_permutations(sequence_2) diff --git a/backtracking/all_subsequences.py b/backtracking/all_subsequences.py index 99db4ea46..c465fc542 100644 --- a/backtracking/all_subsequences.py +++ b/backtracking/all_subsequences.py @@ -5,15 +5,17 @@ of the given sequence. We use backtracking to solve this problem. Time complexity: O(2^n), where n denotes the length of the given sequence. """ -from typing import Any, List +from __future__ import annotations + +from typing import Any -def generate_all_subsequences(sequence: List[Any]) -> None: +def generate_all_subsequences(sequence: list[Any]) -> None: create_state_space_tree(sequence, [], 0) def create_state_space_tree( - sequence: List[Any], current_subsequence: List[Any], index: int + sequence: list[Any], current_subsequence: list[Any], index: int ) -> None: """ Creates a state space tree to iterate through each branch using DFS. @@ -32,7 +34,7 @@ def create_state_space_tree( if __name__ == "__main__": - seq: List[Any] = [3, 1, 2, 4] + seq: list[Any] = [3, 1, 2, 4] generate_all_subsequences(seq) seq.clear() diff --git a/backtracking/coloring.py b/backtracking/coloring.py index 3956b21a9..8bda4b587 100644 --- a/backtracking/coloring.py +++ b/backtracking/coloring.py @@ -5,11 +5,10 @@ Wikipedia: https://en.wikipedia.org/wiki/Graph_coloring """ -from typing import List 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 +34,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 +85,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..19751b347 100644 --- a/backtracking/hamiltonian_cycle.py +++ b/backtracking/hamiltonian_cycle.py @@ -6,11 +6,10 @@ Wikipedia: https://en.wikipedia.org/wiki/Hamiltonian_path """ -from typing import List 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 +46,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 +107,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 8e6613e07..6e9b31bd1 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, int], n: int) -> List[Tuple[int, int]]: +def get_valid_pos(position: tuple[int, int], n: int) -> list[tuple[int, 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, int], n: int) -> List[Tuple[int, 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. @@ -47,7 +47,7 @@ def is_complete(board: List[List[int]]) -> bool: def open_knight_tour_helper( - board: List[List[int]], pos: Tuple[int, int], curr: int + board: list[list[int]], pos: tuple[int, int], curr: int ) -> bool: """ Helper function to solve knight tour problem. @@ -68,7 +68,7 @@ def open_knight_tour_helper( 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/minimax.py b/backtracking/minimax.py index dda29b47d..6e310131e 100644 --- a/backtracking/minimax.py +++ b/backtracking/minimax.py @@ -7,12 +7,13 @@ if move is of maximizer return true else false leaves of game tree is stored in scores[] height is maximum height of Game tree """ +from __future__ import annotations + import math -from typing import List def minimax( - depth: int, node_index: int, is_max: bool, scores: List[int], height: float + depth: int, node_index: int, is_max: bool, scores: list[int], height: float ) -> int: """ >>> import math diff --git a/backtracking/n_queens.py b/backtracking/n_queens.py index 29b8d819a..b8ace5978 100644 --- a/backtracking/n_queens.py +++ b/backtracking/n_queens.py @@ -7,12 +7,12 @@ diagonal lines. """ -from typing import List +from __future__ import annotations solution = [] -def isSafe(board: List[List[int]], row: int, column: int) -> bool: +def isSafe(board: list[list[int]], row: int, column: int) -> bool: """ This function returns a boolean value True if it is safe to place a queen there considering the current state of the board. @@ -40,7 +40,7 @@ def isSafe(board: List[List[int]], row: int, column: int) -> bool: return True -def solve(board: List[List[int]], row: int) -> bool: +def solve(board: list[list[int]], row: int) -> bool: """ It creates a state space tree and calls the safe function until it receives a False Boolean and terminates that branch and backtracks to the next @@ -70,7 +70,7 @@ def solve(board: List[List[int]], row: int) -> bool: return False -def printboard(board: List[List[int]]) -> None: +def printboard(board: list[list[int]]) -> None: """ Prints the boards that have a successful combination. """ diff --git a/backtracking/n_queens_math.py b/backtracking/n_queens_math.py index a8651c5c3..c12aa6c33 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: """ @@ -139,7 +139,7 @@ def depth_first_search( def n_queens_solution(n: int) -> None: - boards: List[List[str]] = [] + boards: list[list[str]] = [] depth_first_search([], [], [], boards, n) # Print all the boards diff --git a/backtracking/rat_in_maze.py b/backtracking/rat_in_maze.py index cd2a8f41d..2860880db 100644 --- a/backtracking/rat_in_maze.py +++ b/backtracking/rat_in_maze.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def solve_maze(maze: List[List[int]]) -> bool: +def solve_maze(maze: list[list[int]]) -> bool: """ This method solves the "rat in maze" problem. In this problem we have some n by n matrix, a start point and an end point. @@ -70,7 +70,7 @@ def solve_maze(maze: List[List[int]]) -> bool: return solved -def run_maze(maze: List[List[int]], i: int, j: int, solutions: List[List[int]]) -> bool: +def run_maze(maze: list[list[int]], i: int, j: int, solutions: list[list[int]]) -> bool: """ This method is recursive starting from (i, j) and going in one of four directions: up, down, left, right. diff --git a/backtracking/sudoku.py b/backtracking/sudoku.py index 593fa52d6..698dedcc2 100644 --- a/backtracking/sudoku.py +++ b/backtracking/sudoku.py @@ -9,9 +9,9 @@ function on the next column to see if it returns True. if yes, we have solved the puzzle. else, we backtrack and place another number in that cell and repeat this process. """ -from typing import List, Optional, Tuple +from __future__ import annotations -Matrix = List[List[int]] +Matrix = list[list[int]] # assigning initial values to the grid initial_grid: Matrix = [ @@ -59,7 +59,7 @@ def is_safe(grid: Matrix, row: int, column: int, n: int) -> bool: return True -def find_empty_location(grid: Matrix) -> Optional[Tuple[int, int]]: +def find_empty_location(grid: Matrix) -> tuple[int, int] | None: """ This function finds an empty location so that we can assign a number for that particular row and column. @@ -71,7 +71,7 @@ def find_empty_location(grid: Matrix) -> Optional[Tuple[int, int]]: return None -def sudoku(grid: Matrix) -> Optional[Matrix]: +def sudoku(grid: Matrix) -> Matrix | None: """ Takes a partially filled-in grid and attempts to assign values to all unassigned locations in such a way to meet the requirements diff --git a/backtracking/sum_of_subsets.py b/backtracking/sum_of_subsets.py index f695b8f7a..8348544c0 100644 --- a/backtracking/sum_of_subsets.py +++ b/backtracking/sum_of_subsets.py @@ -6,12 +6,12 @@ Summation of the chosen numbers must be equal to given number M and one number can be used only once. """ -from typing import List +from __future__ import annotations -def generate_sum_of_subsets_soln(nums: List[int], max_sum: int) -> List[List[int]]: - result: List[List[int]] = [] - path: List[int] = [] +def generate_sum_of_subsets_soln(nums: list[int], max_sum: int) -> list[list[int]]: + result: list[list[int]] = [] + path: list[int] = [] num_index = 0 remaining_nums_sum = sum(nums) create_state_space_tree(nums, max_sum, num_index, path, result, remaining_nums_sum) @@ -19,11 +19,11 @@ def generate_sum_of_subsets_soln(nums: List[int], max_sum: int) -> List[List[int def create_state_space_tree( - nums: List[int], + nums: list[int], max_sum: int, num_index: int, - path: List[int], - result: List[List[int]], + path: list[int], + result: list[list[int]], remaining_nums_sum: int, ) -> None: """ diff --git a/blockchain/chinese_remainder_theorem.py b/blockchain/chinese_remainder_theorem.py index b50147ac1..54d861dd9 100644 --- a/blockchain/chinese_remainder_theorem.py +++ b/blockchain/chinese_remainder_theorem.py @@ -11,11 +11,11 @@ Algorithm : 1. Use extended euclid algorithm to find x,y such that a*x + b*y = 1 2. Take n = ra*by + rb*ax """ -from typing import Tuple +from __future__ import annotations # Extended Euclid -def extended_euclid(a: int, b: int) -> Tuple[int, int]: +def extended_euclid(a: int, b: int) -> tuple[int, int]: """ >>> extended_euclid(10, 6) (-1, 2) diff --git a/blockchain/diophantine_equation.py b/blockchain/diophantine_equation.py index 7df674cb1..22b0cad75 100644 --- a/blockchain/diophantine_equation.py +++ b/blockchain/diophantine_equation.py @@ -1,7 +1,7 @@ -from typing import Tuple +from __future__ import annotations -def diophantine(a: int, b: int, c: int) -> Tuple[float, float]: +def diophantine(a: int, b: int, c: int) -> tuple[float, float]: """ Diophantine Equation : Given integers a,b,c ( at least one of a and b != 0), the diophantine equation a*x + b*y = c has a solution (where x and y are integers) @@ -95,7 +95,7 @@ def greatest_common_divisor(a: int, b: int) -> int: return b -def extended_gcd(a: int, b: int) -> Tuple[int, int, int]: +def extended_gcd(a: int, b: int) -> tuple[int, int, int]: """ Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) diff --git a/blockchain/modular_division.py b/blockchain/modular_division.py index 4f7f50a92..a9d0f65c5 100644 --- a/blockchain/modular_division.py +++ b/blockchain/modular_division.py @@ -1,4 +1,4 @@ -from typing import Tuple +from __future__ import annotations def modular_division(a: int, b: int, n: int) -> int: @@ -73,7 +73,7 @@ def modular_division2(a: int, b: int, n: int) -> int: return x -def extended_gcd(a: int, b: int) -> Tuple[int, int, int]: +def extended_gcd(a: int, b: int) -> tuple[int, int, int]: """ Extended Euclid's Algorithm : If d divides a and b and d = a*x + b*y for integers x and y, then d = gcd(a,b) @@ -101,7 +101,7 @@ def extended_gcd(a: int, b: int) -> Tuple[int, int, int]: return (d, x, y) -def extended_euclid(a: int, b: int) -> Tuple[int, int]: +def extended_euclid(a: int, b: int) -> tuple[int, int]: """ Extended Euclid >>> extended_euclid(10, 6) diff --git a/boolean_algebra/quine_mc_cluskey.py b/boolean_algebra/quine_mc_cluskey.py index 70cdf25a7..9cc99b1ee 100644 --- a/boolean_algebra/quine_mc_cluskey.py +++ b/boolean_algebra/quine_mc_cluskey.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations def compare_string(string1: str, string2: str) -> str: @@ -22,7 +22,7 @@ def compare_string(string1: str, string2: str) -> str: return "".join(l1) -def check(binary: List[str]) -> List[str]: +def check(binary: list[str]) -> list[str]: """ >>> check(['0.00.01.5']) ['0.00.01.5'] @@ -46,7 +46,7 @@ def check(binary: List[str]) -> List[str]: binary = list(set(temp)) -def decimal_to_binary(no_of_variable: int, minterms: List[float]) -> List[str]: +def decimal_to_binary(no_of_variable: int, minterms: list[float]) -> list[str]: """ >>> decimal_to_binary(3,[1.5]) ['0.00.01.5'] @@ -82,7 +82,7 @@ def is_for_table(string1: str, string2: str, count: int) -> bool: return False -def selection(chart: List[List[int]], prime_implicants: List[str]) -> List[str]: +def selection(chart: list[list[int]], prime_implicants: list[str]) -> list[str]: """ >>> selection([[1]],['0.00.01.5']) ['0.00.01.5'] @@ -130,8 +130,8 @@ def selection(chart: List[List[int]], prime_implicants: List[str]) -> List[str]: def prime_implicant_chart( - prime_implicants: List[str], binary: List[str] -) -> List[List[int]]: + prime_implicants: list[str], binary: list[str] +) -> list[list[int]]: """ >>> prime_implicant_chart(['0.00.01.5'],['0.00.01.5']) [[1]] diff --git a/cellular_automata/conways_game_of_life.py b/cellular_automata/conways_game_of_life.py index 321baa3a3..079fb4d04 100644 --- a/cellular_automata/conways_game_of_life.py +++ b/cellular_automata/conways_game_of_life.py @@ -2,11 +2,8 @@ Conway's Game of Life implemented in Python. https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life """ - from __future__ import annotations -from typing import List - from PIL import Image # Define glider example @@ -25,7 +22,7 @@ GLIDER = [ BLINKER = [[0, 1, 0], [0, 1, 0], [0, 1, 0]] -def new_generation(cells: List[List[int]]) -> List[List[int]]: +def new_generation(cells: list[list[int]]) -> list[list[int]]: """ Generates the next generation for a given state of Conway's Game of Life. >>> new_generation(BLINKER) diff --git a/ciphers/caesar_cipher.py b/ciphers/caesar_cipher.py index 4b2f76c7d..8cd9fab58 100644 --- a/ciphers/caesar_cipher.py +++ b/ciphers/caesar_cipher.py @@ -1,8 +1,9 @@ +from __future__ import annotations + from string import ascii_letters -from typing import Dict, Optional -def encrypt(input_string: str, key: int, alphabet: Optional[str] = None) -> str: +def encrypt(input_string: str, key: int, alphabet: str | None = None) -> str: """ encrypt ======= @@ -80,7 +81,7 @@ def encrypt(input_string: str, key: int, alphabet: Optional[str] = None) -> str: return result -def decrypt(input_string: str, key: int, alphabet: Optional[str] = None) -> str: +def decrypt(input_string: str, key: int, alphabet: str | None = None) -> str: """ decrypt ======= @@ -145,7 +146,7 @@ def decrypt(input_string: str, key: int, alphabet: Optional[str] = None) -> str: return encrypt(input_string, key, alphabet) -def brute_force(input_string: str, alphabet: Optional[str] = None) -> Dict[int, str]: +def brute_force(input_string: str, alphabet: str | None = None) -> dict[int, str]: """ brute_force =========== diff --git a/ciphers/decrypt_caesar_with_chi_squared.py b/ciphers/decrypt_caesar_with_chi_squared.py index 7e3705b8f..89477914a 100644 --- a/ciphers/decrypt_caesar_with_chi_squared.py +++ b/ciphers/decrypt_caesar_with_chi_squared.py @@ -1,12 +1,11 @@ #!/usr/bin/env python3 - -from typing import Optional +from __future__ import annotations def decrypt_caesar_with_chi_squared( ciphertext: str, - cipher_alphabet: Optional[list[str]] = None, - frequencies_dict: Optional[dict[str, float]] = None, + cipher_alphabet: list[str] | None = None, + frequencies_dict: dict[str, float] | None = None, case_sensetive: bool = False, ) -> tuple[int, float, str]: """ diff --git a/ciphers/diffie.py b/ciphers/diffie.py index a23a8104a..4ff90be00 100644 --- a/ciphers/diffie.py +++ b/ciphers/diffie.py @@ -1,7 +1,7 @@ -from typing import Optional +from __future__ import annotations -def find_primitive(n: int) -> Optional[int]: +def find_primitive(n: int) -> int | None: for r in range(1, n): li = [] for x in range(n - 1): diff --git a/ciphers/shuffled_shift_cipher.py b/ciphers/shuffled_shift_cipher.py index 01d099641..3b84f97f6 100644 --- a/ciphers/shuffled_shift_cipher.py +++ b/ciphers/shuffled_shift_cipher.py @@ -1,6 +1,7 @@ +from __future__ import annotations + import random import string -from typing import Optional class ShuffledShiftCipher: @@ -27,7 +28,7 @@ class ShuffledShiftCipher: cip2 = ShuffledShiftCipher() """ - def __init__(self, passcode: Optional[str] = None) -> None: + def __init__(self, passcode: str | None = None) -> None: """ Initializes a cipher object with a passcode as it's entity Note: No new passcode is generated if user provides a passcode diff --git a/compression/huffman.py b/compression/huffman.py index b6cc4de1e..8f37a53ce 100644 --- a/compression/huffman.py +++ b/compression/huffman.py @@ -30,7 +30,7 @@ def parse_file(file_path): if not c: break chars[c] = chars[c] + 1 if c in chars.keys() else 1 - return sorted([Letter(c, f) for c, f in chars.items()], key=lambda l: l.freq) + return sorted((Letter(c, f) for c, f in chars.items()), key=lambda l: l.freq) def build_tree(letters): diff --git a/conversions/molecular_chemistry.py b/conversions/molecular_chemistry.py index 8c6845996..0024eb5cb 100644 --- a/conversions/molecular_chemistry.py +++ b/conversions/molecular_chemistry.py @@ -20,7 +20,7 @@ def molarity_to_normality(nfactor: int, moles: float, volume: float) -> float: >>> molarity_to_normality(4, 11.4, 5.7) 8 """ - return round((float(moles / volume) * nfactor)) + return round(float(moles / volume) * nfactor) def moles_to_pressure(volume: float, moles: float, temperature: float) -> float: diff --git a/conversions/prefix_conversions.py b/conversions/prefix_conversions.py index 78db4a917..a77556433 100644 --- a/conversions/prefix_conversions.py +++ b/conversions/prefix_conversions.py @@ -1,8 +1,9 @@ """ Convert International System of Units (SI) and Binary prefixes """ +from __future__ import annotations + from enum import Enum -from typing import Union class SI_Unit(Enum): @@ -41,8 +42,8 @@ class Binary_Unit(Enum): def convert_si_prefix( known_amount: float, - known_prefix: Union[str, SI_Unit], - unknown_prefix: Union[str, SI_Unit], + known_prefix: str | SI_Unit, + unknown_prefix: str | SI_Unit, ) -> float: """ Wikipedia reference: https://en.wikipedia.org/wiki/Binary_prefix @@ -70,8 +71,8 @@ def convert_si_prefix( def convert_binary_prefix( known_amount: float, - known_prefix: Union[str, Binary_Unit], - unknown_prefix: Union[str, Binary_Unit], + known_prefix: str | Binary_Unit, + unknown_prefix: str | Binary_Unit, ) -> float: """ Wikipedia reference: https://en.wikipedia.org/wiki/Metric_prefix diff --git a/data_structures/binary_tree/avl_tree.py b/data_structures/binary_tree/avl_tree.py index e0d3e4d43..1ab13777b 100644 --- a/data_structures/binary_tree/avl_tree.py +++ b/data_structures/binary_tree/avl_tree.py @@ -5,15 +5,16 @@ python3 -m doctest -v avl_tree.py For testing run: python avl_tree.py """ +from __future__ import annotations import math import random -from typing import Any, List, Optional +from typing import Any class my_queue: def __init__(self) -> None: - self.data: List[Any] = [] + self.data: list[Any] = [] self.head: int = 0 self.tail: int = 0 @@ -41,17 +42,17 @@ class my_queue: class my_node: def __init__(self, data: Any) -> None: self.data = data - self.left: Optional[my_node] = None - self.right: Optional[my_node] = None + self.left: my_node | None = None + self.right: my_node | None = None self.height: int = 1 def get_data(self) -> Any: return self.data - def get_left(self) -> Optional["my_node"]: + def get_left(self) -> my_node | None: return self.left - def get_right(self) -> Optional["my_node"]: + def get_right(self) -> my_node | None: return self.right def get_height(self) -> int: @@ -61,11 +62,11 @@ class my_node: self.data = data return - def set_left(self, node: Optional["my_node"]) -> None: + def set_left(self, node: my_node | None) -> None: self.left = node return - def set_right(self, node: Optional["my_node"]) -> None: + def set_right(self, node: my_node | None) -> None: self.right = node return @@ -74,7 +75,7 @@ class my_node: return -def get_height(node: Optional["my_node"]) -> int: +def get_height(node: my_node | None) -> int: if node is None: return 0 return node.get_height() @@ -149,7 +150,7 @@ def rl_rotation(node: my_node) -> my_node: return left_rotation(node) -def insert_node(node: Optional["my_node"], data: Any) -> Optional["my_node"]: +def insert_node(node: my_node | None, data: Any) -> my_node | None: if node is None: return my_node(data) if data < node.get_data(): @@ -197,7 +198,7 @@ def get_leftMost(root: my_node) -> Any: return root.get_data() -def del_node(root: my_node, data: Any) -> Optional["my_node"]: +def del_node(root: my_node, data: Any) -> my_node | None: left_child = root.get_left() right_child = root.get_right() if root.get_data() == data: @@ -275,7 +276,7 @@ class AVLtree: """ def __init__(self) -> None: - self.root: Optional[my_node] = None + self.root: my_node | None = None def get_height(self) -> int: return get_height(self.root) diff --git a/data_structures/binary_tree/basic_binary_tree.py b/data_structures/binary_tree/basic_binary_tree.py index 575b157ee..65dccf247 100644 --- a/data_structures/binary_tree/basic_binary_tree.py +++ b/data_structures/binary_tree/basic_binary_tree.py @@ -1,4 +1,4 @@ -from typing import Optional +from __future__ import annotations class Node: @@ -8,11 +8,11 @@ class Node: def __init__(self, data: int) -> None: self.data = data - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None -def display(tree: Optional[Node]) -> None: # In Order traversal of the tree +def display(tree: Node | None) -> None: # In Order traversal of the tree """ >>> root = Node(1) >>> root.left = Node(0) @@ -30,7 +30,7 @@ def display(tree: Optional[Node]) -> None: # In Order traversal of the tree display(tree.right) -def depth_of_tree(tree: Optional[Node]) -> int: +def depth_of_tree(tree: Node | None) -> int: """ Recursive function that returns the depth of a binary tree. diff --git a/data_structures/binary_tree/binary_search_tree_recursive.py b/data_structures/binary_tree/binary_search_tree_recursive.py index a05e28a7b..4bdf4e33d 100644 --- a/data_structures/binary_tree/binary_search_tree_recursive.py +++ b/data_structures/binary_tree/binary_search_tree_recursive.py @@ -7,21 +7,23 @@ python -m unittest binary_search_tree_recursive.py To run an example: python binary_search_tree_recursive.py """ +from __future__ import annotations + import unittest -from typing import Iterator, Optional +from typing import Iterator class Node: - def __init__(self, label: int, parent: Optional["Node"]) -> None: + def __init__(self, label: int, parent: Node | None) -> None: self.label = label self.parent = parent - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None class BinarySearchTree: def __init__(self) -> None: - self.root: Optional[Node] = None + self.root: Node | None = None def empty(self) -> None: """ @@ -66,9 +68,7 @@ class BinarySearchTree: """ self.root = self._put(self.root, label) - def _put( - self, node: Optional[Node], label: int, parent: Optional[Node] = None - ) -> Node: + def _put(self, node: Node | None, label: int, parent: Node | None = None) -> Node: if node is None: node = Node(label, parent) else: @@ -98,7 +98,7 @@ class BinarySearchTree: """ return self._search(self.root, label) - def _search(self, node: Optional[Node], label: int) -> Node: + def _search(self, node: Node | None, label: int) -> Node: if node is None: raise Exception(f"Node with label {label} does not exist") else: @@ -140,7 +140,7 @@ class BinarySearchTree: else: self._reassign_nodes(node, None) - def _reassign_nodes(self, node: Node, new_children: Optional[Node]) -> None: + def _reassign_nodes(self, node: Node, new_children: Node | None) -> None: if new_children: new_children.parent = node.parent @@ -244,7 +244,7 @@ class BinarySearchTree: """ return self._inorder_traversal(self.root) - def _inorder_traversal(self, node: Optional[Node]) -> Iterator[Node]: + def _inorder_traversal(self, node: Node | None) -> Iterator[Node]: if node is not None: yield from self._inorder_traversal(node.left) yield node @@ -266,7 +266,7 @@ class BinarySearchTree: """ return self._preorder_traversal(self.root) - def _preorder_traversal(self, node: Optional[Node]) -> Iterator[Node]: + def _preorder_traversal(self, node: Node | None) -> Iterator[Node]: if node is not None: yield node yield from self._preorder_traversal(node.left) diff --git a/data_structures/binary_tree/binary_tree_traversals.py b/data_structures/binary_tree/binary_tree_traversals.py index 7857880da..de9e9d60d 100644 --- a/data_structures/binary_tree/binary_tree_traversals.py +++ b/data_structures/binary_tree/binary_tree_traversals.py @@ -1,13 +1,14 @@ # https://en.wikipedia.org/wiki/Tree_traversal +from __future__ import annotations + from dataclasses import dataclass -from typing import Optional @dataclass class Node: data: int - left: Optional["Node"] = None - right: Optional["Node"] = None + left: Node | None = None + right: Node | None = None def make_tree() -> Node: diff --git a/data_structures/binary_tree/lazy_segment_tree.py b/data_structures/binary_tree/lazy_segment_tree.py index 9066db294..94329cb43 100644 --- a/data_structures/binary_tree/lazy_segment_tree.py +++ b/data_structures/binary_tree/lazy_segment_tree.py @@ -1,7 +1,6 @@ from __future__ import annotations import math -from typing import List, Union class SegmentTree: @@ -38,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] @@ -89,7 +88,7 @@ class SegmentTree: # query with O(lg n) def query( self, idx: int, left_element: int, right_element: int, a: int, b: int - ) -> Union[int, float]: + ) -> int | float: """ query(1, 1, size, a, b) for query max of [a,b] >>> A = [1, 2, -4, 7, 3, -5, 6, 11, -20, 9, 14, 15, 5, 2, -8] diff --git a/data_structures/binary_tree/merge_two_binary_trees.py b/data_structures/binary_tree/merge_two_binary_trees.py index 6b202adb3..d169e0e75 100644 --- a/data_structures/binary_tree/merge_two_binary_trees.py +++ b/data_structures/binary_tree/merge_two_binary_trees.py @@ -5,7 +5,7 @@ The rule for merging is that if two nodes overlap, then put the value sum of both nodes to the new value of the merged node. Otherwise, the NOT null node will be used as the node of new tree. """ -from typing import Optional +from __future__ import annotations class Node: @@ -15,11 +15,11 @@ class Node: def __init__(self, value: int = 0) -> None: self.value = value - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None -def merge_two_binary_trees(tree1: Optional[Node], tree2: Optional[Node]) -> Node: +def merge_two_binary_trees(tree1: Node | None, tree2: Node | None) -> Node: """ Returns root node of the merged tree. @@ -52,7 +52,7 @@ def merge_two_binary_trees(tree1: Optional[Node], tree2: Optional[Node]) -> Node return tree1 -def print_preorder(root: Optional[Node]) -> None: +def print_preorder(root: Node | None) -> None: """ Print pre-order traversal of the tree. diff --git a/data_structures/binary_tree/red_black_tree.py b/data_structures/binary_tree/red_black_tree.py index de971a712..e27757f20 100644 --- a/data_structures/binary_tree/red_black_tree.py +++ b/data_structures/binary_tree/red_black_tree.py @@ -2,7 +2,9 @@ python/black : true flake8 : passed """ -from typing import Iterator, Optional +from __future__ import annotations + +from typing import Iterator class RedBlackTree: @@ -21,11 +23,11 @@ class RedBlackTree: def __init__( self, - label: Optional[int] = None, + label: int | None = None, color: int = 0, - parent: Optional["RedBlackTree"] = None, - left: Optional["RedBlackTree"] = None, - right: Optional["RedBlackTree"] = None, + parent: RedBlackTree | None = None, + left: RedBlackTree | None = None, + right: RedBlackTree | None = None, ) -> None: """Initialize a new Red-Black Tree node with the given values: label: The value associated with this node @@ -42,7 +44,7 @@ class RedBlackTree: # Here are functions which are specific to red-black trees - def rotate_left(self) -> "RedBlackTree": + def rotate_left(self) -> RedBlackTree: """Rotate the subtree rooted at this node to the left and returns the new root to this subtree. Performing one rotation can be done in O(1). @@ -62,7 +64,7 @@ class RedBlackTree: right.parent = parent return right - def rotate_right(self) -> "RedBlackTree": + def rotate_right(self) -> RedBlackTree: """Rotate the subtree rooted at this node to the right and returns the new root to this subtree. Performing one rotation can be done in O(1). @@ -82,7 +84,7 @@ class RedBlackTree: left.parent = parent return left - def insert(self, label: int) -> "RedBlackTree": + def insert(self, label: int) -> RedBlackTree: """Inserts label into the subtree rooted at self, performs any rotations necessary to maintain balance, and then returns the new root to this subtree (likely self). @@ -139,7 +141,7 @@ class RedBlackTree: self.grandparent.color = 1 self.grandparent._insert_repair() - def remove(self, label: int) -> "RedBlackTree": + def remove(self, label: int) -> RedBlackTree: """Remove label from this tree.""" if self.label == label: if self.left and self.right: @@ -337,7 +339,7 @@ class RedBlackTree: """ return self.search(label) is not None - def search(self, label: int) -> "RedBlackTree": + def search(self, label: int) -> RedBlackTree: """Search through the tree for label, returning its node if it's found, and None otherwise. This method is guaranteed to run in O(log(n)) time. @@ -411,7 +413,7 @@ class RedBlackTree: return self.label @property - def grandparent(self) -> "RedBlackTree": + def grandparent(self) -> RedBlackTree: """Get the current node's grandparent, or None if it doesn't exist.""" if self.parent is None: return None @@ -419,7 +421,7 @@ class RedBlackTree: return self.parent.parent @property - def sibling(self) -> "RedBlackTree": + def sibling(self) -> RedBlackTree: """Get the current node's sibling, or None if it doesn't exist.""" if self.parent is None: return None diff --git a/data_structures/binary_tree/treap.py b/data_structures/binary_tree/treap.py index a09dcc928..0526b139b 100644 --- a/data_structures/binary_tree/treap.py +++ b/data_structures/binary_tree/treap.py @@ -1,9 +1,6 @@ -# flake8: noqa - from __future__ import annotations from random import random -from typing import Optional, Tuple class Node: @@ -12,11 +9,11 @@ class Node: Treap is a binary tree by value and heap by priority """ - def __init__(self, value: Optional[int] = None): + def __init__(self, value: int | None = None): self.value = value self.prior = random() - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None def __repr__(self) -> str: from pprint import pformat @@ -35,7 +32,7 @@ class Node: return value + left + right -def split(root: Optional[Node], value: int) -> Tuple[Optional[Node], Optional[Node]]: +def split(root: Node | None, value: int) -> tuple[Node | None, Node | None]: """ We split current tree into 2 trees with value: @@ -64,7 +61,7 @@ def split(root: Optional[Node], value: int) -> Tuple[Optional[Node], Optional[No return root, right -def merge(left: Optional[Node], right: Optional[Node]) -> Optional[Node]: +def merge(left: Node | None, right: Node | None) -> Node | None: """ We merge 2 trees into one. Note: all left tree's values must be less than all right tree's @@ -86,7 +83,7 @@ def merge(left: Optional[Node], right: Optional[Node]) -> Optional[Node]: return right -def insert(root: Optional[Node], value: int) -> Optional[Node]: +def insert(root: Node | None, value: int) -> Node | None: """ Insert element @@ -99,7 +96,7 @@ def insert(root: Optional[Node], value: int) -> Optional[Node]: return merge(merge(left, node), right) -def erase(root: Optional[Node], value: int) -> Optional[Node]: +def erase(root: Node | None, value: int) -> Node | None: """ Erase element @@ -112,7 +109,7 @@ def erase(root: Optional[Node], value: int) -> Optional[Node]: return merge(left, right) -def inorder(root: Optional[Node]) -> None: +def inorder(root: Node | None) -> None: """ Just recursive print of a tree """ @@ -124,7 +121,7 @@ def inorder(root: Optional[Node]) -> None: inorder(root.right) -def interactTreap(root: Optional[Node], args: str) -> Optional[Node]: +def interactTreap(root: Node | None, args: str) -> Node | None: """ Commands: + value to add value into treap diff --git a/data_structures/binary_tree/wavelet_tree.py b/data_structures/binary_tree/wavelet_tree.py index 1607244f7..173a88ab7 100644 --- a/data_structures/binary_tree/wavelet_tree.py +++ b/data_structures/binary_tree/wavelet_tree.py @@ -7,8 +7,7 @@ such as the with segment trees or fenwick trees. You can read more about them he 2. https://www.youtube.com/watch?v=4aSv9PcecDw&t=811s 3. https://www.youtube.com/watch?v=CybAgVF-MMc&t=1178s """ - -from typing import Optional +from __future__ import annotations test_array = [2, 1, 4, 5, 6, 0, 8, 9, 1, 2, 0, 6, 4, 2, 0, 6, 5, 3, 2, 7] @@ -18,8 +17,8 @@ class Node: self.minn: int = -1 self.maxx: int = -1 self.map_left: list[int] = [-1] * length - self.left: Optional[Node] = None - self.right: Optional[Node] = None + self.left: Node | None = None + self.right: Node | None = None def __repr__(self) -> str: """ diff --git a/data_structures/hashing/hash_table.py b/data_structures/hashing/hash_table.py index fd9e6eec1..f4422de53 100644 --- a/data_structures/hashing/hash_table.py +++ b/data_structures/hashing/hash_table.py @@ -19,7 +19,7 @@ class HashTable: return self._keys def balanced_factor(self): - return sum([1 for slot in self.values if slot is not None]) / ( + return sum(1 for slot in self.values if slot is not None) / ( self.size_table * self.charge_factor ) diff --git a/data_structures/hashing/hash_table_with_linked_list.py b/data_structures/hashing/hash_table_with_linked_list.py index fe838268f..f404c5251 100644 --- a/data_structures/hashing/hash_table_with_linked_list.py +++ b/data_structures/hashing/hash_table_with_linked_list.py @@ -14,7 +14,7 @@ class HashTableWithLinkedList(HashTable): def balanced_factor(self): return ( - sum([self.charge_factor - len(slot) for slot in self.values]) + sum(self.charge_factor - len(slot) for slot in self.values) / self.size_table * self.charge_factor ) diff --git a/data_structures/heap/heap.py b/data_structures/heap/heap.py index 65a70e468..550439edd 100644 --- a/data_structures/heap/heap.py +++ b/data_structures/heap/heap.py @@ -1,4 +1,6 @@ -from typing import Iterable, List, Optional +from __future__ import annotations + +from typing import Iterable class Heap: @@ -25,19 +27,19 @@ class Heap: """ def __init__(self) -> None: - self.h: List[float] = [] + self.h: list[float] = [] self.heap_size: int = 0 def __repr__(self) -> str: return str(self.h) - def parent_index(self, child_idx: int) -> Optional[int]: + def parent_index(self, child_idx: int) -> int | None: """return the parent index of given child""" if child_idx > 0: return (child_idx - 1) // 2 return None - def left_child_idx(self, parent_idx: int) -> Optional[int]: + def left_child_idx(self, parent_idx: int) -> int | None: """ return the left child index if the left child exists. if not, return None. @@ -47,7 +49,7 @@ class Heap: return left_child_index return None - def right_child_idx(self, parent_idx: int) -> Optional[int]: + def right_child_idx(self, parent_idx: int) -> int | None: """ return the right child index if the right child exists. if not, return None. diff --git a/data_structures/heap/randomized_heap.py b/data_structures/heap/randomized_heap.py index 0ddc2272e..f584f5cb3 100644 --- a/data_structures/heap/randomized_heap.py +++ b/data_structures/heap/randomized_heap.py @@ -3,7 +3,7 @@ from __future__ import annotations import random -from typing import Generic, Iterable, List, Optional, TypeVar +from typing import Generic, Iterable, TypeVar T = TypeVar("T") @@ -16,8 +16,8 @@ class RandomizedHeapNode(Generic[T]): def __init__(self, value: T) -> None: self._value: T = value - self.left: Optional[RandomizedHeapNode[T]] = None - self.right: Optional[RandomizedHeapNode[T]] = None + self.left: RandomizedHeapNode[T] | None = None + self.right: RandomizedHeapNode[T] | None = None @property def value(self) -> T: @@ -26,8 +26,8 @@ class RandomizedHeapNode(Generic[T]): @staticmethod def merge( - root1: Optional[RandomizedHeapNode[T]], root2: Optional[RandomizedHeapNode[T]] - ) -> Optional[RandomizedHeapNode[T]]: + root1: RandomizedHeapNode[T] | None, root2: RandomizedHeapNode[T] | None + ) -> RandomizedHeapNode[T] | None: """Merge 2 nodes together.""" if not root1: return root2 @@ -69,13 +69,13 @@ class RandomizedHeap(Generic[T]): [-1, 0, 1] """ - def __init__(self, data: Optional[Iterable[T]] = ()) -> None: + def __init__(self, data: Iterable[T] | None = ()) -> None: """ >>> rh = RandomizedHeap([3, 1, 3, 7]) >>> rh.to_sorted_list() [1, 3, 3, 7] """ - self._root: Optional[RandomizedHeapNode[T]] = None + self._root: RandomizedHeapNode[T] | None = None for item in data: self.insert(item) @@ -151,7 +151,7 @@ class RandomizedHeap(Generic[T]): """ self._root = None - def to_sorted_list(self) -> List[T]: + def to_sorted_list(self) -> list[T]: """ Returns sorted list containing all the values in the heap. diff --git a/data_structures/heap/skew_heap.py b/data_structures/heap/skew_heap.py index 417a383f7..b59441389 100644 --- a/data_structures/heap/skew_heap.py +++ b/data_structures/heap/skew_heap.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Generic, Iterable, Iterator, Optional, TypeVar +from typing import Generic, Iterable, Iterator, TypeVar T = TypeVar("T") @@ -15,8 +15,8 @@ class SkewNode(Generic[T]): def __init__(self, value: T) -> None: self._value: T = value - self.left: Optional[SkewNode[T]] = None - self.right: Optional[SkewNode[T]] = None + self.left: SkewNode[T] | None = None + self.right: SkewNode[T] | None = None @property def value(self) -> T: @@ -25,8 +25,8 @@ class SkewNode(Generic[T]): @staticmethod def merge( - root1: Optional[SkewNode[T]], root2: Optional[SkewNode[T]] - ) -> Optional[SkewNode[T]]: + root1: SkewNode[T] | None, root2: SkewNode[T] | None + ) -> SkewNode[T] | None: """Merge 2 nodes together.""" if not root1: return root2 @@ -69,13 +69,13 @@ class SkewHeap(Generic[T]): [-1, 0, 1] """ - def __init__(self, data: Optional[Iterable[T]] = ()) -> None: + def __init__(self, data: Iterable[T] | None = ()) -> None: """ >>> sh = SkewHeap([3, 1, 3, 7]) >>> list(sh) [1, 3, 3, 7] """ - self._root: Optional[SkewNode[T]] = None + self._root: SkewNode[T] | None = None for item in data: self.insert(item) diff --git a/data_structures/linked_list/merge_two_lists.py b/data_structures/linked_list/merge_two_lists.py index 96ec6b8ab..43dd46186 100644 --- a/data_structures/linked_list/merge_two_lists.py +++ b/data_structures/linked_list/merge_two_lists.py @@ -5,7 +5,6 @@ from __future__ import annotations from collections.abc import Iterable, Iterator from dataclasses import dataclass -from typing import Optional test_data_odd = (3, 9, -11, 0, 7, 5, 1, -1) test_data_even = (4, 6, 2, 0, 8, 10, 3, -2) @@ -14,12 +13,12 @@ test_data_even = (4, 6, 2, 0, 8, 10, 3, -2) @dataclass class Node: data: int - next: Optional[Node] + next: Node | None class SortedLinkedList: def __init__(self, ints: Iterable[int]) -> None: - self.head: Optional[Node] = None + self.head: Node | None = None for i in reversed(sorted(ints)): self.head = Node(i, self.head) diff --git a/data_structures/linked_list/print_reverse.py b/data_structures/linked_list/print_reverse.py index c46f228e7..f83d5607f 100644 --- a/data_structures/linked_list/print_reverse.py +++ b/data_structures/linked_list/print_reverse.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations class Node: @@ -16,7 +16,7 @@ class Node: return "->".join(string_rep) -def make_linked_list(elements_list: List): +def make_linked_list(elements_list: list): """Creates a Linked List from the elements of the given sequence (list/tuple) and returns the head of the Linked List. >>> make_linked_list([]) diff --git a/data_structures/linked_list/skip_list.py b/data_structures/linked_list/skip_list.py index 8f06e6193..ee0b44607 100644 --- a/data_structures/linked_list/skip_list.py +++ b/data_structures/linked_list/skip_list.py @@ -2,11 +2,10 @@ Based on "Skip Lists: A Probabilistic Alternative to Balanced Trees" by William Pugh https://epaperpress.com/sortsearch/download/skiplist.pdf """ - from __future__ import annotations from random import random -from typing import Generic, Optional, TypeVar +from typing import Generic, TypeVar KT = TypeVar("KT") VT = TypeVar("VT") @@ -124,7 +123,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[Node[KT, VT] | None, list[Node[KT, VT]]]: """ :param key: Searched key, :return: Tuple with searched node (or None if given key is not present) @@ -222,7 +221,7 @@ class SkipList(Generic[KT, VT]): else: update_node.forward[i] = new_node - def find(self, key: VT) -> Optional[VT]: + def find(self, key: VT) -> VT | None: """ :param key: Search key. :return: Value associated with given key or None if given key is not present. diff --git a/data_structures/stacks/evaluate_postfix_notations.py b/data_structures/stacks/evaluate_postfix_notations.py index 2a4baf9d6..51ea353b1 100644 --- a/data_structures/stacks/evaluate_postfix_notations.py +++ b/data_structures/stacks/evaluate_postfix_notations.py @@ -1,5 +1,3 @@ -from typing import Any, List - """ The Reverse Polish Nation also known as Polish postfix notation or simply postfix notation. @@ -8,6 +6,9 @@ Classic examples of simple stack implementations Valid operators are +, -, *, /. Each operand may be an integer or another expression. """ +from __future__ import annotations + +from typing import Any def evaluate_postfix(postfix_notation: list) -> int: @@ -23,7 +24,7 @@ def evaluate_postfix(postfix_notation: list) -> int: return 0 operations = {"+", "-", "*", "/"} - stack: List[Any] = [] + stack: list[Any] = [] for token in postfix_notation: if token in operations: diff --git a/data_structures/stacks/linked_stack.py b/data_structures/stacks/linked_stack.py index 0b9c9d45e..85b59a940 100644 --- a/data_structures/stacks/linked_stack.py +++ b/data_structures/stacks/linked_stack.py @@ -1,5 +1,7 @@ """ A Stack using a linked list like structure """ -from typing import Any, Optional +from __future__ import annotations + +from typing import Any class Node: @@ -42,7 +44,7 @@ class LinkedStack: """ def __init__(self) -> None: - self.top: Optional[Node] = None + self.top: Node | None = None def __iter__(self): node = self.top diff --git a/data_structures/stacks/stack.py b/data_structures/stacks/stack.py index 245d39b32..c62412150 100644 --- a/data_structures/stacks/stack.py +++ b/data_structures/stacks/stack.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations class StackOverflowError(BaseException): @@ -15,7 +15,7 @@ class Stack: """ def __init__(self, limit: int = 10): - self.stack: List[int] = [] + self.stack: list[int] = [] self.limit = limit def __bool__(self) -> bool: diff --git a/divide_and_conquer/convex_hull.py b/divide_and_conquer/convex_hull.py index 9c096f671..63f8dbb20 100644 --- a/divide_and_conquer/convex_hull.py +++ b/divide_and_conquer/convex_hull.py @@ -12,8 +12,9 @@ There are other several other algorithms for the convex hull problem which have not been implemented here, yet. """ +from __future__ import annotations -from typing import Iterable, List, Set, Union +from typing import Iterable class Point: @@ -84,8 +85,8 @@ class Point: def _construct_points( - list_of_tuples: Union[List[Point], List[List[float]], Iterable[List[float]]] -) -> List[Point]: + list_of_tuples: list[Point] | list[list[float]] | Iterable[list[float]], +) -> list[Point]: """ constructs a list of points from an array-like object of numbers @@ -114,7 +115,7 @@ def _construct_points( [] """ - points: List[Point] = [] + points: list[Point] = [] if list_of_tuples: for p in list_of_tuples: if isinstance(p, Point): @@ -130,7 +131,7 @@ def _construct_points( return points -def _validate_input(points: Union[List[Point], List[List[float]]]) -> List[Point]: +def _validate_input(points: list[Point] | list[list[float]]) -> list[Point]: """ validates an input instance before a convex-hull algorithms uses it @@ -218,7 +219,7 @@ def _det(a: Point, b: Point, c: Point) -> float: return det -def convex_hull_bf(points: List[Point]) -> List[Point]: +def convex_hull_bf(points: list[Point]) -> list[Point]: """ Constructs the convex hull of a set of 2D points using a brute force algorithm. The algorithm basically considers all combinations of points (i, j) and uses the @@ -291,7 +292,7 @@ def convex_hull_bf(points: List[Point]) -> List[Point]: return sorted(convex_set) -def convex_hull_recursive(points: List[Point]) -> List[Point]: +def convex_hull_recursive(points: list[Point]) -> list[Point]: """ Constructs the convex hull of a set of 2D points using a divide-and-conquer strategy The algorithm exploits the geometric properties of the problem by repeatedly @@ -362,7 +363,7 @@ def convex_hull_recursive(points: List[Point]) -> List[Point]: def _construct_hull( - points: List[Point], left: Point, right: Point, convex_set: Set[Point] + points: list[Point], left: Point, right: Point, convex_set: set[Point] ) -> None: """ @@ -405,7 +406,7 @@ def _construct_hull( _construct_hull(candidate_points, extreme_point, right, convex_set) -def convex_hull_melkman(points: List[Point]) -> List[Point]: +def convex_hull_melkman(points: list[Point]) -> list[Point]: """ Constructs the convex hull of a set of 2D points using the melkman algorithm. The algorithm works by iteratively inserting points of a simple polygonal chain diff --git a/divide_and_conquer/kth_order_statistic.py b/divide_and_conquer/kth_order_statistic.py index f6e81a306..666ad1a39 100644 --- a/divide_and_conquer/kth_order_statistic.py +++ b/divide_and_conquer/kth_order_statistic.py @@ -8,8 +8,9 @@ This is a divide and conquer algorithm that can find a solution in O(n) time. For more information of this algorithm: https://web.stanford.edu/class/archive/cs/cs161/cs161.1138/lectures/08/Small08.pdf """ +from __future__ import annotations + from random import choice -from typing import List def random_pivot(lst): @@ -21,7 +22,7 @@ def random_pivot(lst): return choice(lst) -def kth_number(lst: List[int], k: int) -> int: +def kth_number(lst: list[int], k: int) -> int: """ Return the kth smallest number in lst. >>> kth_number([2, 1, 3, 4, 5], 3) diff --git a/divide_and_conquer/mergesort.py b/divide_and_conquer/mergesort.py index 46a46941c..628080cef 100644 --- a/divide_and_conquer/mergesort.py +++ b/divide_and_conquer/mergesort.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def merge(left_half: List, right_half: List) -> List: +def merge(left_half: list, right_half: list) -> list: """Helper function for mergesort. >>> left_half = [-2] @@ -57,7 +57,7 @@ def merge(left_half: List, right_half: List) -> List: return sorted_array -def merge_sort(array: List) -> List: +def merge_sort(array: list) -> list: """Returns a list of sorted array elements using merge sort. >>> from random import shuffle diff --git a/divide_and_conquer/peak.py b/divide_and_conquer/peak.py index f94f83ed3..e60f28bfb 100644 --- a/divide_and_conquer/peak.py +++ b/divide_and_conquer/peak.py @@ -7,10 +7,10 @@ to find the maximum of the array. (From Kleinberg and Tardos. Algorithm Design. Addison Wesley 2006: Chapter 5 Solved Exercise 1) """ -from typing import List +from __future__ import annotations -def peak(lst: List[int]) -> int: +def peak(lst: list[int]) -> int: """ Return the peak value of `lst`. >>> peak([1, 2, 3, 4, 5, 4, 3, 2, 1]) diff --git a/electronics/electric_power.py b/electronics/electric_power.py index e4e685bbd..ac673d7e3 100644 --- a/electronics/electric_power.py +++ b/electronics/electric_power.py @@ -1,9 +1,10 @@ # https://en.m.wikipedia.org/wiki/Electric_power +from __future__ import annotations + from collections import namedtuple -from typing import Tuple -def electric_power(voltage: float, current: float, power: float) -> Tuple: +def electric_power(voltage: float, current: float, power: float) -> tuple: """ This function can calculate any one of the three (voltage, current, power), fundamental value of electrical system. diff --git a/electronics/ohms_law.py b/electronics/ohms_law.py index 41bffa9f8..66e737c1f 100644 --- a/electronics/ohms_law.py +++ b/electronics/ohms_law.py @@ -1,8 +1,8 @@ # https://en.wikipedia.org/wiki/Ohm%27s_law -from typing import Dict +from __future__ import annotations -def ohms_law(voltage: float, current: float, resistance: float) -> Dict[str, float]: +def ohms_law(voltage: float, current: float, resistance: float) -> dict[str, float]: """ Apply Ohm's Law, on any two given electrical values, which can be voltage, current, and resistance, and then in a Python dict return name/value pair of the zero value. diff --git a/graphs/basic_graphs.py b/graphs/basic_graphs.py index 9cd6dd0f9..db0ef8e7b 100644 --- a/graphs/basic_graphs.py +++ b/graphs/basic_graphs.py @@ -13,7 +13,7 @@ def initialize_unweighted_directed_graph( graph[i + 1] = [] for e in range(edge_count): - x, y = [int(i) for i in _input(f"Edge {e + 1}: ")] + x, y = (int(i) for i in _input(f"Edge {e + 1}: ")) graph[x].append(y) return graph @@ -26,7 +26,7 @@ def initialize_unweighted_undirected_graph( graph[i + 1] = [] for e in range(edge_count): - x, y = [int(i) for i in _input(f"Edge {e + 1}: ")] + x, y = (int(i) for i in _input(f"Edge {e + 1}: ")) graph[x].append(y) graph[y].append(x) return graph @@ -40,14 +40,14 @@ def initialize_weighted_undirected_graph( graph[i + 1] = [] for e in range(edge_count): - x, y, w = [int(i) for i in _input(f"Edge {e + 1}: ")] + x, y, w = (int(i) for i in _input(f"Edge {e + 1}: ")) graph[x].append((y, w)) graph[y].append((x, w)) return graph if __name__ == "__main__": - n, m = [int(i) for i in _input("Number of nodes and edges: ")] + n, m = (int(i) for i in _input("Number of nodes and edges: ")) graph_choice = int( _input( diff --git a/graphs/bellman_ford.py b/graphs/bellman_ford.py index d6d6b2ac7..0f654a510 100644 --- a/graphs/bellman_ford.py +++ b/graphs/bellman_ford.py @@ -11,7 +11,7 @@ def check_negative_cycle( graph: list[dict[str, int]], distance: list[float], edge_count: int ): for j in range(edge_count): - u, v, w = [graph[j][k] for k in ["src", "dst", "weight"]] + u, v, w = (graph[j][k] for k in ["src", "dst", "weight"]) if distance[u] != float("inf") and distance[u] + w < distance[v]: return True return False @@ -38,7 +38,7 @@ def bellman_ford( for i in range(vertex_count - 1): for j in range(edge_count): - u, v, w = [graph[j][k] for k in ["src", "dst", "weight"]] + u, v, w = (graph[j][k] for k in ["src", "dst", "weight"]) if distance[u] != float("inf") and distance[u] + w < distance[v]: distance[v] = distance[u] + w @@ -62,10 +62,10 @@ if __name__ == "__main__": for i in range(E): print("Edge ", i + 1) - src, dest, weight = [ + src, dest, weight = ( int(x) for x in input("Enter source, destination, weight: ").strip().split(" ") - ] + ) graph[i] = {"src": src, "dst": dest, "weight": weight} source = int(input("\nEnter shortest path source:").strip()) diff --git a/graphs/bfs_zero_one_shortest_path.py b/graphs/bfs_zero_one_shortest_path.py index a68b5602c..78047c5d2 100644 --- a/graphs/bfs_zero_one_shortest_path.py +++ b/graphs/bfs_zero_one_shortest_path.py @@ -1,13 +1,13 @@ -from collections import deque -from collections.abc import Iterator -from dataclasses import dataclass -from typing import Optional, Union - """ Finding the shortest path in 0-1-graph in O(E + V) which is faster than dijkstra. 0-1-graph is the weighted graph with the weights equal to 0 or 1. Link: https://codeforces.com/blog/entry/22276 """ +from __future__ import annotations + +from collections import deque +from collections.abc import Iterator +from dataclasses import dataclass @dataclass @@ -59,7 +59,7 @@ class AdjacencyList: self._graph[from_vertex].append(Edge(to_vertex, weight)) - def get_shortest_path(self, start_vertex: int, finish_vertex: int) -> Optional[int]: + def get_shortest_path(self, start_vertex: int, finish_vertex: int) -> int | None: """ Return the shortest distance from start_vertex to finish_vertex in 0-1-graph. 1 1 1 @@ -107,7 +107,7 @@ class AdjacencyList: ValueError: No path from start_vertex to finish_vertex. """ queue = deque([start_vertex]) - distances: list[Union[int, None]] = [None] * self.size + distances: list[int | None] = [None] * self.size distances[start_vertex] = 0 while queue: diff --git a/graphs/bidirectional_a_star.py b/graphs/bidirectional_a_star.py index 729d8957b..071f1cd68 100644 --- a/graphs/bidirectional_a_star.py +++ b/graphs/bidirectional_a_star.py @@ -1,15 +1,12 @@ """ https://en.wikipedia.org/wiki/Bidirectional_search """ - from __future__ import annotations import time from math import sqrt # 1 for manhattan, 0 for euclidean -from typing import Optional - HEURISTIC = 0 grid = [ @@ -50,7 +47,7 @@ class Node: goal_x: int, goal_y: int, g_cost: int, - parent: Optional[Node], + parent: Node | None, ) -> None: self.pos_x = pos_x self.pos_y = pos_y @@ -157,7 +154,7 @@ class AStar: ) return successors - def retrace_path(self, node: Optional[Node]) -> list[TPosition]: + def retrace_path(self, node: Node | None) -> list[TPosition]: """ Retrace the path from parents to parents until start node """ diff --git a/graphs/bidirectional_breadth_first_search.py b/graphs/bidirectional_breadth_first_search.py index 9b84ab21b..27e4f0b16 100644 --- a/graphs/bidirectional_breadth_first_search.py +++ b/graphs/bidirectional_breadth_first_search.py @@ -1,11 +1,9 @@ """ https://en.wikipedia.org/wiki/Bidirectional_search """ - from __future__ import annotations import time -from typing import Optional Path = list[tuple[int, int]] @@ -24,7 +22,7 @@ delta = [[-1, 0], [0, -1], [1, 0], [0, 1]] # up, left, down, right class Node: def __init__( - self, pos_x: int, pos_y: int, goal_x: int, goal_y: int, parent: Optional[Node] + self, pos_x: int, pos_y: int, goal_x: int, goal_y: int, parent: Node | None ): self.pos_x = pos_x self.pos_y = pos_y @@ -57,7 +55,7 @@ class BreadthFirstSearch: self.node_queue = [self.start] self.reached = False - def search(self) -> Optional[Path]: + def search(self) -> Path | None: while self.node_queue: current_node = self.node_queue.pop(0) @@ -93,7 +91,7 @@ class BreadthFirstSearch: ) return successors - def retrace_path(self, node: Optional[Node]) -> Path: + def retrace_path(self, node: Node | None) -> Path: """ Retrace the path from parents to parents until start node """ @@ -125,7 +123,7 @@ class BidirectionalBreadthFirstSearch: self.bwd_bfs = BreadthFirstSearch(goal, start) self.reached = False - def search(self) -> Optional[Path]: + def search(self) -> Path | None: 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) diff --git a/graphs/breadth_first_search.py b/graphs/breadth_first_search.py index 305db01e1..7c626429e 100644 --- a/graphs/breadth_first_search.py +++ b/graphs/breadth_first_search.py @@ -1,13 +1,12 @@ #!/usr/bin/python """ Author: OMKAR PATHAK """ - -from typing import Dict, List, Set +from __future__ import annotations class Graph: def __init__(self) -> None: - self.vertices: Dict[int, List[int]] = {} + self.vertices: dict[int, list[int]] = {} def print_graph(self) -> None: """ @@ -35,7 +34,7 @@ class Graph: else: self.vertices[from_vertex] = [to_vertex] - def bfs(self, start_vertex: int) -> Set[int]: + def bfs(self, start_vertex: int) -> set[int]: """ >>> g = Graph() >>> g.add_edge(0, 1) diff --git a/graphs/breadth_first_search_shortest_path.py b/graphs/breadth_first_search_shortest_path.py index 48f8ab1a4..697a8c634 100644 --- a/graphs/breadth_first_search_shortest_path.py +++ b/graphs/breadth_first_search_shortest_path.py @@ -3,8 +3,6 @@ from a given source node to a target node in an unweighted graph. """ from __future__ import annotations -from typing import Optional - graph = { "A": ["B", "C", "E"], "B": ["A", "D", "E"], @@ -24,7 +22,7 @@ class Graph: """ self.graph = graph # mapping node to its parent in resulting breadth first tree - self.parent: dict[str, Optional[str]] = {} + self.parent: dict[str, str | None] = {} self.source_vertex = source_vertex def breath_first_search(self) -> None: diff --git a/graphs/depth_first_search.py b/graphs/depth_first_search.py index 5d74a6db9..f20a503ca 100644 --- a/graphs/depth_first_search.py +++ b/graphs/depth_first_search.py @@ -1,11 +1,8 @@ """Non recursive implementation of a DFS algorithm.""" - from __future__ import annotations -from typing import Set - -def depth_first_search(graph: dict, start: str) -> Set[str]: +def depth_first_search(graph: dict, start: str) -> set[str]: """Depth First Search on Graph :param graph: directed graph in dictionary format :param start: starting vertex as a string diff --git a/graphs/greedy_best_first.py b/graphs/greedy_best_first.py index d5e80247a..d49e65b9d 100644 --- a/graphs/greedy_best_first.py +++ b/graphs/greedy_best_first.py @@ -4,8 +4,6 @@ https://en.wikipedia.org/wiki/Best-first_search#Greedy_BFS from __future__ import annotations -from typing import Optional - Path = list[tuple[int, int]] grid = [ @@ -44,7 +42,7 @@ class Node: goal_x: int, goal_y: int, g_cost: float, - parent: Optional[Node], + parent: Node | None, ): self.pos_x = pos_x self.pos_y = pos_y @@ -93,7 +91,7 @@ class GreedyBestFirst: self.reached = False - def search(self) -> Optional[Path]: + def search(self) -> Path | None: """ Search for the path, if a path is not found, only the starting position is returned @@ -156,7 +154,7 @@ class GreedyBestFirst: ) return successors - def retrace_path(self, node: Optional[Node]) -> Path: + def retrace_path(self, node: Node | None) -> Path: """ Retrace the path from parents to parents until start node """ diff --git a/graphs/minimum_spanning_tree_kruskal.py b/graphs/minimum_spanning_tree_kruskal.py index f21a87a7d..85d937010 100644 --- a/graphs/minimum_spanning_tree_kruskal.py +++ b/graphs/minimum_spanning_tree_kruskal.py @@ -40,7 +40,7 @@ if __name__ == "__main__": # pragma: no cover edges = [] for _ in range(num_edges): - node1, node2, cost = [int(x) for x in input().strip().split()] + node1, node2, cost = (int(x) for x in input().strip().split()) edges.append((node1, node2, cost)) kruskal(num_nodes, edges) diff --git a/graphs/minimum_spanning_tree_prims2.py b/graphs/minimum_spanning_tree_prims2.py index c3444c36f..d924ee3db 100644 --- a/graphs/minimum_spanning_tree_prims2.py +++ b/graphs/minimum_spanning_tree_prims2.py @@ -6,9 +6,10 @@ edges in the tree is minimized. The algorithm operates by building this tree one at a time, from an arbitrary starting vertex, at each step adding the cheapest possible connection from the tree to another vertex. """ +from __future__ import annotations from sys import maxsize -from typing import Generic, Optional, TypeVar +from typing import Generic, TypeVar T = TypeVar("T") @@ -219,7 +220,7 @@ class GraphUndirectedWeighted(Generic[T]): def prims_algo( graph: GraphUndirectedWeighted[T], -) -> tuple[dict[T, int], dict[T, Optional[T]]]: +) -> tuple[dict[T, int], dict[T, T | None]]: """ >>> graph = GraphUndirectedWeighted() @@ -240,7 +241,7 @@ def prims_algo( """ # prim's algorithm for minimum spanning tree dist: dict[T, int] = {node: maxsize for node in graph.connections} - parent: dict[T, Optional[T]] = {node: None for node in graph.connections} + parent: dict[T, T | None] = {node: None for node in graph.connections} priority_queue: MinPriorityQueue[T] = MinPriorityQueue() for node, weight in dist.items(): diff --git a/graphs/page_rank.py b/graphs/page_rank.py index 0f5129146..672405b73 100644 --- a/graphs/page_rank.py +++ b/graphs/page_rank.py @@ -43,7 +43,7 @@ def page_rank(nodes, limit=3, d=0.85): print(f"======= Iteration {i + 1} =======") for j, node in enumerate(nodes): ranks[node.name] = (1 - d) + d * sum( - [ranks[ib] / outbounds[ib] for ib in node.inbound] + ranks[ib] / outbounds[ib] for ib in node.inbound ) print(ranks) diff --git a/graphs/scc_kosaraju.py b/graphs/scc_kosaraju.py index 2b3417014..fa182aa2f 100644 --- a/graphs/scc_kosaraju.py +++ b/graphs/scc_kosaraju.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations def dfs(u): @@ -39,16 +39,16 @@ if __name__ == "__main__": # n - no of nodes, m - no of edges n, m = list(map(int, input().strip().split())) - graph: List[List[int]] = [[] for i in range(n)] # graph - reversedGraph: List[List[int]] = [[] for i in range(n)] # reversed graph + graph: list[list[int]] = [[] for i in range(n)] # graph + reversedGraph: list[list[int]] = [[] for i in range(n)] # reversed graph # input graph data (edges) for i in range(m): u, v = list(map(int, input().strip().split())) graph[u].append(v) reversedGraph[v].append(u) - stack: List[int] = [] - visit: List[bool] = [False] * n - scc: List[int] = [] - component: List[int] = [] + stack: list[int] = [] + visit: list[bool] = [False] * n + scc: list[int] = [] + component: list[int] = [] print(kosaraju()) diff --git a/hashes/luhn.py b/hashes/luhn.py index 81014120d..bb77fd05c 100644 --- a/hashes/luhn.py +++ b/hashes/luhn.py @@ -1,5 +1,5 @@ """ Luhn Algorithm """ -from typing import List +from __future__ import annotations def is_luhn(string: str) -> bool: @@ -17,9 +17,9 @@ def is_luhn(string: str) -> bool: [False, False, False, True, False, False, False, False, False, False] """ check_digit: int - _vector: List[str] = list(string) + _vector: list[str] = list(string) __vector, check_digit = _vector[:-1], int(_vector[-1]) - vector: List[int] = [int(digit) for digit in __vector] + vector: list[int] = [int(digit) for digit in __vector] vector.reverse() for i, digit in enumerate(vector): diff --git a/knapsack/knapsack.py b/knapsack/knapsack.py index 756443ea6..18a36c3bc 100644 --- a/knapsack/knapsack.py +++ b/knapsack/knapsack.py @@ -1,11 +1,10 @@ -from typing import List - """ A naive recursive implementation of 0-1 Knapsack Problem https://en.wikipedia.org/wiki/Knapsack_problem """ +from __future__ import annotations -def knapsack(capacity: int, weights: List[int], values: List[int], counter: int) -> int: +def knapsack(capacity: int, weights: list[int], values: list[int], counter: int) -> int: """ Returns the maximum value that can be put in a knapsack of a capacity cap, whereby each weight w has a specific value val. diff --git a/linear_algebra/src/lib.py b/linear_algebra/src/lib.py index 5e2f82018..74aeb9137 100644 --- a/linear_algebra/src/lib.py +++ b/linear_algebra/src/lib.py @@ -18,11 +18,11 @@ Overview: - function squareZeroMatrix(N) - function randomMatrix(W,H,a,b) """ - +from __future__ import annotations import math import random -from typing import Collection, Optional, Union, overload +from typing import Collection, overload class Vector: @@ -46,7 +46,7 @@ class Vector: TODO: compare-operator """ - def __init__(self, components: Optional[Collection[float]] = None) -> None: + def __init__(self, components: Collection[float] | None = None) -> None: """ input: components or nothing simple constructor for init the vector @@ -97,7 +97,7 @@ class Vector: summe += c ** 2 return math.sqrt(summe) - def __add__(self, other: "Vector") -> "Vector": + def __add__(self, other: Vector) -> Vector: """ input: other vector assumes: other vector has the same size @@ -110,7 +110,7 @@ class Vector: else: raise Exception("must have the same size") - def __sub__(self, other: "Vector") -> "Vector": + def __sub__(self, other: Vector) -> Vector: """ input: other vector assumes: other vector has the same size @@ -124,14 +124,14 @@ class Vector: raise Exception("must have the same size") @overload - def __mul__(self, other: float) -> "Vector": + def __mul__(self, other: float) -> Vector: ... @overload - def __mul__(self, other: "Vector") -> float: + def __mul__(self, other: Vector) -> float: ... - def __mul__(self, other: Union[float, "Vector"]) -> Union[float, "Vector"]: + def __mul__(self, other: float | Vector) -> float | Vector: """ mul implements the scalar multiplication and the dot-product @@ -148,7 +148,7 @@ class Vector: else: # error case raise Exception("invalid operand!") - def copy(self) -> "Vector": + def copy(self) -> Vector: """ copies this vector and returns it. """ @@ -313,14 +313,14 @@ class Matrix: raise Exception("matrix is not square") @overload - def __mul__(self, other: float) -> "Matrix": + def __mul__(self, other: float) -> Matrix: ... @overload def __mul__(self, other: Vector) -> Vector: ... - def __mul__(self, other: Union[float, Vector]) -> Union[Vector, "Matrix"]: + def __mul__(self, other: float | Vector) -> Vector | Matrix: """ implements the matrix-vector multiplication. implements the matrix-scalar multiplication @@ -347,7 +347,7 @@ class Matrix: ] return Matrix(matrix, self.__width, self.__height) - def __add__(self, other: "Matrix") -> "Matrix": + def __add__(self, other: Matrix) -> Matrix: """ implements the matrix-addition. """ @@ -362,7 +362,7 @@ class Matrix: else: raise Exception("matrix must have the same dimension!") - def __sub__(self, other: "Matrix") -> "Matrix": + def __sub__(self, other: Matrix) -> Matrix: """ implements the matrix-subtraction. """ diff --git a/machine_learning/similarity_search.py b/machine_learning/similarity_search.py index af845c910..ec1b9f9e3 100644 --- a/machine_learning/similarity_search.py +++ b/machine_learning/similarity_search.py @@ -7,8 +7,9 @@ returns a list containing two data for each vector: 1. the nearest vector 2. distance between the vector and the nearest vector (float) """ +from __future__ import annotations + import math -from typing import List, Union import numpy as np @@ -33,7 +34,7 @@ def euclidean(input_a: np.ndarray, input_b: np.ndarray) -> float: def similarity_search( dataset: np.ndarray, value_array: np.ndarray -) -> List[List[Union[List[float], float]]]: +) -> list[list[list[float] | float]]: """ :param dataset: Set containing the vectors. Should be ndarray. :param value_array: vector/vectors we want to know the nearest vector from dataset. diff --git a/maths/area_under_curve.py b/maths/area_under_curve.py index 2d01e414b..ce0932426 100644 --- a/maths/area_under_curve.py +++ b/maths/area_under_curve.py @@ -1,14 +1,15 @@ """ Approximates the area under the curve using the trapezoidal rule """ +from __future__ import annotations -from typing import Callable, Union +from typing import Callable def trapezoidal_area( - fnc: Callable[[Union[int, float]], Union[int, float]], - x_start: Union[int, float], - x_end: Union[int, float], + fnc: Callable[[int | float], int | float], + x_start: int | float, + x_end: int | float, steps: int = 100, ) -> float: """ diff --git a/maths/average_mean.py b/maths/average_mean.py index e02e307f2..274c434ab 100644 --- a/maths/average_mean.py +++ b/maths/average_mean.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def mean(nums: List) -> float: +def mean(nums: list) -> float: """ Find mean of a list of numbers. Wiki: https://en.wikipedia.org/wiki/Mean diff --git a/maths/average_median.py b/maths/average_median.py index 497bf0c3a..cd1ec1574 100644 --- a/maths/average_median.py +++ b/maths/average_median.py @@ -1,7 +1,7 @@ -from typing import Union +from __future__ import annotations -def median(nums: list) -> Union[int, float]: +def median(nums: list) -> int | float: """ Find median of a list of numbers. Wiki: https://en.wikipedia.org/wiki/Median diff --git a/maths/entropy.py b/maths/entropy.py index 43bb3860f..498c28f31 100644 --- a/maths/entropy.py +++ b/maths/entropy.py @@ -68,7 +68,7 @@ def calculate_prob(text: str) -> None: my_fir_sum += prob * math.log2(prob) # entropy formula. # print entropy - print("{:.1f}".format(round(-1 * my_fir_sum))) + print(f"{round(-1 * my_fir_sum):.1f}") # two len string all_sum = sum(two_char_strings.values()) @@ -83,10 +83,10 @@ def calculate_prob(text: str) -> None: my_sec_sum += prob * math.log2(prob) # print second entropy - print("{:.1f}".format(round(-1 * my_sec_sum))) + print(f"{round(-1 * my_sec_sum):.1f}") # print the difference between them - print("{:.1f}".format(round((-1 * my_sec_sum) - (-1 * my_fir_sum)))) + print(f"{round((-1 * my_sec_sum) - (-1 * my_fir_sum)):.1f}") def analyze_text(text: str) -> tuple[dict, dict]: diff --git a/maths/euclidean_distance.py b/maths/euclidean_distance.py index 6e0da6370..a20781613 100644 --- a/maths/euclidean_distance.py +++ b/maths/euclidean_distance.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Iterable, Union import numpy as np diff --git a/maths/extended_euclidean_algorithm.py b/maths/extended_euclidean_algorithm.py index e7087636c..72afd40aa 100644 --- a/maths/extended_euclidean_algorithm.py +++ b/maths/extended_euclidean_algorithm.py @@ -12,12 +12,12 @@ https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm # @Email: silentcat@protonmail.com # @Last modified by: pikulet # @Last modified time: 2020-10-02 +from __future__ import annotations import sys -from typing import Tuple -def extended_euclidean_algorithm(a: int, b: int) -> Tuple[int, int]: +def extended_euclidean_algorithm(a: int, b: int) -> tuple[int, int]: """ Extended Euclidean Algorithm. diff --git a/maths/hardy_ramanujanalgo.py b/maths/hardy_ramanujanalgo.py index 90e4913c7..e36f763da 100644 --- a/maths/hardy_ramanujanalgo.py +++ b/maths/hardy_ramanujanalgo.py @@ -37,7 +37,7 @@ def exactPrimeFactorCount(n): if __name__ == "__main__": n = 51242183 print(f"The number of distinct prime factors is/are {exactPrimeFactorCount(n)}") - print("The value of log(log(n)) is {:.4f}".format(math.log(math.log(n)))) + print(f"The value of log(log(n)) is {math.log(math.log(n)):.4f}") """ The number of distinct prime factors is/are 3 diff --git a/maths/line_length.py b/maths/line_length.py index 1d386b44b..c4d986279 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -1,11 +1,13 @@ +from __future__ import annotations + import math -from typing import Callable, Union +from typing import Callable def line_length( - fnc: Callable[[Union[int, float]], Union[int, float]], - x_start: Union[int, float], - x_end: Union[int, float], + fnc: Callable[[int | float], int | float], + x_start: int | float, + x_end: int | float, steps: int = 100, ) -> float: diff --git a/maths/max_sum_sliding_window.py b/maths/max_sum_sliding_window.py index 593cb5c8b..c6f9b4ed0 100644 --- a/maths/max_sum_sliding_window.py +++ b/maths/max_sum_sliding_window.py @@ -6,10 +6,10 @@ Instead of using a nested for loop, in a Brute force approach we will use a tech called 'Window sliding technique' where the nested loops can be converted to a single loop to reduce time complexity. """ -from typing import List +from __future__ import annotations -def max_sum_in_array(array: List[int], k: int) -> int: +def max_sum_in_array(array: list[int], k: int) -> int: """ Returns the maximum sum of k consecutive elements >>> arr = [1, 4, 2, 10, 2, 3, 1, 0, 20] diff --git a/maths/median_of_two_arrays.py b/maths/median_of_two_arrays.py index cde12f5d7..55aa587a9 100644 --- a/maths/median_of_two_arrays.py +++ b/maths/median_of_two_arrays.py @@ -1,7 +1,7 @@ -from typing import List +from __future__ import annotations -def median_of_two_arrays(nums1: List[float], nums2: List[float]) -> float: +def median_of_two_arrays(nums1: list[float], nums2: list[float]) -> float: """ >>> median_of_two_arrays([1, 2], [3]) 2 diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py index 87184a76b..577c41a44 100644 --- a/maths/numerical_integration.py +++ b/maths/numerical_integration.py @@ -1,14 +1,15 @@ """ Approximates the area under the curve using the trapezoidal rule """ +from __future__ import annotations -from typing import Callable, Union +from typing import Callable def trapezoidal_area( - fnc: Callable[[Union[int, float]], Union[int, float]], - x_start: Union[int, float], - x_end: Union[int, float], + fnc: Callable[[int | float], int | float], + x_start: int | float, + x_end: int | float, steps: int = 100, ) -> float: diff --git a/maths/sieve_of_eratosthenes.py b/maths/sieve_of_eratosthenes.py index 47a086546..3cd6ce0b4 100644 --- a/maths/sieve_of_eratosthenes.py +++ b/maths/sieve_of_eratosthenes.py @@ -10,13 +10,12 @@ Reference: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes doctest provider: Bruno Simas Hadlich (https://github.com/brunohadlich) Also thanks to Dmitry (https://github.com/LizardWizzard) for finding the problem """ - +from __future__ import annotations import math -from typing import List -def prime_sieve(num: int) -> List[int]: +def prime_sieve(num: int) -> list[int]: """ Returns a list with all prime numbers up to n. diff --git a/maths/volume.py b/maths/volume.py index 41d2331db..51b2b9fc0 100644 --- a/maths/volume.py +++ b/maths/volume.py @@ -3,11 +3,12 @@ Find Volumes of Various Shapes. Wikipedia reference: https://en.wikipedia.org/wiki/Volume """ +from __future__ import annotations + from math import pi, pow -from typing import Union -def vol_cube(side_length: Union[int, float]) -> float: +def vol_cube(side_length: int | float) -> float: """ Calculate the Volume of a Cube. diff --git a/matrix/searching_in_sorted_matrix.py b/matrix/searching_in_sorted_matrix.py index ca6263a32..ae8136149 100644 --- a/matrix/searching_in_sorted_matrix.py +++ b/matrix/searching_in_sorted_matrix.py @@ -1,10 +1,8 @@ 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: int | float ) -> None: """ >>> search_in_a_sorted_matrix( diff --git a/other/date_to_weekday.py b/other/date_to_weekday.py index bb17130c0..9dc68666e 100644 --- a/other/date_to_weekday.py +++ b/other/date_to_weekday.py @@ -14,7 +14,7 @@ def date_to_weekday(inp_date: str) -> str: >>> date_to_weekday("1/1/2021") 'Friday' """ - day, month, year = [int(x) for x in inp_date.split("/")] + day, month, year = (int(x) for x in inp_date.split("/")) if year % 100 == 0: year = "00" new_base_date: str = f"{day}/{month}/{year%100} 0:0:0" diff --git a/other/davis–putnam–logemann–loveland.py b/other/davisb_putnamb_logemannb_loveland.py similarity index 94% rename from other/davis–putnam–logemann–loveland.py rename to other/davisb_putnamb_logemannb_loveland.py index d16de6dd9..00068930b 100644 --- a/other/davis–putnam–logemann–loveland.py +++ b/other/davisb_putnamb_logemannb_loveland.py @@ -8,9 +8,9 @@ conjunctive normal form, i.e, for solving the Conjunctive Normal Form SATisfiabi For more information about the algorithm: https://en.wikipedia.org/wiki/DPLL_algorithm """ +from __future__ import annotations import random -from typing import Dict, List class Clause: @@ -27,7 +27,7 @@ class Clause: True """ - def __init__(self, literals: List[int]) -> None: + def __init__(self, literals: list[int]) -> None: """ Represent the literals and an assignment in a clause." """ @@ -52,7 +52,7 @@ class Clause: """ return len(self.literals) - def assign(self, model: Dict[str, bool]) -> None: + def assign(self, model: dict[str, bool]) -> None: """ Assign values to literals of the clause as given by model. """ @@ -68,7 +68,7 @@ class Clause: value = not value self.literals[literal] = value - def evaluate(self, model: Dict[str, bool]) -> bool: + def evaluate(self, model: dict[str, bool]) -> bool: """ Evaluates the clause with the assignments in model. This has the following steps: @@ -97,7 +97,7 @@ class Formula: {{A1, A2, A3'}, {A5', A2', A1}} is ((A1 v A2 v A3') and (A5' v A2' v A1)) """ - def __init__(self, clauses: List[Clause]) -> None: + def __init__(self, clauses: list[Clause]) -> None: """ Represent the number of clauses and the clauses themselves. """ @@ -146,7 +146,7 @@ def generate_formula() -> Formula: return Formula(set(clauses)) -def generate_parameters(formula: Formula) -> (List[Clause], List[str]): +def generate_parameters(formula: Formula) -> (list[Clause], list[str]): """ Return the clauses and symbols from a formula. A symbol is the uncomplemented form of a literal. @@ -173,8 +173,8 @@ def generate_parameters(formula: Formula) -> (List[Clause], List[str]): def find_pure_symbols( - clauses: List[Clause], symbols: List[str], model: Dict[str, bool] -) -> (List[str], Dict[str, bool]): + clauses: list[Clause], symbols: list[str], model: dict[str, bool] +) -> (list[str], dict[str, bool]): """ Return pure symbols and their values to satisfy clause. Pure symbols are symbols in a formula that exist only @@ -225,8 +225,8 @@ def find_pure_symbols( def find_unit_clauses( - clauses: List[Clause], model: Dict[str, bool] -) -> (List[str], Dict[str, bool]): + clauses: list[Clause], model: dict[str, bool] +) -> (list[str], dict[str, bool]): """ Returns the unit symbols and their values to satisfy clause. Unit symbols are symbols in a formula that are: @@ -273,8 +273,8 @@ def find_unit_clauses( def dpll_algorithm( - clauses: List[Clause], symbols: List[str], model: Dict[str, bool] -) -> (bool, Dict[str, bool]): + clauses: list[Clause], symbols: list[str], model: dict[str, bool] +) -> (bool, dict[str, bool]): """ Returns the model if the formula is satisfiable, else None This has the following steps: diff --git a/other/lfu_cache.py b/other/lfu_cache.py index 40268242f..88167ac1f 100644 --- a/other/lfu_cache.py +++ b/other/lfu_cache.py @@ -1,4 +1,6 @@ -from typing import Callable, Optional +from __future__ import annotations + +from typing import Callable class DoubleLinkedListNode: @@ -119,7 +121,7 @@ class LFUCache: """ return key in self.cache - def get(self, key: int) -> Optional[int]: + def get(self, key: int) -> int | None: """ Returns the value for the input key and updates the Double Linked List. Returns None if key is not present in cache diff --git a/other/lru_cache.py b/other/lru_cache.py index 2a9d7e49b..b74c0a45c 100644 --- a/other/lru_cache.py +++ b/other/lru_cache.py @@ -1,4 +1,6 @@ -from typing import Callable, Optional +from __future__ import annotations + +from typing import Callable class DoubleLinkedListNode: @@ -125,7 +127,7 @@ class LRUCache: return key in self.cache - def get(self, key: int) -> Optional[int]: + def get(self, key: int) -> int | None: """ Returns the value for the input key and updates the Double Linked List. Returns None if key is not present in cache diff --git a/project_euler/problem_001/sol1.py b/project_euler/problem_001/sol1.py index 85ad32294..fcc24c86e 100644 --- a/project_euler/problem_001/sol1.py +++ b/project_euler/problem_001/sol1.py @@ -26,7 +26,7 @@ def solution(n: int = 1000) -> int: 0 """ - return sum([e for e in range(3, n) if e % 3 == 0 or e % 5 == 0]) + return sum(e for e in range(3, n) if e % 3 == 0 or e % 5 == 0) if __name__ == "__main__": diff --git a/project_euler/problem_001/sol5.py b/project_euler/problem_001/sol5.py index 7f0b0bd1b..3edc6f245 100644 --- a/project_euler/problem_001/sol5.py +++ b/project_euler/problem_001/sol5.py @@ -25,7 +25,7 @@ def solution(n: int = 1000) -> int: 83700 """ - return sum([i for i in range(n) if i % 3 == 0 or i % 5 == 0]) + return sum(i for i in range(n) if i % 3 == 0 or i % 5 == 0) if __name__ == "__main__": diff --git a/project_euler/problem_006/sol3.py b/project_euler/problem_006/sol3.py index c87931309..529f233c9 100644 --- a/project_euler/problem_006/sol3.py +++ b/project_euler/problem_006/sol3.py @@ -33,7 +33,7 @@ def solution(n: int = 100) -> int: 1582700 """ - sum_of_squares = sum([i * i for i in range(1, n + 1)]) + sum_of_squares = sum(i * i for i in range(1, n + 1)) square_of_sum = int(math.pow(sum(range(1, n + 1)), 2)) return square_of_sum - sum_of_squares diff --git a/project_euler/problem_008/sol2.py b/project_euler/problem_008/sol2.py index d2c1b4f7c..7f0540263 100644 --- a/project_euler/problem_008/sol2.py +++ b/project_euler/problem_008/sol2.py @@ -70,10 +70,7 @@ def solution(n: str = N) -> int: """ return max( - [ - reduce(lambda x, y: int(x) * int(y), n[i : i + 13]) - for i in range(len(n) - 12) - ] + reduce(lambda x, y: int(x) * int(y), n[i : i + 13]) for i in range(len(n) - 12) ) diff --git a/project_euler/problem_012/sol2.py b/project_euler/problem_012/sol2.py index 5ff0d8349..7578caa98 100644 --- a/project_euler/problem_012/sol2.py +++ b/project_euler/problem_012/sol2.py @@ -29,7 +29,7 @@ def triangle_number_generator(): def count_divisors(n): - return sum([2 for i in range(1, int(n ** 0.5) + 1) if n % i == 0 and i * i != n]) + return sum(2 for i in range(1, int(n ** 0.5) + 1) if n % i == 0 and i * i != n) def solution(): diff --git a/project_euler/problem_013/sol1.py b/project_euler/problem_013/sol1.py index 1ea08b12e..7a414a937 100644 --- a/project_euler/problem_013/sol1.py +++ b/project_euler/problem_013/sol1.py @@ -18,7 +18,7 @@ def solution(): """ file_path = os.path.join(os.path.dirname(__file__), "num.txt") with open(file_path) as file_hand: - return str(sum([int(line) for line in file_hand]))[:10] + return str(sum(int(line) for line in file_hand))[:10] if __name__ == "__main__": diff --git a/project_euler/problem_014/sol2.py b/project_euler/problem_014/sol2.py index 20ad96327..7ed68273b 100644 --- a/project_euler/problem_014/sol2.py +++ b/project_euler/problem_014/sol2.py @@ -25,10 +25,10 @@ that all starting numbers finish at 1. Which starting number, under one million, produces the longest chain? """ -from typing import List +from __future__ import annotations -def collatz_sequence(n: int) -> List[int]: +def collatz_sequence(n: int) -> list[int]: """Returns the Collatz sequence for n.""" sequence = [n] while n != 1: @@ -54,7 +54,7 @@ def solution(n: int = 1000000) -> int: 13255 """ - result = max([(len(collatz_sequence(i)), i) for i in range(1, n)]) + result = max((len(collatz_sequence(i)), i) for i in range(1, n)) return result[1] diff --git a/project_euler/problem_020/sol2.py b/project_euler/problem_020/sol2.py index 92e1e724a..676e96e78 100644 --- a/project_euler/problem_020/sol2.py +++ b/project_euler/problem_020/sol2.py @@ -28,7 +28,7 @@ def solution(num: int = 100) -> int: >>> solution(1) 1 """ - return sum([int(x) for x in str(factorial(num))]) + return sum(int(x) for x in str(factorial(num))) if __name__ == "__main__": diff --git a/project_euler/problem_021/sol1.py b/project_euler/problem_021/sol1.py index 3fac79156..353510ae8 100644 --- a/project_euler/problem_021/sol1.py +++ b/project_euler/problem_021/sol1.py @@ -41,11 +41,9 @@ def solution(n: int = 10000) -> int: 0 """ total = sum( - [ - i - for i in range(1, n) - if sum_of_divisors(sum_of_divisors(i)) == i and sum_of_divisors(i) != i - ] + i + for i in range(1, n) + if sum_of_divisors(sum_of_divisors(i)) == i and sum_of_divisors(i) != i ) return total diff --git a/project_euler/problem_033/sol1.py b/project_euler/problem_033/sol1.py index ba6e553d8..e0c9a058a 100644 --- a/project_euler/problem_033/sol1.py +++ b/project_euler/problem_033/sol1.py @@ -14,8 +14,9 @@ and denominator. If the product of these four fractions is given in its lowest common terms, find the value of the denominator. """ +from __future__ import annotations + from fractions import Fraction -from typing import List def is_digit_cancelling(num: int, den: int) -> bool: @@ -26,7 +27,7 @@ def is_digit_cancelling(num: int, den: int) -> bool: return False -def fraction_list(digit_len: int) -> List[str]: +def fraction_list(digit_len: int) -> list[str]: """ >>> fraction_list(2) ['16/64', '19/95', '26/65', '49/98'] diff --git a/project_euler/problem_036/sol1.py b/project_euler/problem_036/sol1.py index 13a749862..425c41221 100644 --- a/project_euler/problem_036/sol1.py +++ b/project_euler/problem_036/sol1.py @@ -14,11 +14,10 @@ base 10 and base 2. (Please note that the palindromic number, in either base, may not include leading zeros.) """ - -from typing import Union +from __future__ import annotations -def is_palindrome(n: Union[int, str]) -> bool: +def is_palindrome(n: int | str) -> bool: """ Return true if the input n is a palindrome. Otherwise return false. n can be an integer or a string. diff --git a/project_euler/problem_038/sol1.py b/project_euler/problem_038/sol1.py index 6d54f6df7..e4a6d09f8 100644 --- a/project_euler/problem_038/sol1.py +++ b/project_euler/problem_038/sol1.py @@ -37,8 +37,7 @@ a has 3 digits, etc... => 100 <= a < 334, candidate = a * 10^6 + 2a * 10^3 + 3a = 1002003 * a """ - -from typing import Union +from __future__ import annotations def is_9_pandigital(n: int) -> bool: @@ -55,7 +54,7 @@ def is_9_pandigital(n: int) -> bool: return len(s) == 9 and set(s) == set("123456789") -def solution() -> Union[int, None]: +def solution() -> int | None: """ Return the largest 1 to 9 pandigital 9-digital number that can be formed as the concatenated product of an integer with (1,2,...,n) where n > 1. diff --git a/project_euler/problem_049/sol1.py b/project_euler/problem_049/sol1.py index c0d0715be..dd2ef71a3 100644 --- a/project_euler/problem_049/sol1.py +++ b/project_euler/problem_049/sol1.py @@ -132,7 +132,7 @@ def solution(): for seq in passed: answer.add("".join([str(i) for i in seq])) - return max([int(x) for x in answer]) + return max(int(x) for x in answer) if __name__ == "__main__": diff --git a/project_euler/problem_050/sol1.py b/project_euler/problem_050/sol1.py index 7d142e5ff..cfb1911df 100644 --- a/project_euler/problem_050/sol1.py +++ b/project_euler/problem_050/sol1.py @@ -15,10 +15,10 @@ contains 21 terms, and is equal to 953. Which prime, below one-million, can be written as the sum of the most consecutive primes? """ -from typing import List +from __future__ import annotations -def prime_sieve(limit: int) -> List[int]: +def prime_sieve(limit: int) -> list[int]: """ Sieve of Erotosthenes Function to return all the prime numbers up to a number 'limit' diff --git a/project_euler/problem_051/sol1.py b/project_euler/problem_051/sol1.py index b160b5a2d..5f607e3ff 100644 --- a/project_euler/problem_051/sol1.py +++ b/project_euler/problem_051/sol1.py @@ -15,12 +15,12 @@ with this property. Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family. """ +from __future__ import annotations from collections import Counter -from typing import List -def prime_sieve(n: int) -> List[int]: +def prime_sieve(n: int) -> list[int]: """ Sieve of Erotosthenes Function to return all the prime numbers up to a certain number @@ -52,7 +52,7 @@ def prime_sieve(n: int) -> List[int]: return primes -def digit_replacements(number: int) -> List[List[int]]: +def digit_replacements(number: int) -> list[list[int]]: """ Returns all the possible families of digit replacements in a number which contains at least one repeating digit diff --git a/project_euler/problem_054/sol1.py b/project_euler/problem_054/sol1.py index d2fd810d1..9af7aef5a 100644 --- a/project_euler/problem_054/sol1.py +++ b/project_euler/problem_054/sol1.py @@ -135,7 +135,7 @@ class PokerHand: """Returns the self hand""" return self._hand - def compare_with(self, other: "PokerHand") -> str: + def compare_with(self, other: PokerHand) -> str: """ Determines the outcome of comparing self hand with other hand. Returns the output as 'Win', 'Loss', 'Tie' according to the rules of @@ -220,7 +220,7 @@ class PokerHand: else: return name + f", {high}" - def _compare_cards(self, other: "PokerHand") -> str: + def _compare_cards(self, other: PokerHand) -> str: # Enumerate gives us the index as well as the element of a list for index, card_value in enumerate(self._card_values): if card_value != other._card_values[index]: diff --git a/project_euler/problem_056/sol1.py b/project_euler/problem_056/sol1.py index 8eaa6e553..f1ec03c49 100644 --- a/project_euler/problem_056/sol1.py +++ b/project_euler/problem_056/sol1.py @@ -30,11 +30,9 @@ def solution(a: int = 100, b: int = 100) -> int: # RETURN the MAXIMUM from the list of SUMs of the list of INT converted from STR of # BASE raised to the POWER return max( - [ - sum([int(x) for x in str(base ** power)]) - for base in range(a) - for power in range(b) - ] + sum(int(x) for x in str(base ** power)) + for base in range(a) + for power in range(b) ) diff --git a/project_euler/problem_059/sol1.py b/project_euler/problem_059/sol1.py index 1f55029b2..b795dd243 100644 --- a/project_euler/problem_059/sol1.py +++ b/project_euler/problem_059/sol1.py @@ -25,23 +25,22 @@ file containing the encrypted ASCII codes, and the knowledge that the plain text must contain common English words, decrypt the message and find the sum of the ASCII values in the original text. """ - +from __future__ import annotations import string from itertools import cycle, product from pathlib import Path -from typing import List, Optional, Set, Tuple VALID_CHARS: str = ( string.ascii_letters + string.digits + string.punctuation + string.whitespace ) -LOWERCASE_INTS: List[int] = [ord(letter) for letter in string.ascii_lowercase] -VALID_INTS: Set[int] = {ord(char) for char in VALID_CHARS} +LOWERCASE_INTS: list[int] = [ord(letter) for letter in string.ascii_lowercase] +VALID_INTS: set[int] = {ord(char) for char in VALID_CHARS} -COMMON_WORDS: List[str] = ["the", "be", "to", "of", "and", "in", "that", "have"] +COMMON_WORDS: list[str] = ["the", "be", "to", "of", "and", "in", "that", "have"] -def try_key(ciphertext: List[int], key: Tuple[int, ...]) -> Optional[str]: +def try_key(ciphertext: list[int], key: tuple[int, ...]) -> str | None: """ Given an encrypted message and a possible 3-character key, decrypt the message. If the decrypted message contains a invalid character, i.e. not an ASCII letter, @@ -66,7 +65,7 @@ def try_key(ciphertext: List[int], key: Tuple[int, ...]) -> Optional[str]: return decoded -def filter_valid_chars(ciphertext: List[int]) -> List[str]: +def filter_valid_chars(ciphertext: list[int]) -> list[str]: """ Given an encrypted message, test all 3-character strings to try and find the key. Return a list of the possible decrypted messages. @@ -77,7 +76,7 @@ def filter_valid_chars(ciphertext: List[int]) -> List[str]: >>> text in filter_valid_chars(encoded) True """ - possibles: List[str] = [] + possibles: list[str] = [] for key in product(LOWERCASE_INTS, repeat=3): encoded = try_key(ciphertext, key) if encoded is not None: @@ -85,7 +84,7 @@ def filter_valid_chars(ciphertext: List[int]) -> List[str]: return possibles -def filter_common_word(possibles: List[str], common_word: str) -> List[str]: +def filter_common_word(possibles: list[str], common_word: str) -> list[str]: """ Given a list of possible decoded messages, narrow down the possibilities for checking for the presence of a specified common word. Only decoded messages @@ -106,8 +105,8 @@ def solution(filename: str = "p059_cipher.txt") -> int: >>> solution("test_cipher.txt") 3000 """ - ciphertext: List[int] - possibles: List[str] + ciphertext: list[int] + possibles: list[str] common_word: str decoded_text: str data: str = Path(__file__).parent.joinpath(filename).read_text(encoding="utf-8") @@ -121,7 +120,7 @@ def solution(filename: str = "p059_cipher.txt") -> int: break decoded_text = possibles[0] - return sum([ord(char) for char in decoded_text]) + return sum(ord(char) for char in decoded_text) if __name__ == "__main__": diff --git a/project_euler/problem_070/sol1.py b/project_euler/problem_070/sol1.py index 9d27119ba..e106800d5 100644 --- a/project_euler/problem_070/sol1.py +++ b/project_euler/problem_070/sol1.py @@ -28,10 +28,10 @@ References: Finding totients https://en.wikipedia.org/wiki/Euler's_totient_function#Euler's_product_formula """ -from typing import List +from __future__ import annotations -def get_totients(max_one: int) -> List[int]: +def get_totients(max_one: int) -> list[int]: """ Calculates a list of totients from 0 to max_one exclusive, using the definition of Euler's product formula. diff --git a/project_euler/problem_074/sol1.py b/project_euler/problem_074/sol1.py index 38d4e1439..a40a62903 100644 --- a/project_euler/problem_074/sol1.py +++ b/project_euler/problem_074/sol1.py @@ -66,7 +66,7 @@ def sum_digit_factorials(n: int) -> int: """ if n in CACHE_SUM_DIGIT_FACTORIALS: return CACHE_SUM_DIGIT_FACTORIALS[n] - ret = sum([DIGIT_FACTORIALS[let] for let in str(n)]) + ret = sum(DIGIT_FACTORIALS[let] for let in str(n)) CACHE_SUM_DIGIT_FACTORIALS[n] = ret return ret diff --git a/project_euler/problem_077/sol1.py b/project_euler/problem_077/sol1.py index e92992a90..214e25879 100644 --- a/project_euler/problem_077/sol1.py +++ b/project_euler/problem_077/sol1.py @@ -12,10 +12,10 @@ It is possible to write ten as the sum of primes in exactly five different ways: What is the first value which can be written as the sum of primes in over five thousand different ways? """ +from __future__ import annotations from functools import lru_cache from math import ceil -from typing import Optional, Set NUM_PRIMES = 100 @@ -30,7 +30,7 @@ for prime in range(3, ceil(NUM_PRIMES ** 0.5), 2): @lru_cache(maxsize=100) -def partition(number_to_partition: int) -> Set[int]: +def partition(number_to_partition: int) -> set[int]: """ Return a set of integers corresponding to unique prime partitions of n. The unique prime partitions can be represented as unique prime decompositions, @@ -47,7 +47,7 @@ def partition(number_to_partition: int) -> Set[int]: elif number_to_partition == 0: return {1} - ret: Set[int] = set() + ret: set[int] = set() prime: int sub: int @@ -60,7 +60,7 @@ def partition(number_to_partition: int) -> Set[int]: return ret -def solution(number_unique_partitions: int = 5000) -> Optional[int]: +def solution(number_unique_partitions: int = 5000) -> int | None: """ Return the smallest integer that can be written as the sum of primes in over m unique ways. diff --git a/project_euler/problem_080/sol1.py b/project_euler/problem_080/sol1.py index db69d7e84..517be3fc0 100644 --- a/project_euler/problem_080/sol1.py +++ b/project_euler/problem_080/sol1.py @@ -27,7 +27,7 @@ def solution() -> int: if len(str(sqrt_number)) > 1: answer += int(str(sqrt_number)[0]) sqrt_number = str(sqrt_number)[2:101] - answer += sum([int(x) for x in sqrt_number]) + answer += sum(int(x) for x in sqrt_number) return answer diff --git a/project_euler/problem_081/sol1.py b/project_euler/problem_081/sol1.py index afa143f23..aef6106b5 100644 --- a/project_euler/problem_081/sol1.py +++ b/project_euler/problem_081/sol1.py @@ -22,7 +22,7 @@ def solution(filename: str = "matrix.txt") -> int: >>> solution() 427337 """ - with open(os.path.join(os.path.dirname(__file__), filename), "r") as in_file: + with open(os.path.join(os.path.dirname(__file__), filename)) as in_file: data = in_file.read() grid = [[int(cell) for cell in row.split(",")] for row in data.strip().splitlines()] diff --git a/project_euler/problem_085/sol1.py b/project_euler/problem_085/sol1.py index 74e36b130..d0f297964 100644 --- a/project_euler/problem_085/sol1.py +++ b/project_euler/problem_085/sol1.py @@ -44,10 +44,9 @@ Solution: Reference: https://en.wikipedia.org/wiki/Triangular_number https://en.wikipedia.org/wiki/Quadratic_formula """ - +from __future__ import annotations from math import ceil, floor, sqrt -from typing import List def solution(target: int = 2000000) -> int: @@ -61,7 +60,7 @@ def solution(target: int = 2000000) -> int: >>> solution(2000000000) 86595 """ - triangle_numbers: List[int] = [0] + triangle_numbers: list[int] = [0] idx: int for idx in range(1, ceil(sqrt(target * 2) * 1.1)): diff --git a/project_euler/problem_089/sol1.py b/project_euler/problem_089/sol1.py index 11582aa4a..1c4e2600f 100644 --- a/project_euler/problem_089/sol1.py +++ b/project_euler/problem_089/sol1.py @@ -125,7 +125,7 @@ def solution(roman_numerals_filename: str = "/p089_roman.txt") -> int: savings = 0 - file1 = open(os.path.dirname(__file__) + roman_numerals_filename, "r") + file1 = open(os.path.dirname(__file__) + roman_numerals_filename) lines = file1.readlines() for line in lines: original = line.strip() diff --git a/project_euler/problem_101/sol1.py b/project_euler/problem_101/sol1.py index e66316090..553f8f442 100644 --- a/project_euler/problem_101/sol1.py +++ b/project_euler/problem_101/sol1.py @@ -41,11 +41,11 @@ Consider the following tenth degree polynomial generating function: Find the sum of FITs for the BOPs. """ +from __future__ import annotations +from typing import Callable, Union -from typing import Callable, List, Union - -Matrix = List[List[Union[float, int]]] +Matrix = list[list[Union[float, int]]] def solve(matrix: Matrix, vector: Matrix) -> Matrix: @@ -78,9 +78,9 @@ def solve(matrix: Matrix, vector: Matrix) -> Matrix: col = 0 while row < size and col < size: # pivoting - pivot_row = max( - [(abs(augmented[row2][col]), row2) for row2 in range(col, size)] - )[1] + pivot_row = max((abs(augmented[row2][col]), row2) for row2 in range(col, size))[ + 1 + ] if augmented[pivot_row][col] == 0: col += 1 continue @@ -109,7 +109,7 @@ def solve(matrix: Matrix, vector: Matrix) -> Matrix: ] -def interpolate(y_list: List[int]) -> Callable[[int], int]: +def interpolate(y_list: list[int]) -> Callable[[int], int]: """ Given a list of data points (1,y0),(2,y1), ..., return a function that interpolates the data points. We find the coefficients of the interpolating @@ -195,9 +195,9 @@ def solution(func: Callable[[int], int] = question_function, order: int = 10) -> >>> solution(lambda n: n ** 3, 3) 74 """ - data_points: List[int] = [func(x_val) for x_val in range(1, order + 1)] + data_points: list[int] = [func(x_val) for x_val in range(1, order + 1)] - polynomials: List[Callable[[int], int]] = [ + polynomials: list[Callable[[int], int]] = [ interpolate(data_points[:max_coeff]) for max_coeff in range(1, order + 1) ] diff --git a/project_euler/problem_102/sol1.py b/project_euler/problem_102/sol1.py index 00af72665..4f6e6361e 100644 --- a/project_euler/problem_102/sol1.py +++ b/project_euler/problem_102/sol1.py @@ -18,12 +18,12 @@ the number of triangles for which the interior contains the origin. NOTE: The first two examples in the file represent the triangles in the example given above. """ +from __future__ import annotations from pathlib import Path -from typing import List, Tuple -def vector_product(point1: Tuple[int, int], point2: Tuple[int, int]) -> int: +def vector_product(point1: tuple[int, int], point2: tuple[int, int]) -> int: """ Return the 2-d vector product of two vectors. >>> vector_product((1, 2), (-5, 0)) @@ -43,9 +43,9 @@ def contains_origin(x1: int, y1: int, x2: int, y2: int, x3: int, y3: int) -> boo >>> contains_origin(-175, 41, -421, -714, 574, -645) False """ - point_a: Tuple[int, int] = (x1, y1) - point_a_to_b: Tuple[int, int] = (x2 - x1, y2 - y1) - point_a_to_c: Tuple[int, int] = (x3 - x1, y3 - y1) + point_a: tuple[int, int] = (x1, y1) + point_a_to_b: tuple[int, int] = (x2 - x1, y2 - y1) + point_a_to_c: tuple[int, int] = (x3 - x1, y3 - y1) a: float = -vector_product(point_a, point_a_to_b) / vector_product( point_a_to_c, point_a_to_b ) @@ -64,12 +64,12 @@ def solution(filename: str = "p102_triangles.txt") -> int: """ data: str = Path(__file__).parent.joinpath(filename).read_text(encoding="utf-8") - triangles: List[List[int]] = [] + triangles: list[list[int]] = [] for line in data.strip().split("\n"): triangles.append([int(number) for number in line.split(",")]) ret: int = 0 - triangle: List[int] + triangle: list[int] for triangle in triangles: ret += contains_origin(*triangle) diff --git a/project_euler/problem_107/sol1.py b/project_euler/problem_107/sol1.py index 80a10e499..6a411a114 100644 --- a/project_euler/problem_107/sol1.py +++ b/project_euler/problem_107/sol1.py @@ -27,11 +27,12 @@ Solution: We use Prim's algorithm to find a Minimum Spanning Tree. Reference: https://en.wikipedia.org/wiki/Prim%27s_algorithm """ +from __future__ import annotations import os -from typing import Dict, List, Mapping, Set, Tuple +from typing import Mapping -EdgeT = Tuple[int, int] +EdgeT = tuple[int, int] class Graph: @@ -39,9 +40,9 @@ class Graph: A class representing an undirected weighted graph. """ - def __init__(self, vertices: Set[int], edges: Mapping[EdgeT, int]) -> None: - self.vertices: Set[int] = vertices - self.edges: Dict[EdgeT, int] = { + def __init__(self, vertices: set[int], edges: Mapping[EdgeT, int]) -> None: + self.vertices: set[int] = vertices + self.edges: dict[EdgeT, int] = { (min(edge), max(edge)): weight for edge, weight in edges.items() } @@ -59,7 +60,7 @@ class Graph: self.vertices.add(edge[1]) self.edges[(min(edge), max(edge))] = weight - def prims_algorithm(self) -> "Graph": + def prims_algorithm(self) -> Graph: """ Run Prim's algorithm to find the minimum spanning tree. Reference: https://en.wikipedia.org/wiki/Prim%27s_algorithm @@ -98,13 +99,13 @@ def solution(filename: str = "p107_network.txt") -> int: """ script_dir: str = os.path.abspath(os.path.dirname(__file__)) network_file: str = os.path.join(script_dir, filename) - adjacency_matrix: List[List[str]] - edges: Dict[EdgeT, int] = dict() - data: List[str] + adjacency_matrix: list[list[str]] + edges: dict[EdgeT, int] = dict() + data: list[str] edge1: int edge2: int - with open(network_file, "r") as f: + with open(network_file) as f: data = f.read().strip().split("\n") adjaceny_matrix = [line.split(",") for line in data] diff --git a/project_euler/problem_119/sol1.py b/project_euler/problem_119/sol1.py index 7f343ac24..60ec16cda 100644 --- a/project_euler/problem_119/sol1.py +++ b/project_euler/problem_119/sol1.py @@ -23,7 +23,7 @@ def digit_sum(n: int) -> int: >>> digit_sum(78910) 25 """ - return sum([int(digit) for digit in str(n)]) + return sum(int(digit) for digit in str(n)) def solution(n: int = 30) -> int: diff --git a/project_euler/problem_123/sol1.py b/project_euler/problem_123/sol1.py index 85350c8ba..919132227 100644 --- a/project_euler/problem_123/sol1.py +++ b/project_euler/problem_123/sol1.py @@ -37,8 +37,9 @@ So it could be simplified as, r = 2pn when n is odd r = 2 when n is even. """ +from __future__ import annotations -from typing import Dict, Generator +from typing import Generator def sieve() -> Generator[int, None, None]: @@ -60,7 +61,7 @@ def sieve() -> Generator[int, None, None]: >>> next(primes) 13 """ - factor_map: Dict[int, int] = {} + factor_map: dict[int, int] = {} prime = 2 while True: factor = factor_map.pop(prime, None) diff --git a/project_euler/problem_180/sol1.py b/project_euler/problem_180/sol1.py index 6112db2ea..f7c097323 100644 --- a/project_euler/problem_180/sol1.py +++ b/project_euler/problem_180/sol1.py @@ -44,11 +44,10 @@ we get the right numerator and denominator. Reference: https://en.wikipedia.org/wiki/Fermat%27s_Last_Theorem """ - +from __future__ import annotations from fractions import Fraction from math import gcd, sqrt -from typing import Tuple def is_sq(number: int) -> bool: @@ -68,7 +67,7 @@ def is_sq(number: int) -> bool: def add_three( x_num: int, x_den: int, y_num: int, y_den: int, z_num: int, z_den: int -) -> Tuple[int, int]: +) -> tuple[int, int]: """ Given the numerators and denominators of three fractions, return the numerator and denominator of their sum in lowest form. @@ -100,7 +99,7 @@ def solution(order: int = 35) -> int: unique_s: set = set() hcf: int total: Fraction = Fraction(0) - fraction_sum: Tuple[int, int] + fraction_sum: tuple[int, int] for x_num in range(1, order + 1): for x_den in range(x_num + 1, order + 1): diff --git a/project_euler/problem_203/sol1.py b/project_euler/problem_203/sol1.py index 227b476da..030cf12f2 100644 --- a/project_euler/problem_203/sol1.py +++ b/project_euler/problem_203/sol1.py @@ -27,12 +27,12 @@ Pascal's triangle. References: - https://en.wikipedia.org/wiki/Pascal%27s_triangle """ +from __future__ import annotations import math -from typing import List, Set -def get_pascal_triangle_unique_coefficients(depth: int) -> Set[int]: +def get_pascal_triangle_unique_coefficients(depth: int) -> set[int]: """ Returns the unique coefficients of a Pascal's triangle of depth "depth". @@ -61,7 +61,7 @@ def get_pascal_triangle_unique_coefficients(depth: int) -> Set[int]: return coefficients -def get_primes_squared(max_number: int) -> List[int]: +def get_primes_squared(max_number: int) -> list[int]: """ Calculates all primes between 2 and round(sqrt(max_number)) and returns them squared up. @@ -92,7 +92,7 @@ def get_primes_squared(max_number: int) -> List[int]: def get_squared_primes_to_use( - num_to_look: int, squared_primes: List[int], previous_index: int + num_to_look: int, squared_primes: list[int], previous_index: int ) -> int: """ Returns an int indicating the last index on which squares of primes @@ -128,8 +128,8 @@ def get_squared_primes_to_use( def get_squarefree( - unique_coefficients: Set[int], squared_primes: List[int] -) -> Set[int]: + unique_coefficients: set[int], squared_primes: list[int] +) -> set[int]: """ Calculates the squarefree numbers inside unique_coefficients given a list of square of primes. 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 100644 --- 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 a49d037d6..17409108a 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 ) -> None: """ This function calculates the average of the waiting & turnaround times diff --git a/searches/binary_search.py b/searches/binary_search.py index 35e0dd059..0966cd8de 100644 --- a/searches/binary_search.py +++ b/searches/binary_search.py @@ -9,12 +9,13 @@ python3 -m doctest -v binary_search.py For manual testing run: python3 binary_search.py """ +from __future__ import annotations + import bisect -from typing import List, Optional def bisect_left( - sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 + sorted_collection: list[int], item: int, lo: int = 0, hi: int = -1 ) -> int: """ Locates the first element in a sorted array that is larger or equal to a given @@ -60,7 +61,7 @@ def bisect_left( def bisect_right( - sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 + sorted_collection: list[int], item: int, lo: int = 0, hi: int = -1 ) -> int: """ Locates the first element in a sorted array that is larger than a given value. @@ -105,7 +106,7 @@ def bisect_right( def insort_left( - sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 + sorted_collection: list[int], item: int, lo: int = 0, hi: int = -1 ) -> None: """ Inserts a given value into a sorted array before other values with the same value. @@ -148,7 +149,7 @@ def insort_left( def insort_right( - sorted_collection: List[int], item: int, lo: int = 0, hi: int = -1 + sorted_collection: list[int], item: int, lo: int = 0, hi: int = -1 ) -> None: """ Inserts a given value into a sorted array after other values with the same value. @@ -190,7 +191,7 @@ def insort_right( sorted_collection.insert(bisect_right(sorted_collection, item, lo, hi), item) -def binary_search(sorted_collection: List[int], item: int) -> Optional[int]: +def binary_search(sorted_collection: list[int], item: int) -> int | None: """Pure implementation of binary search algorithm in Python Be careful collection must be ascending sorted, otherwise result will be @@ -228,7 +229,7 @@ def binary_search(sorted_collection: List[int], item: int) -> Optional[int]: return None -def binary_search_std_lib(sorted_collection: List[int], item: int) -> Optional[int]: +def binary_search_std_lib(sorted_collection: list[int], item: int) -> int | None: """Pure implementation of binary search algorithm in Python using stdlib Be careful collection must be ascending sorted, otherwise result will be @@ -258,8 +259,8 @@ def binary_search_std_lib(sorted_collection: List[int], item: int) -> Optional[i def binary_search_by_recursion( - sorted_collection: List[int], item: int, left: int, right: int -) -> Optional[int]: + sorted_collection: list[int], item: int, left: int, right: int +) -> int | None: """Pure implementation of binary search algorithm in Python by recursion diff --git a/searches/fibonacci_search.py b/searches/fibonacci_search.py index ac8ecc99a..55fc05d39 100644 --- a/searches/fibonacci_search.py +++ b/searches/fibonacci_search.py @@ -13,7 +13,7 @@ python3 fibonacci_search.py from functools import lru_cache -@lru_cache() +@lru_cache def fibonacci(k: int) -> int: """Finds fibonacci number in index k. diff --git a/searches/ternary_search.py b/searches/ternary_search.py index 9422a4ccb..01e437723 100644 --- a/searches/ternary_search.py +++ b/searches/ternary_search.py @@ -6,7 +6,7 @@ This is a type of divide and conquer algorithm which divides the search space in Time Complexity : O(log3 N) Space Complexity : O(1) """ -from typing import List +from __future__ import annotations # This is the precision for this function which can be altered. # It is recommended for users to keep this number greater than or equal to 10. @@ -16,7 +16,7 @@ precision = 10 # This is the linear search that will occur after the search space has become smaller. -def lin_search(left: int, right: int, array: List[int], target: int) -> int: +def lin_search(left: int, right: int, array: list[int], target: int) -> int: """Perform linear search in list. Returns -1 if element is not found. Parameters @@ -58,7 +58,7 @@ def lin_search(left: int, right: int, array: List[int], target: int) -> int: return -1 -def ite_ternary_search(array: List[int], target: int) -> int: +def ite_ternary_search(array: list[int], target: int) -> int: """Iterative method of the ternary search algorithm. >>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42] >>> ite_ternary_search(test_list, 3) @@ -110,7 +110,7 @@ def ite_ternary_search(array: List[int], target: int) -> int: return -1 -def rec_ternary_search(left: int, right: int, array: List[int], target: int) -> int: +def rec_ternary_search(left: int, right: int, array: list[int], target: int) -> int: """Recursive method of the ternary search algorithm. >>> test_list = [0, 1, 2, 8, 13, 17, 19, 32, 42] diff --git a/sorts/bitonic_sort.py b/sorts/bitonic_sort.py index c718973e5..201fecd2c 100644 --- a/sorts/bitonic_sort.py +++ b/sorts/bitonic_sort.py @@ -3,10 +3,10 @@ Python program for Bitonic Sort. Note that this program works only when size of input is a power of 2. """ -from typing import List +from __future__ import annotations -def comp_and_swap(array: List[int], index1: int, index2: int, direction: int) -> None: +def comp_and_swap(array: list[int], index1: int, index2: int, direction: int) -> None: """Compare the value at given index1 and index2 of the array and swap them as per the given direction. @@ -37,7 +37,7 @@ def comp_and_swap(array: List[int], index1: int, index2: int, direction: int) -> array[index1], array[index2] = array[index2], array[index1] -def bitonic_merge(array: List[int], low: int, length: int, direction: int) -> None: +def bitonic_merge(array: list[int], low: int, length: int, direction: int) -> None: """ It recursively sorts a bitonic sequence in ascending order, if direction = 1, and in descending if direction = 0. @@ -61,7 +61,7 @@ def bitonic_merge(array: List[int], low: int, length: int, direction: int) -> No bitonic_merge(array, low + middle, middle, direction) -def bitonic_sort(array: List[int], low: int, length: int, direction: int) -> None: +def bitonic_sort(array: list[int], low: int, length: int, direction: int) -> None: """ This function first produces a bitonic sequence by recursively sorting its two halves in opposite sorting orders, and then calls bitonic_merge to make them in the diff --git a/sorts/bucket_sort.py b/sorts/bucket_sort.py index 1ac76774f..58242a1cb 100644 --- a/sorts/bucket_sort.py +++ b/sorts/bucket_sort.py @@ -27,7 +27,7 @@ If k = O(n), time complexity is O(n) Source: https://en.wikipedia.org/wiki/Bucket_sort """ -from typing import List +from __future__ import annotations def bucket_sort(my_list: list) -> list: @@ -52,7 +52,7 @@ def bucket_sort(my_list: list) -> list: return [] min_value, max_value = min(my_list), max(my_list) bucket_count = int(max_value - min_value) + 1 - buckets: List[list] = [[] for _ in range(bucket_count)] + buckets: list[list] = [[] for _ in range(bucket_count)] for i in range(len(my_list)): buckets[(int(my_list[i] - min_value) // bucket_count)].append(my_list[i]) diff --git a/sorts/msd_radix_sort.py b/sorts/msd_radix_sort.py index 4c3cea30e..3cdec4bd0 100644 --- a/sorts/msd_radix_sort.py +++ b/sorts/msd_radix_sort.py @@ -4,10 +4,10 @@ It used the binary representation of the integers to sort them. https://en.wikipedia.org/wiki/Radix_sort """ -from typing import List +from __future__ import annotations -def msd_radix_sort(list_of_ints: List[int]) -> List[int]: +def msd_radix_sort(list_of_ints: list[int]) -> list[int]: """ Implementation of the MSD radix sort algorithm. Only works with positive integers @@ -36,7 +36,7 @@ def msd_radix_sort(list_of_ints: List[int]) -> List[int]: return _msd_radix_sort(list_of_ints, most_bits) -def _msd_radix_sort(list_of_ints: List[int], bit_position: int) -> List[int]: +def _msd_radix_sort(list_of_ints: list[int], bit_position: int) -> list[int]: """ Sort the given list based on the bit at bit_position. Numbers with a 0 at that position will be at the start of the list, numbers with a @@ -74,7 +74,7 @@ def _msd_radix_sort(list_of_ints: List[int], bit_position: int) -> List[int]: return res -def msd_radix_sort_inplace(list_of_ints: List[int]): +def msd_radix_sort_inplace(list_of_ints: list[int]): """ Inplace implementation of the MSD radix sort algorithm. Sorts based on the binary representation of the integers. @@ -109,7 +109,7 @@ def msd_radix_sort_inplace(list_of_ints: List[int]): def _msd_radix_sort_inplace( - list_of_ints: List[int], bit_position: int, begin_index: int, end_index: int + list_of_ints: list[int], bit_position: int, begin_index: int, end_index: int ): """ Sort the given list based on the bit at bit_position. Numbers with a diff --git a/sorts/patience_sort.py b/sorts/patience_sort.py index 87f5a4078..845db5174 100644 --- a/sorts/patience_sort.py +++ b/sorts/patience_sort.py @@ -1,7 +1,8 @@ +from __future__ import annotations + from bisect import bisect_left from functools import total_ordering from heapq import merge -from typing import List """ A pure Python implementation of the patience sort algorithm @@ -44,7 +45,7 @@ def patience_sort(collection: list) -> list: >>> patience_sort([-3, -17, -48]) [-48, -17, -3] """ - stacks: List[Stack] = [] + stacks: list[Stack] = [] # sort into stacks for element in collection: new_stacks = Stack([element]) @@ -55,7 +56,7 @@ def patience_sort(collection: list) -> list: stacks.append(new_stacks) # use a heap-based merge to merge stack efficiently - collection[:] = merge(*[reversed(stack) for stack in stacks]) + collection[:] = merge(*(reversed(stack) for stack in stacks)) return collection diff --git a/sorts/pigeon_sort.py b/sorts/pigeon_sort.py index 3d81f0643..3e6d4c09c 100644 --- a/sorts/pigeon_sort.py +++ b/sorts/pigeon_sort.py @@ -9,10 +9,10 @@ For manual testing run: python pigeon_sort.py """ -from typing import List +from __future__ import annotations -def pigeon_sort(array: List[int]) -> List[int]: +def pigeon_sort(array: list[int]) -> list[int]: """ Implementation of pigeon hole sort algorithm :param array: Collection of comparable items diff --git a/sorts/quick_sort.py b/sorts/quick_sort.py index 6f51f6eca..b099c7886 100644 --- a/sorts/quick_sort.py +++ b/sorts/quick_sort.py @@ -7,7 +7,7 @@ python3 -m doctest -v quick_sort.py For manual testing run: python3 quick_sort.py """ -from typing import List +from __future__ import annotations def quick_sort(collection: list) -> list: @@ -27,8 +27,8 @@ def quick_sort(collection: list) -> list: if len(collection) < 2: return collection pivot = collection.pop() # Use the last element as the first pivot - greater: List[int] = [] # All elements greater than pivot - lesser: List[int] = [] # All elements less than or equal to pivot + greater: list[int] = [] # All elements greater than pivot + lesser: list[int] = [] # All elements less than or equal to pivot for element in collection: (greater if element > pivot else lesser).append(element) return quick_sort(lesser) + [pivot] + quick_sort(greater) diff --git a/sorts/radix_sort.py b/sorts/radix_sort.py index b802b5278..e433bc507 100644 --- a/sorts/radix_sort.py +++ b/sorts/radix_sort.py @@ -9,10 +9,8 @@ python radix_sort.py """ from __future__ import annotations -from typing import List - -def radix_sort(list_of_ints: List[int]) -> List[int]: +def radix_sort(list_of_ints: list[int]) -> list[int]: """ Examples: >>> radix_sort([0, 5, 3, 2, 2]) @@ -30,7 +28,7 @@ def radix_sort(list_of_ints: List[int]) -> List[int]: max_digit = max(list_of_ints) while placement <= max_digit: # declare and initialize empty buckets - buckets: List[list] = [list() for _ in range(RADIX)] + buckets: list[list] = [list() for _ in range(RADIX)] # split list_of_ints between the buckets for i in list_of_ints: tmp = int((i / placement) % RADIX) diff --git a/sorts/recursive_insertion_sort.py b/sorts/recursive_insertion_sort.py index 89f88b4a9..ab2716f8e 100644 --- a/sorts/recursive_insertion_sort.py +++ b/sorts/recursive_insertion_sort.py @@ -1,11 +1,8 @@ """ A recursive implementation of the insertion sort algorithm """ - from __future__ import annotations -from typing import List - def rec_insertion_sort(collection: list, n: int): """ @@ -72,6 +69,6 @@ def insert_next(collection: list, index: int): if __name__ == "__main__": numbers = input("Enter integers separated by spaces: ") - number_list: List[int] = [int(num) for num in numbers.split()] + number_list: list[int] = [int(num) for num in numbers.split()] rec_insertion_sort(number_list, len(number_list)) print(number_list) diff --git a/sorts/slowsort.py b/sorts/slowsort.py index 53bb14554..a5f4e873e 100644 --- a/sorts/slowsort.py +++ b/sorts/slowsort.py @@ -8,13 +8,10 @@ in their paper Pessimal Algorithms and Simplexity Analysis Source: https://en.wikipedia.org/wiki/Slowsort """ - -from typing import Optional +from __future__ import annotations -def slowsort( - sequence: list, start: Optional[int] = None, end: Optional[int] = None -) -> None: +def slowsort(sequence: list, start: int | None = None, end: int | None = None) -> None: """ Sorts sequence[start..end] (both inclusive) in-place. start defaults to 0 if not given. diff --git a/strings/aho_corasick.py b/strings/aho_corasick.py index 712cb338a..b9a6a8072 100644 --- a/strings/aho_corasick.py +++ b/strings/aho_corasick.py @@ -1,5 +1,6 @@ +from __future__ import annotations + from collections import deque -from typing import Dict, List, Union class Automaton: @@ -13,7 +14,7 @@ class Automaton: self.add_keyword(keyword) self.set_fail_transitions() - def find_next_state(self, current_state: int, char: str) -> Union[int, None]: + def find_next_state(self, current_state: int, char: str) -> int | None: for state in self.adlist[current_state]["next_states"]: if char == self.adlist[state]["value"]: return state @@ -63,7 +64,7 @@ class Automaton: + self.adlist[self.adlist[child]["fail_state"]]["output"] ) - def search_in(self, string: str) -> Dict[str, List[int]]: + def search_in(self, string: str) -> dict[str, list[int]]: """ >>> A = Automaton(["what", "hat", "ver", "er"]) >>> A.search_in("whatever, err ... , wherever") diff --git a/strings/boyer_moore_search.py b/strings/boyer_moore_search.py index a3e6cf614..8d8ff22f6 100644 --- a/strings/boyer_moore_search.py +++ b/strings/boyer_moore_search.py @@ -17,7 +17,7 @@ Time Complexity : O(n/m) n=length of main string m=length of pattern string """ -from typing import List +from __future__ import annotations class BoyerMooreSearch: @@ -59,7 +59,7 @@ class BoyerMooreSearch: return currentPos + i return -1 - def bad_character_heuristic(self) -> List[int]: + def bad_character_heuristic(self) -> list[int]: # searches pattern in text and returns index positions positions = [] for i in range(self.textLen - self.patLen + 1): diff --git a/strings/knuth_morris_pratt.py b/strings/knuth_morris_pratt.py index a205ce37e..a488c171a 100644 --- a/strings/knuth_morris_pratt.py +++ b/strings/knuth_morris_pratt.py @@ -1,4 +1,4 @@ -from typing import List +from __future__ import annotations def kmp(pattern: str, text: str) -> bool: @@ -36,7 +36,7 @@ def kmp(pattern: str, text: str) -> bool: return False -def get_failure_array(pattern: str) -> List[int]: +def get_failure_array(pattern: str) -> list[int]: """ Calculates the new index we should go to if we fail a comparison :param pattern: diff --git a/web_programming/emails_from_url.py b/web_programming/emails_from_url.py index 0571ac331..afaee5bbe 100644 --- a/web_programming/emails_from_url.py +++ b/web_programming/emails_from_url.py @@ -1,4 +1,6 @@ """Get the site emails from URL.""" +from __future__ import annotations + __author__ = "Muhammad Umer Farooq" __license__ = "MIT" __version__ = "1.0.0" @@ -8,7 +10,6 @@ __status__ = "Alpha" import re from html.parser import HTMLParser -from typing import Optional from urllib import parse import requests @@ -20,7 +21,7 @@ class Parser(HTMLParser): self.urls: list[str] = [] self.domain = domain - def handle_starttag(self, tag: str, attrs: list[tuple[str, Optional[str]]]) -> None: + def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: """ This function parse html to take takes url from tags """ diff --git a/web_programming/fetch_github_info.py b/web_programming/fetch_github_info.py index c9198460f..aa4e1d7b1 100644 --- a/web_programming/fetch_github_info.py +++ b/web_programming/fetch_github_info.py @@ -17,8 +17,10 @@ with your token:: #!/usr/bin/env bash export USER_TOKEN="" """ +from __future__ import annotations + import os -from typing import Any, Dict +from typing import Any import requests @@ -31,7 +33,7 @@ AUTHENTICATED_USER_ENDPOINT = BASE_URL + "/user" USER_TOKEN = os.environ.get("USER_TOKEN", "") -def fetch_github_info(auth_token: str) -> Dict[Any, Any]: +def fetch_github_info(auth_token: str) -> dict[Any, Any]: """ Fetch GitHub info of a user using the requests module """