diff --git a/DIRECTORY.md b/DIRECTORY.md index 41485f6f..0c00d5ca 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 7b5006a1..6e8d1d04 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 5bb63175..b488b1bb 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 66cde4b7..490e0687 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 146bb0aa..1a820538 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 76462837..bde60f03 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 a0032c5c..ff8a53e0 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 99db4ea4..c465fc54 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 3956b21a..8bda4b58 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 7be1ea35..19751b34 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 8e6613e0..6e9b31bd 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 dda29b47..6e310131 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 29b8d819..b8ace597 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 a8651c5c..c12aa6c3 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 cd2a8f41..2860880d 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 593fa52d..698dedcc 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 f695b8f7..8348544c 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 b50147ac..54d861dd 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 7df674cb..22b0cad7 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 4f7f50a9..a9d0f65c 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 70cdf25a..9cc99b1e 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 321baa3a..079fb4d0 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 4b2f76c7..8cd9fab5 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 7e3705b8..89477914 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 a23a8104..4ff90be0 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 01d09964..3b84f97f 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 b6cc4de1..8f37a53c 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 8c684599..0024eb5c 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 78db4a91..a7755643 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 e0d3e4d4..1ab13777 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 575b157e..65dccf24 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 a05e28a7..4bdf4e33 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 7857880d..de9e9d60 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 9066db29..94329cb4 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 6b202adb..d169e0e7 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 de971a71..e27757f2 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 a09dcc92..0526b139 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 1607244f..173a88ab 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 fd9e6eec..f4422de5 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 fe838268..f404c525 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 65a70e46..550439ed 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 0ddc2272..f584f5cb 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 417a383f..b5944138 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 96ec6b8a..43dd4618 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 c46f228e..f83d5607 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 8f06e619..ee0b4460 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 2a4baf9d..51ea353b 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 0b9c9d45..85b59a94 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 245d39b3..c6241215 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 9c096f67..63f8dbb2 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 f6e81a30..666ad1a3 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 46a46941..628080ce 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 f94f83ed..e60f28bf 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 e4e685bb..ac673d7e 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 41bffa9f..66e737c1 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 9cd6dd0f..db0ef8e7 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 d6d6b2ac..0f654a51 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 a68b5602..78047c5d 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 729d8957..071f1cd6 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 9b84ab21..27e4f0b1 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 305db01e..7c626429 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 48f8ab1a..697a8c63 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 5d74a6db..f20a503c 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 d5e80247..d49e65b9 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 f21a87a7..85d93701 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 c3444c36..d924ee3d 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 0f512914..672405b7 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 2b341701..fa182aa2 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 81014120..bb77fd05 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 756443ea..18a36c3b 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 5e2f8201..74aeb913 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 af845c91..ec1b9f9e 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 2d01e414..ce093242 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 e02e307f..274c434a 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 497bf0c3..cd1ec157 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 43bb3860..498c28f3 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 6e0da637..a2078161 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 e7087636..72afd40a 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 90e4913c..e36f763d 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 1d386b44..c4d98627 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 593cb5c8..c6f9b4ed 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 cde12f5d..55aa587a 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 87184a76..577c41a4 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 47a08654..3cd6ce0b 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 41d2331d..51b2b9fc 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 ca6263a3..ae813614 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 bb17130c..9dc68666 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 d16de6dd..00068930 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 40268242..88167ac1 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 2a9d7e49..b74c0a45 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 85ad3229..fcc24c86 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 7f0b0bd1..3edc6f24 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 c8793130..529f233c 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 d2c1b4f7..7f054026 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 5ff0d834..7578caa9 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 1ea08b12..7a414a93 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 20ad9632..7ed68273 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 92e1e724..676e96e7 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 3fac7915..353510ae 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 ba6e553d..e0c9a058 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 13a74986..425c4122 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 6d54f6df..e4a6d09f 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 c0d0715b..dd2ef71a 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 7d142e5f..cfb1911d 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 b160b5a2..5f607e3f 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 d2fd810d..9af7aef5 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 8eaa6e55..f1ec03c4 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 1f55029b..b795dd24 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 9d27119b..e106800d 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 38d4e143..a40a6290 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 e92992a9..214e2587 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 db69d7e8..517be3fc 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 afa143f2..aef6106b 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 74e36b13..d0f29796 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 11582aa4..1c4e2600 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 e6631609..553f8f44 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 00af7266..4f6e6361 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 80a10e49..6a411a11 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 7f343ac2..60ec16cd 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 85350c8b..91913222 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 6112db2e..f7c09732 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 227b476d..030cf12f 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 b51fc9fe..c5f61720 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 4a79301c..e8d54dd9 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 a49d037d..17409108 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 35e0dd05..0966cd8d 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 ac8ecc99..55fc05d3 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 9422a4cc..01e43772 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 c718973e..201fecd2 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 1ac76774..58242a1c 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 4c3cea30..3cdec4bd 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 87f5a407..845db517 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 3d81f064..3e6d4c09 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 6f51f6ec..b099c788 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 b802b527..e433bc50 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 89f88b4a..ab2716f8 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 53bb1455..a5f4e873 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 712cb338..b9a6a807 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 a3e6cf61..8d8ff22f 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 a205ce37..a488c171 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 0571ac33..afaee5bb 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 c9198460..aa4e1d7b 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 """